Browse Source

made the buffer location seperate

OpenShift guest 12 years ago
parent
commit
4c68bf6b8e

File diff suppressed because it is too large
+ 50 - 2508
src/renderers/WebGLRenderer2.js


+ 200 - 0
src/renderers/webgl/Objects/LineRenderer.js

@@ -0,0 +1,200 @@
+
+
+THREE.LineRenderer = function(lowlevelrenderer, info){
+	THREE.Object3DRenderer.call( this, lowlevelrenderer, info );
+};
+
+
+THREE.LineRenderer.prototype = Object.create( THREE.Object3DRenderer.prototype );
+
+THREE.LineRenderer.prototype.createBuffers = function( geometry ) {
+	
+	var renderer = this.renderer;
+	geometry.__webglVertexBuffer = renderer.createBuffer();
+	geometry.__webglColorBuffer = renderer.createBuffer();
+	geometry.__webglLineDistanceBuffer = renderer.createBuffer();
+
+	this.info.memory.geometries ++;
+};
+
+THREE.LineRenderer.prototype.initBuffers = function( geometry, object ) {
+
+	var nvertices = geometry.vertices.length;
+
+	geometry.__vertexArray = new Float32Array( nvertices * 3 );
+	geometry.__colorArray = new Float32Array( nvertices * 3 );
+	geometry.__lineDistanceArray = new Float32Array( nvertices * 1 );
+
+	geometry.__webglLineCount = nvertices;
+
+	this.initCustomAttributes ( geometry, object );
+};
+
+
+THREE.LineRenderer.prototype.setBuffers = function( geometry, object) {
+	
+	var renderer = this.renderer;
+	var v, c, d, vertex, offset, color,
+
+	vertices = geometry.vertices,
+	colors = geometry.colors,
+	lineDistances = geometry.lineDistances,
+
+	vl = vertices.length,
+	cl = colors.length,
+	dl = lineDistances.length,
+
+	vertexArray = geometry.__vertexArray,
+	colorArray = geometry.__colorArray,
+	lineDistanceArray = geometry.__lineDistanceArray,
+
+	dirtyVertices = geometry.verticesNeedUpdate,
+	dirtyColors = geometry.colorsNeedUpdate,
+	dirtyLineDistances = geometry.lineDistancesNeedUpdate,
+
+	customAttributes = geometry.__webglCustomAttributesList,
+
+	i, il,
+	a, ca, cal, value,
+	customAttribute;
+
+	if ( dirtyVertices ) {
+
+		for ( v = 0; v < vl; v ++ ) {
+
+			vertex = vertices[ v ];
+
+			offset = v * 3;
+
+			vertexArray[ offset ]     = vertex.x;
+			vertexArray[ offset + 1 ] = vertex.y;
+			vertexArray[ offset + 2 ] = vertex.z;
+
+		}
+		
+		renderer.setDynamicArrayBuffer(geometry.__webglVertexBuffer,vertexArray);
+
+	}
+
+	if ( dirtyColors ) {
+
+		for ( c = 0; c < cl; c ++ ) {
+
+			color = colors[ c ];
+
+			offset = c * 3;
+
+			colorArray[ offset ]     = color.r;
+			colorArray[ offset + 1 ] = color.g;
+			colorArray[ offset + 2 ] = color.b;
+
+		}
+		
+		renderer.setDynamicArrayBuffer(geometry.__webglColorBuffer,colorArray);
+
+	}
+
+	if ( dirtyLineDistances ) {
+
+		for ( d = 0; d < dl; d ++ ) {
+
+			lineDistanceArray[ d ] = lineDistances[ d ];
+
+		}
+		
+		renderer.setDynamicArrayBuffer( geometry.__webglLineDistanceBuffer,lineDistanceArray);
+
+	}
+
+	if ( customAttributes ) {
+
+		for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+			customAttribute = customAttributes[ i ];
+
+			if ( customAttribute.needsUpdate &&
+				 ( customAttribute.boundTo === undefined ||
+				   customAttribute.boundTo === "vertices" ) ) {
+
+				offset = 0;
+
+				cal = customAttribute.value.length;
+
+				if ( customAttribute.size === 1 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						customAttribute.array[ ca ] = customAttribute.value[ ca ];
+
+					}
+
+				} else if ( customAttribute.size === 2 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						value = customAttribute.value[ ca ];
+
+						customAttribute.array[ offset ] 	= value.x;
+						customAttribute.array[ offset + 1 ] = value.y;
+
+						offset += 2;
+
+					}
+
+				} else if ( customAttribute.size === 3 ) {
+
+					if ( customAttribute.type === "c" ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	= value.r;
+							customAttribute.array[ offset + 1 ] = value.g;
+							customAttribute.array[ offset + 2 ] = value.b;
+
+							offset += 3;
+
+						}
+
+					} else {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
+							customAttribute.array[ offset + 2 ] = value.z;
+
+							offset += 3;
+
+						}
+
+					}
+
+				} else if ( customAttribute.size === 4 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						value = customAttribute.value[ ca ];
+
+						customAttribute.array[ offset ] 	 = value.x;
+						customAttribute.array[ offset + 1  ] = value.y;
+						customAttribute.array[ offset + 2  ] = value.z;
+						customAttribute.array[ offset + 3  ] = value.w;
+
+						offset += 4;
+
+					}
+
+				}
+
+				renderer.setDynamicArrayBuffer( customAttribute.buffer,customAttribute.array);
+
+			}
+
+		}
+
+	}
+};

+ 1616 - 0
src/renderers/webgl/Objects/MeshRenderer.js

@@ -0,0 +1,1616 @@
+
+
+THREE.MeshRenderer = function(lowlevelrenderer, info){
+	THREE.Object3DRenderer.call( this, lowlevelrenderer, info );
+};
+
+
+THREE.MeshRenderer.prototype = Object.create( THREE.Object3DRenderer.prototype );
+
+THREE.MeshRenderer.prototype.createBuffers = function( geometryGroup ) {
+
+	var renderer = this.renderer;
+	geometryGroup.__webglVertexBuffer = renderer.createBuffer();
+	geometryGroup.__webglNormalBuffer = renderer.createBuffer();
+	geometryGroup.__webglTangentBuffer = renderer.createBuffer();
+	geometryGroup.__webglColorBuffer = renderer.createBuffer();
+	geometryGroup.__webglUVBuffer = renderer.createBuffer();
+	geometryGroup.__webglUV2Buffer = renderer.createBuffer();
+
+	geometryGroup.__webglSkinIndicesBuffer = renderer.createBuffer();
+	geometryGroup.__webglSkinWeightsBuffer = renderer.createBuffer();
+
+	geometryGroup.__webglFaceBuffer = renderer.createBuffer();
+	geometryGroup.__webglLineBuffer = renderer.createBuffer();
+
+	var m, ml;
+
+	if ( geometryGroup.numMorphTargets ) {
+
+		geometryGroup.__webglMorphTargetsBuffers = [];
+
+		for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+
+			geometryGroup.__webglMorphTargetsBuffers.push( renderer.createBuffer() );
+
+		}
+
+	}
+
+	if ( geometryGroup.numMorphNormals ) {
+
+		geometryGroup.__webglMorphNormalsBuffers = [];
+
+		for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+
+			geometryGroup.__webglMorphNormalsBuffers.push( renderer.createBuffer() );
+
+		}
+
+	}
+
+	this.info.memory.geometries ++;
+
+};
+
+THREE.MeshRenderer.prototype.initBuffers = function( geometryGroup, object ) {
+
+	var geometry = object.geometry,
+		faces3 = geometryGroup.faces3,
+		faces4 = geometryGroup.faces4,
+
+		nvertices = faces3.length * 3 + faces4.length * 4,
+		ntris     = faces3.length * 1 + faces4.length * 2,
+		nlines    = faces3.length * 3 + faces4.length * 4,
+
+		material = this.getBufferMaterial( object, geometryGroup ),
+
+		uvType = this.bufferGuessUVType( material ),
+		normalType = this.bufferGuessNormalType( material ),
+		vertexColorType = this.bufferGuessVertexColorType( material );
+
+	//console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
+
+	geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
+
+	if ( normalType ) {
+
+		geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
+
+	}
+
+	if ( geometry.hasTangents ) {
+
+		geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
+
+	}
+
+	if ( vertexColorType ) {
+
+		geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
+
+	}
+
+	if ( uvType ) {
+
+		if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
+
+			geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
+
+		}
+
+		if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
+
+			geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
+
+		}
+
+	}
+
+	if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
+
+		geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
+		geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
+
+	}
+
+	geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
+	geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
+
+	var m, ml;
+
+	if ( geometryGroup.numMorphTargets ) {
+
+		geometryGroup.__morphTargetsArrays = [];
+
+		for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
+
+			geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
+
+		}
+
+	}
+
+	if ( geometryGroup.numMorphNormals ) {
+
+		geometryGroup.__morphNormalsArrays = [];
+
+		for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
+
+			geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
+
+		}
+
+	}
+
+	geometryGroup.__webglFaceCount = ntris * 3;
+	geometryGroup.__webglLineCount = nlines * 2;
+
+
+	// custom attributes
+
+	if ( material.attributes ) {
+
+		if ( geometryGroup.__webglCustomAttributesList === undefined ) {
+
+			geometryGroup.__webglCustomAttributesList = [];
+
+		}
+
+		for ( var a in material.attributes ) {
+
+			// Do a shallow copy of the attribute object so different geometryGroup chunks use different
+			// attribute buffers which are correctly indexed in the setMeshBuffers function
+
+			var originalAttribute = material.attributes[ a ];
+
+			var attribute = {};
+
+			for ( var property in originalAttribute ) {
+
+				attribute[ property ] = originalAttribute[ property ];
+
+			}
+
+			if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
+
+				attribute.__webglInitialized = true;
+
+				var size = 1;		// "f" and "i"
+
+				if( attribute.type === "v2" ) size = 2;
+				else if( attribute.type === "v3" ) size = 3;
+				else if( attribute.type === "v4" ) size = 4;
+				else if( attribute.type === "c"  ) size = 3;
+
+				attribute.size = size;
+
+				attribute.array = new Float32Array( nvertices * size );
+
+				attribute.buffer = this.renderer.createBuffer();
+				attribute.buffer.belongsToAttribute = a;
+
+				originalAttribute.needsUpdate = true;
+				attribute.__original = originalAttribute;
+
+			}
+
+			geometryGroup.__webglCustomAttributesList.push( attribute );
+
+		}
+
+	}
+
+	geometryGroup.__inittedArrays = true;
+
+};
+
+
+
+THREE.MeshRenderer.prototype.setBuffers = function( geometryGroup, object, dispose, material ) {
+
+	if ( ! geometryGroup.__inittedArrays ) {
+
+		return;
+
+	}
+
+	var renderer = this.renderer;
+	var normalType = this.bufferGuessNormalType( material ),
+	vertexColorType = this.bufferGuessVertexColorType( material ),
+	uvType = this.bufferGuessUVType( material ),
+
+	needsSmoothNormals = ( normalType === THREE.SmoothShading );
+
+	var f, fl, fi, face,
+	vertexNormals, faceNormal, normal,
+	vertexColors, faceColor,
+	vertexTangents,
+	uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
+	c1, c2, c3, c4,
+	sw1, sw2, sw3, sw4,
+	si1, si2, si3, si4,
+	sa1, sa2, sa3, sa4,
+	sb1, sb2, sb3, sb4,
+	m, ml, i, il,
+	vn, uvi, uv2i,
+	vk, vkl, vka,
+	nka, chf, faceVertexNormals,
+	a,
+
+	vertexIndex = 0,
+
+	offset = 0,
+	offset_uv = 0,
+	offset_uv2 = 0,
+	offset_face = 0,
+	offset_normal = 0,
+	offset_tangent = 0,
+	offset_line = 0,
+	offset_color = 0,
+	offset_skin = 0,
+	offset_morphTarget = 0,
+	offset_custom = 0,
+	offset_customSrc = 0,
+
+	value,
+
+	vertexArray = geometryGroup.__vertexArray,
+	uvArray = geometryGroup.__uvArray,
+	uv2Array = geometryGroup.__uv2Array,
+	normalArray = geometryGroup.__normalArray,
+	tangentArray = geometryGroup.__tangentArray,
+	colorArray = geometryGroup.__colorArray,
+
+	skinIndexArray = geometryGroup.__skinIndexArray,
+	skinWeightArray = geometryGroup.__skinWeightArray,
+
+	morphTargetsArrays = geometryGroup.__morphTargetsArrays,
+	morphNormalsArrays = geometryGroup.__morphNormalsArrays,
+
+	customAttributes = geometryGroup.__webglCustomAttributesList,
+	customAttribute,
+
+	faceArray = geometryGroup.__faceArray,
+	lineArray = geometryGroup.__lineArray,
+
+	geometry = object.geometry, // this is shared for all chunks
+
+	dirtyVertices = geometry.verticesNeedUpdate,
+	dirtyElements = geometry.elementsNeedUpdate,
+	dirtyUvs = geometry.uvsNeedUpdate,
+	dirtyNormals = geometry.normalsNeedUpdate,
+	dirtyTangents = geometry.tangentsNeedUpdate,
+	dirtyColors = geometry.colorsNeedUpdate,
+	dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
+
+	vertices = geometry.vertices,
+	chunk_faces3 = geometryGroup.faces3,
+	chunk_faces4 = geometryGroup.faces4,
+	obj_faces = geometry.faces,
+
+	obj_uvs  = geometry.faceVertexUvs[ 0 ],
+	obj_uvs2 = geometry.faceVertexUvs[ 1 ],
+
+	obj_colors = geometry.colors,
+
+	obj_skinIndices = geometry.skinIndices,
+	obj_skinWeights = geometry.skinWeights,
+
+	morphTargets = geometry.morphTargets,
+	morphNormals = geometry.morphNormals;
+
+	if ( dirtyVertices ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces3[ f ] ];
+
+			v1 = vertices[ face.a ];
+			v2 = vertices[ face.b ];
+			v3 = vertices[ face.c ];
+
+			vertexArray[ offset ]     = v1.x;
+			vertexArray[ offset + 1 ] = v1.y;
+			vertexArray[ offset + 2 ] = v1.z;
+
+			vertexArray[ offset + 3 ] = v2.x;
+			vertexArray[ offset + 4 ] = v2.y;
+			vertexArray[ offset + 5 ] = v2.z;
+
+			vertexArray[ offset + 6 ] = v3.x;
+			vertexArray[ offset + 7 ] = v3.y;
+			vertexArray[ offset + 8 ] = v3.z;
+
+			offset += 9;
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces4[ f ] ];
+
+			v1 = vertices[ face.a ];
+			v2 = vertices[ face.b ];
+			v3 = vertices[ face.c ];
+			v4 = vertices[ face.d ];
+
+			vertexArray[ offset ]     = v1.x;
+			vertexArray[ offset + 1 ] = v1.y;
+			vertexArray[ offset + 2 ] = v1.z;
+
+			vertexArray[ offset + 3 ] = v2.x;
+			vertexArray[ offset + 4 ] = v2.y;
+			vertexArray[ offset + 5 ] = v2.z;
+
+			vertexArray[ offset + 6 ] = v3.x;
+			vertexArray[ offset + 7 ] = v3.y;
+			vertexArray[ offset + 8 ] = v3.z;
+
+			vertexArray[ offset + 9 ]  = v4.x;
+			vertexArray[ offset + 10 ] = v4.y;
+			vertexArray[ offset + 11 ] = v4.z;
+
+			offset += 12;
+
+		}
+
+		renderer.setDynamicArrayBuffer( geometryGroup.__webglVertexBuffer, vertexArray);
+
+	}
+
+	if ( dirtyMorphTargets ) {
+
+		for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
+
+			offset_morphTarget = 0;
+
+			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+				chf = chunk_faces3[ f ];
+				face = obj_faces[ chf ];
+
+				// morph positions
+
+				v1 = morphTargets[ vk ].vertices[ face.a ];
+				v2 = morphTargets[ vk ].vertices[ face.b ];
+				v3 = morphTargets[ vk ].vertices[ face.c ];
+
+				vka = morphTargetsArrays[ vk ];
+
+				vka[ offset_morphTarget ] 	  = v1.x;
+				vka[ offset_morphTarget + 1 ] = v1.y;
+				vka[ offset_morphTarget + 2 ] = v1.z;
+
+				vka[ offset_morphTarget + 3 ] = v2.x;
+				vka[ offset_morphTarget + 4 ] = v2.y;
+				vka[ offset_morphTarget + 5 ] = v2.z;
+
+				vka[ offset_morphTarget + 6 ] = v3.x;
+				vka[ offset_morphTarget + 7 ] = v3.y;
+				vka[ offset_morphTarget + 8 ] = v3.z;
+
+				// morph normals
+
+				if ( material.morphNormals ) {
+
+					if ( needsSmoothNormals ) {
+
+						faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
+
+						n1 = faceVertexNormals.a;
+						n2 = faceVertexNormals.b;
+						n3 = faceVertexNormals.c;
+
+					} else {
+
+						n1 = morphNormals[ vk ].faceNormals[ chf ];
+						n2 = n1;
+						n3 = n1;
+
+					}
+
+					nka = morphNormalsArrays[ vk ];
+
+					nka[ offset_morphTarget ] 	  = n1.x;
+					nka[ offset_morphTarget + 1 ] = n1.y;
+					nka[ offset_morphTarget + 2 ] = n1.z;
+
+					nka[ offset_morphTarget + 3 ] = n2.x;
+					nka[ offset_morphTarget + 4 ] = n2.y;
+					nka[ offset_morphTarget + 5 ] = n2.z;
+
+					nka[ offset_morphTarget + 6 ] = n3.x;
+					nka[ offset_morphTarget + 7 ] = n3.y;
+					nka[ offset_morphTarget + 8 ] = n3.z;
+
+				}
+
+				//
+
+				offset_morphTarget += 9;
+
+			}
+
+			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+				chf = chunk_faces4[ f ];
+				face = obj_faces[ chf ];
+
+				// morph positions
+
+				v1 = morphTargets[ vk ].vertices[ face.a ];
+				v2 = morphTargets[ vk ].vertices[ face.b ];
+				v3 = morphTargets[ vk ].vertices[ face.c ];
+				v4 = morphTargets[ vk ].vertices[ face.d ];
+
+				vka = morphTargetsArrays[ vk ];
+
+				vka[ offset_morphTarget ] 	  = v1.x;
+				vka[ offset_morphTarget + 1 ] = v1.y;
+				vka[ offset_morphTarget + 2 ] = v1.z;
+
+				vka[ offset_morphTarget + 3 ] = v2.x;
+				vka[ offset_morphTarget + 4 ] = v2.y;
+				vka[ offset_morphTarget + 5 ] = v2.z;
+
+				vka[ offset_morphTarget + 6 ] = v3.x;
+				vka[ offset_morphTarget + 7 ] = v3.y;
+				vka[ offset_morphTarget + 8 ] = v3.z;
+
+				vka[ offset_morphTarget + 9 ]  = v4.x;
+				vka[ offset_morphTarget + 10 ] = v4.y;
+				vka[ offset_morphTarget + 11 ] = v4.z;
+
+				// morph normals
+
+				if ( material.morphNormals ) {
+
+					if ( needsSmoothNormals ) {
+
+						faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
+
+						n1 = faceVertexNormals.a;
+						n2 = faceVertexNormals.b;
+						n3 = faceVertexNormals.c;
+						n4 = faceVertexNormals.d;
+
+					} else {
+
+						n1 = morphNormals[ vk ].faceNormals[ chf ];
+						n2 = n1;
+						n3 = n1;
+						n4 = n1;
+
+					}
+
+					nka = morphNormalsArrays[ vk ];
+
+					nka[ offset_morphTarget ] 	  = n1.x;
+					nka[ offset_morphTarget + 1 ] = n1.y;
+					nka[ offset_morphTarget + 2 ] = n1.z;
+
+					nka[ offset_morphTarget + 3 ] = n2.x;
+					nka[ offset_morphTarget + 4 ] = n2.y;
+					nka[ offset_morphTarget + 5 ] = n2.z;
+
+					nka[ offset_morphTarget + 6 ] = n3.x;
+					nka[ offset_morphTarget + 7 ] = n3.y;
+					nka[ offset_morphTarget + 8 ] = n3.z;
+
+					nka[ offset_morphTarget + 9 ]  = n4.x;
+					nka[ offset_morphTarget + 10 ] = n4.y;
+					nka[ offset_morphTarget + 11 ] = n4.z;
+
+				}
+
+				//
+
+				offset_morphTarget += 12;
+
+			}
+
+			this.renderer.setDynamicArrayBuffer( geometryGroup.__webglMorphTargetsBuffers[ vk ], morphTargetsArrays[ vk ]);
+
+			if ( material.morphNormals ) {
+
+				this.renderer.setDynamicArrayBuffer( geometryGroup.__webglMorphNormalsBuffers[ vk ], morphNormalsArrays[ vk ]);
+
+			}
+
+		}
+
+	}
+
+	if ( obj_skinWeights.length ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces3[ f ]	];
+
+			// weights
+
+			sw1 = obj_skinWeights[ face.a ];
+			sw2 = obj_skinWeights[ face.b ];
+			sw3 = obj_skinWeights[ face.c ];
+
+			skinWeightArray[ offset_skin ]     = sw1.x;
+			skinWeightArray[ offset_skin + 1 ] = sw1.y;
+			skinWeightArray[ offset_skin + 2 ] = sw1.z;
+			skinWeightArray[ offset_skin + 3 ] = sw1.w;
+
+			skinWeightArray[ offset_skin + 4 ] = sw2.x;
+			skinWeightArray[ offset_skin + 5 ] = sw2.y;
+			skinWeightArray[ offset_skin + 6 ] = sw2.z;
+			skinWeightArray[ offset_skin + 7 ] = sw2.w;
+
+			skinWeightArray[ offset_skin + 8 ]  = sw3.x;
+			skinWeightArray[ offset_skin + 9 ]  = sw3.y;
+			skinWeightArray[ offset_skin + 10 ] = sw3.z;
+			skinWeightArray[ offset_skin + 11 ] = sw3.w;
+
+			// indices
+
+			si1 = obj_skinIndices[ face.a ];
+			si2 = obj_skinIndices[ face.b ];
+			si3 = obj_skinIndices[ face.c ];
+
+			skinIndexArray[ offset_skin ]     = si1.x;
+			skinIndexArray[ offset_skin + 1 ] = si1.y;
+			skinIndexArray[ offset_skin + 2 ] = si1.z;
+			skinIndexArray[ offset_skin + 3 ] = si1.w;
+
+			skinIndexArray[ offset_skin + 4 ] = si2.x;
+			skinIndexArray[ offset_skin + 5 ] = si2.y;
+			skinIndexArray[ offset_skin + 6 ] = si2.z;
+			skinIndexArray[ offset_skin + 7 ] = si2.w;
+
+			skinIndexArray[ offset_skin + 8 ]  = si3.x;
+			skinIndexArray[ offset_skin + 9 ]  = si3.y;
+			skinIndexArray[ offset_skin + 10 ] = si3.z;
+			skinIndexArray[ offset_skin + 11 ] = si3.w;
+
+			offset_skin += 12;
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces4[ f ] ];
+
+			// weights
+
+			sw1 = obj_skinWeights[ face.a ];
+			sw2 = obj_skinWeights[ face.b ];
+			sw3 = obj_skinWeights[ face.c ];
+			sw4 = obj_skinWeights[ face.d ];
+
+			skinWeightArray[ offset_skin ]     = sw1.x;
+			skinWeightArray[ offset_skin + 1 ] = sw1.y;
+			skinWeightArray[ offset_skin + 2 ] = sw1.z;
+			skinWeightArray[ offset_skin + 3 ] = sw1.w;
+
+			skinWeightArray[ offset_skin + 4 ] = sw2.x;
+			skinWeightArray[ offset_skin + 5 ] = sw2.y;
+			skinWeightArray[ offset_skin + 6 ] = sw2.z;
+			skinWeightArray[ offset_skin + 7 ] = sw2.w;
+
+			skinWeightArray[ offset_skin + 8 ]  = sw3.x;
+			skinWeightArray[ offset_skin + 9 ]  = sw3.y;
+			skinWeightArray[ offset_skin + 10 ] = sw3.z;
+			skinWeightArray[ offset_skin + 11 ] = sw3.w;
+
+			skinWeightArray[ offset_skin + 12 ] = sw4.x;
+			skinWeightArray[ offset_skin + 13 ] = sw4.y;
+			skinWeightArray[ offset_skin + 14 ] = sw4.z;
+			skinWeightArray[ offset_skin + 15 ] = sw4.w;
+
+			// indices
+
+			si1 = obj_skinIndices[ face.a ];
+			si2 = obj_skinIndices[ face.b ];
+			si3 = obj_skinIndices[ face.c ];
+			si4 = obj_skinIndices[ face.d ];
+
+			skinIndexArray[ offset_skin ]     = si1.x;
+			skinIndexArray[ offset_skin + 1 ] = si1.y;
+			skinIndexArray[ offset_skin + 2 ] = si1.z;
+			skinIndexArray[ offset_skin + 3 ] = si1.w;
+
+			skinIndexArray[ offset_skin + 4 ] = si2.x;
+			skinIndexArray[ offset_skin + 5 ] = si2.y;
+			skinIndexArray[ offset_skin + 6 ] = si2.z;
+			skinIndexArray[ offset_skin + 7 ] = si2.w;
+
+			skinIndexArray[ offset_skin + 8 ]  = si3.x;
+			skinIndexArray[ offset_skin + 9 ]  = si3.y;
+			skinIndexArray[ offset_skin + 10 ] = si3.z;
+			skinIndexArray[ offset_skin + 11 ] = si3.w;
+
+			skinIndexArray[ offset_skin + 12 ] = si4.x;
+			skinIndexArray[ offset_skin + 13 ] = si4.y;
+			skinIndexArray[ offset_skin + 14 ] = si4.z;
+			skinIndexArray[ offset_skin + 15 ] = si4.w;
+
+			offset_skin += 16;
+
+		}
+
+		if ( offset_skin > 0 ) {
+
+		renderer.setDynamicArrayBuffer( geometryGroup.__webglSkinIndicesBuffer, skinIndexArray);
+		renderer.setDynamicArrayBuffer( geometryGroup.__webglSkinWeightsBuffer, skinWeightArray);
+
+		}
+
+	}
+
+	if ( dirtyColors && vertexColorType ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces3[ f ]	];
+
+			vertexColors = face.vertexColors;
+			faceColor = face.color;
+
+			if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
+
+				c1 = vertexColors[ 0 ];
+				c2 = vertexColors[ 1 ];
+				c3 = vertexColors[ 2 ];
+
+			} else {
+
+				c1 = faceColor;
+				c2 = faceColor;
+				c3 = faceColor;
+
+			}
+
+			colorArray[ offset_color ]     = c1.r;
+			colorArray[ offset_color + 1 ] = c1.g;
+			colorArray[ offset_color + 2 ] = c1.b;
+
+			colorArray[ offset_color + 3 ] = c2.r;
+			colorArray[ offset_color + 4 ] = c2.g;
+			colorArray[ offset_color + 5 ] = c2.b;
+
+			colorArray[ offset_color + 6 ] = c3.r;
+			colorArray[ offset_color + 7 ] = c3.g;
+			colorArray[ offset_color + 8 ] = c3.b;
+
+			offset_color += 9;
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces4[ f ] ];
+
+			vertexColors = face.vertexColors;
+			faceColor = face.color;
+
+			if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
+
+				c1 = vertexColors[ 0 ];
+				c2 = vertexColors[ 1 ];
+				c3 = vertexColors[ 2 ];
+				c4 = vertexColors[ 3 ];
+
+			} else {
+
+				c1 = faceColor;
+				c2 = faceColor;
+				c3 = faceColor;
+				c4 = faceColor;
+
+			}
+
+			colorArray[ offset_color ]     = c1.r;
+			colorArray[ offset_color + 1 ] = c1.g;
+			colorArray[ offset_color + 2 ] = c1.b;
+
+			colorArray[ offset_color + 3 ] = c2.r;
+			colorArray[ offset_color + 4 ] = c2.g;
+			colorArray[ offset_color + 5 ] = c2.b;
+
+			colorArray[ offset_color + 6 ] = c3.r;
+			colorArray[ offset_color + 7 ] = c3.g;
+			colorArray[ offset_color + 8 ] = c3.b;
+
+			colorArray[ offset_color + 9 ]  = c4.r;
+			colorArray[ offset_color + 10 ] = c4.g;
+			colorArray[ offset_color + 11 ] = c4.b;
+
+			offset_color += 12;
+
+		}
+
+		if ( offset_color > 0 ) {
+			
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglColorBuffer, colorArray);
+
+		}
+
+	}
+
+	if ( dirtyTangents && geometry.hasTangents ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces3[ f ]	];
+
+			vertexTangents = face.vertexTangents;
+
+			t1 = vertexTangents[ 0 ];
+			t2 = vertexTangents[ 1 ];
+			t3 = vertexTangents[ 2 ];
+
+			tangentArray[ offset_tangent ]     = t1.x;
+			tangentArray[ offset_tangent + 1 ] = t1.y;
+			tangentArray[ offset_tangent + 2 ] = t1.z;
+			tangentArray[ offset_tangent + 3 ] = t1.w;
+
+			tangentArray[ offset_tangent + 4 ] = t2.x;
+			tangentArray[ offset_tangent + 5 ] = t2.y;
+			tangentArray[ offset_tangent + 6 ] = t2.z;
+			tangentArray[ offset_tangent + 7 ] = t2.w;
+
+			tangentArray[ offset_tangent + 8 ]  = t3.x;
+			tangentArray[ offset_tangent + 9 ]  = t3.y;
+			tangentArray[ offset_tangent + 10 ] = t3.z;
+			tangentArray[ offset_tangent + 11 ] = t3.w;
+
+			offset_tangent += 12;
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces4[ f ] ];
+
+			vertexTangents = face.vertexTangents;
+
+			t1 = vertexTangents[ 0 ];
+			t2 = vertexTangents[ 1 ];
+			t3 = vertexTangents[ 2 ];
+			t4 = vertexTangents[ 3 ];
+
+			tangentArray[ offset_tangent ]     = t1.x;
+			tangentArray[ offset_tangent + 1 ] = t1.y;
+			tangentArray[ offset_tangent + 2 ] = t1.z;
+			tangentArray[ offset_tangent + 3 ] = t1.w;
+
+			tangentArray[ offset_tangent + 4 ] = t2.x;
+			tangentArray[ offset_tangent + 5 ] = t2.y;
+			tangentArray[ offset_tangent + 6 ] = t2.z;
+			tangentArray[ offset_tangent + 7 ] = t2.w;
+
+			tangentArray[ offset_tangent + 8 ]  = t3.x;
+			tangentArray[ offset_tangent + 9 ]  = t3.y;
+			tangentArray[ offset_tangent + 10 ] = t3.z;
+			tangentArray[ offset_tangent + 11 ] = t3.w;
+
+			tangentArray[ offset_tangent + 12 ] = t4.x;
+			tangentArray[ offset_tangent + 13 ] = t4.y;
+			tangentArray[ offset_tangent + 14 ] = t4.z;
+			tangentArray[ offset_tangent + 15 ] = t4.w;
+
+			offset_tangent += 16;
+
+		}
+		
+		renderer.setDynamicArrayBuffer( geometryGroup.__webglTangentBuffer, tangentArray);
+
+	}
+
+	if ( dirtyNormals && normalType ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces3[ f ]	];
+
+			vertexNormals = face.vertexNormals;
+			faceNormal = face.normal;
+
+			if ( vertexNormals.length === 3 && needsSmoothNormals ) {
+
+				for ( i = 0; i < 3; i ++ ) {
+
+					vn = vertexNormals[ i ];
+
+					normalArray[ offset_normal ]     = vn.x;
+					normalArray[ offset_normal + 1 ] = vn.y;
+					normalArray[ offset_normal + 2 ] = vn.z;
+
+					offset_normal += 3;
+
+				}
+
+			} else {
+
+				for ( i = 0; i < 3; i ++ ) {
+
+					normalArray[ offset_normal ]     = faceNormal.x;
+					normalArray[ offset_normal + 1 ] = faceNormal.y;
+					normalArray[ offset_normal + 2 ] = faceNormal.z;
+
+					offset_normal += 3;
+
+				}
+
+			}
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			face = obj_faces[ chunk_faces4[ f ] ];
+
+			vertexNormals = face.vertexNormals;
+			faceNormal = face.normal;
+
+			if ( vertexNormals.length === 4 && needsSmoothNormals ) {
+
+				for ( i = 0; i < 4; i ++ ) {
+
+					vn = vertexNormals[ i ];
+
+					normalArray[ offset_normal ]     = vn.x;
+					normalArray[ offset_normal + 1 ] = vn.y;
+					normalArray[ offset_normal + 2 ] = vn.z;
+
+					offset_normal += 3;
+
+				}
+
+			} else {
+
+				for ( i = 0; i < 4; i ++ ) {
+
+					normalArray[ offset_normal ]     = faceNormal.x;
+					normalArray[ offset_normal + 1 ] = faceNormal.y;
+					normalArray[ offset_normal + 2 ] = faceNormal.z;
+
+					offset_normal += 3;
+
+				}
+
+			}
+
+		}
+		
+		renderer.setDynamicArrayBuffer( geometryGroup.__webglNormalBuffer, normalArray);
+		
+	}
+
+	if ( dirtyUvs && obj_uvs && uvType ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			fi = chunk_faces3[ f ];
+
+			uv = obj_uvs[ fi ];
+
+			if ( uv === undefined ) continue;
+
+			for ( i = 0; i < 3; i ++ ) {
+
+				uvi = uv[ i ];
+
+				uvArray[ offset_uv ]     = uvi.x;
+				uvArray[ offset_uv + 1 ] = uvi.y;
+
+				offset_uv += 2;
+
+			}
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			fi = chunk_faces4[ f ];
+
+			uv = obj_uvs[ fi ];
+
+			if ( uv === undefined ) continue;
+
+			for ( i = 0; i < 4; i ++ ) {
+
+				uvi = uv[ i ];
+
+				uvArray[ offset_uv ]     = uvi.x;
+				uvArray[ offset_uv + 1 ] = uvi.y;
+
+				offset_uv += 2;
+
+			}
+
+		}
+
+		if ( offset_uv > 0 ) {
+			
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglUVBuffer, uvArray);
+
+		}
+
+	}
+
+	if ( dirtyUvs && obj_uvs2 && uvType ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			fi = chunk_faces3[ f ];
+
+			uv2 = obj_uvs2[ fi ];
+
+			if ( uv2 === undefined ) continue;
+
+			for ( i = 0; i < 3; i ++ ) {
+
+				uv2i = uv2[ i ];
+
+				uv2Array[ offset_uv2 ]     = uv2i.x;
+				uv2Array[ offset_uv2 + 1 ] = uv2i.y;
+
+				offset_uv2 += 2;
+
+			}
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			fi = chunk_faces4[ f ];
+
+			uv2 = obj_uvs2[ fi ];
+
+			if ( uv2 === undefined ) continue;
+
+			for ( i = 0; i < 4; i ++ ) {
+
+				uv2i = uv2[ i ];
+
+				uv2Array[ offset_uv2 ]     = uv2i.x;
+				uv2Array[ offset_uv2 + 1 ] = uv2i.y;
+
+				offset_uv2 += 2;
+
+			}
+
+		}
+
+		if ( offset_uv2 > 0 ) {
+
+			renderer.setDynamicArrayBuffer( geometryGroup.__webglUV2Buffer, uv2Array);
+
+		}
+
+	}
+
+	if ( dirtyElements ) {
+
+		for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+			faceArray[ offset_face ] 	 = vertexIndex;
+			faceArray[ offset_face + 1 ] = vertexIndex + 1;
+			faceArray[ offset_face + 2 ] = vertexIndex + 2;
+
+			offset_face += 3;
+
+			lineArray[ offset_line ]     = vertexIndex;
+			lineArray[ offset_line + 1 ] = vertexIndex + 1;
+
+			lineArray[ offset_line + 2 ] = vertexIndex;
+			lineArray[ offset_line + 3 ] = vertexIndex + 2;
+
+			lineArray[ offset_line + 4 ] = vertexIndex + 1;
+			lineArray[ offset_line + 5 ] = vertexIndex + 2;
+
+			offset_line += 6;
+
+			vertexIndex += 3;
+
+		}
+
+		for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+			faceArray[ offset_face ]     = vertexIndex;
+			faceArray[ offset_face + 1 ] = vertexIndex + 1;
+			faceArray[ offset_face + 2 ] = vertexIndex + 3;
+
+			faceArray[ offset_face + 3 ] = vertexIndex + 1;
+			faceArray[ offset_face + 4 ] = vertexIndex + 2;
+			faceArray[ offset_face + 5 ] = vertexIndex + 3;
+
+			offset_face += 6;
+
+			lineArray[ offset_line ]     = vertexIndex;
+			lineArray[ offset_line + 1 ] = vertexIndex + 1;
+
+			lineArray[ offset_line + 2 ] = vertexIndex;
+			lineArray[ offset_line + 3 ] = vertexIndex + 3;
+
+			lineArray[ offset_line + 4 ] = vertexIndex + 1;
+			lineArray[ offset_line + 5 ] = vertexIndex + 2;
+
+			lineArray[ offset_line + 6 ] = vertexIndex + 2;
+			lineArray[ offset_line + 7 ] = vertexIndex + 3;
+
+			offset_line += 8;
+
+			vertexIndex += 4;
+
+		}
+
+		renderer.setDynamicIndexBuffer( geometryGroup.__webglFaceBuffer, faceArray);
+		renderer.setDynamicIndexBuffer( geometryGroup.__webglLineBuffer, lineArray);
+
+	}
+
+	if ( customAttributes ) {
+
+		for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+			customAttribute = customAttributes[ i ];
+
+			if ( ! customAttribute.__original.needsUpdate ) continue;
+
+			offset_custom = 0;
+			offset_customSrc = 0;
+
+			if ( customAttribute.size === 1 ) {
+
+				if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces3[ f ]	];
+
+						customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
+						customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
+						customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
+
+						offset_custom += 3;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces4[ f ] ];
+
+						customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
+						customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
+						customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
+						customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
+
+						offset_custom += 4;
+
+					}
+
+				} else if ( customAttribute.boundTo === "faces" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces3[ f ] ];
+
+						customAttribute.array[ offset_custom ] 	   = value;
+						customAttribute.array[ offset_custom + 1 ] = value;
+						customAttribute.array[ offset_custom + 2 ] = value;
+
+						offset_custom += 3;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces4[ f ] ];
+
+						customAttribute.array[ offset_custom ] 	   = value;
+						customAttribute.array[ offset_custom + 1 ] = value;
+						customAttribute.array[ offset_custom + 2 ] = value;
+						customAttribute.array[ offset_custom + 3 ] = value;
+
+						offset_custom += 4;
+
+					}
+
+				}
+
+			} else if ( customAttribute.size === 2 ) {
+
+				if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces3[ f ]	];
+
+						v1 = customAttribute.value[ face.a ];
+						v2 = customAttribute.value[ face.b ];
+						v3 = customAttribute.value[ face.c ];
+
+						customAttribute.array[ offset_custom ] 	   = v1.x;
+						customAttribute.array[ offset_custom + 1 ] = v1.y;
+
+						customAttribute.array[ offset_custom + 2 ] = v2.x;
+						customAttribute.array[ offset_custom + 3 ] = v2.y;
+
+						customAttribute.array[ offset_custom + 4 ] = v3.x;
+						customAttribute.array[ offset_custom + 5 ] = v3.y;
+
+						offset_custom += 6;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces4[ f ] ];
+
+						v1 = customAttribute.value[ face.a ];
+						v2 = customAttribute.value[ face.b ];
+						v3 = customAttribute.value[ face.c ];
+						v4 = customAttribute.value[ face.d ];
+
+						customAttribute.array[ offset_custom ] 	   = v1.x;
+						customAttribute.array[ offset_custom + 1 ] = v1.y;
+
+						customAttribute.array[ offset_custom + 2 ] = v2.x;
+						customAttribute.array[ offset_custom + 3 ] = v2.y;
+
+						customAttribute.array[ offset_custom + 4 ] = v3.x;
+						customAttribute.array[ offset_custom + 5 ] = v3.y;
+
+						customAttribute.array[ offset_custom + 6 ] = v4.x;
+						customAttribute.array[ offset_custom + 7 ] = v4.y;
+
+						offset_custom += 8;
+
+					}
+
+				} else if ( customAttribute.boundTo === "faces" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces3[ f ] ];
+
+						v1 = value;
+						v2 = value;
+						v3 = value;
+
+						customAttribute.array[ offset_custom ] 	   = v1.x;
+						customAttribute.array[ offset_custom + 1 ] = v1.y;
+
+						customAttribute.array[ offset_custom + 2 ] = v2.x;
+						customAttribute.array[ offset_custom + 3 ] = v2.y;
+
+						customAttribute.array[ offset_custom + 4 ] = v3.x;
+						customAttribute.array[ offset_custom + 5 ] = v3.y;
+
+						offset_custom += 6;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces4[ f ] ];
+
+						v1 = value;
+						v2 = value;
+						v3 = value;
+						v4 = value;
+
+						customAttribute.array[ offset_custom ] 	   = v1.x;
+						customAttribute.array[ offset_custom + 1 ] = v1.y;
+
+						customAttribute.array[ offset_custom + 2 ] = v2.x;
+						customAttribute.array[ offset_custom + 3 ] = v2.y;
+
+						customAttribute.array[ offset_custom + 4 ] = v3.x;
+						customAttribute.array[ offset_custom + 5 ] = v3.y;
+
+						customAttribute.array[ offset_custom + 6 ] = v4.x;
+						customAttribute.array[ offset_custom + 7 ] = v4.y;
+
+						offset_custom += 8;
+
+					}
+
+				}
+
+			} else if ( customAttribute.size === 3 ) {
+
+				var pp;
+
+				if ( customAttribute.type === "c" ) {
+
+					pp = [ "r", "g", "b" ];
+
+				} else {
+
+					pp = [ "x", "y", "z" ];
+
+				}
+
+				if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces3[ f ]	];
+
+						v1 = customAttribute.value[ face.a ];
+						v2 = customAttribute.value[ face.b ];
+						v3 = customAttribute.value[ face.c ];
+
+						customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
+
+						offset_custom += 9;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces4[ f ] ];
+
+						v1 = customAttribute.value[ face.a ];
+						v2 = customAttribute.value[ face.b ];
+						v3 = customAttribute.value[ face.c ];
+						v4 = customAttribute.value[ face.d ];
+
+						customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
+
+						offset_custom += 12;
+
+					}
+
+				} else if ( customAttribute.boundTo === "faces" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces3[ f ] ];
+
+						v1 = value;
+						v2 = value;
+						v3 = value;
+
+						customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
+
+						offset_custom += 9;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces4[ f ] ];
+
+						v1 = value;
+						v2 = value;
+						v3 = value;
+						v4 = value;
+
+						customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
+
+						offset_custom += 12;
+
+					}
+
+				} else if ( customAttribute.boundTo === "faceVertices" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces3[ f ] ];
+
+						v1 = value[ 0 ];
+						v2 = value[ 1 ];
+						v3 = value[ 2 ];
+
+						customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
+
+						offset_custom += 9;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces4[ f ] ];
+
+						v1 = value[ 0 ];
+						v2 = value[ 1 ];
+						v3 = value[ 2 ];
+						v4 = value[ 3 ];
+
+						customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
+
+						customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
+						customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
+						customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
+
+						offset_custom += 12;
+
+					}
+
+				}
+
+			} else if ( customAttribute.size === 4 ) {
+
+				if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces3[ f ]	];
+
+						v1 = customAttribute.value[ face.a ];
+						v2 = customAttribute.value[ face.b ];
+						v3 = customAttribute.value[ face.c ];
+
+						customAttribute.array[ offset_custom  ] 	= v1.x;
+						customAttribute.array[ offset_custom + 1  ] = v1.y;
+						customAttribute.array[ offset_custom + 2  ] = v1.z;
+						customAttribute.array[ offset_custom + 3  ] = v1.w;
+
+						customAttribute.array[ offset_custom + 4  ] = v2.x;
+						customAttribute.array[ offset_custom + 5  ] = v2.y;
+						customAttribute.array[ offset_custom + 6  ] = v2.z;
+						customAttribute.array[ offset_custom + 7  ] = v2.w;
+
+						customAttribute.array[ offset_custom + 8  ] = v3.x;
+						customAttribute.array[ offset_custom + 9  ] = v3.y;
+						customAttribute.array[ offset_custom + 10 ] = v3.z;
+						customAttribute.array[ offset_custom + 11 ] = v3.w;
+
+						offset_custom += 12;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						face = obj_faces[ chunk_faces4[ f ] ];
+
+						v1 = customAttribute.value[ face.a ];
+						v2 = customAttribute.value[ face.b ];
+						v3 = customAttribute.value[ face.c ];
+						v4 = customAttribute.value[ face.d ];
+
+						customAttribute.array[ offset_custom  ] 	= v1.x;
+						customAttribute.array[ offset_custom + 1  ] = v1.y;
+						customAttribute.array[ offset_custom + 2  ] = v1.z;
+						customAttribute.array[ offset_custom + 3  ] = v1.w;
+
+						customAttribute.array[ offset_custom + 4  ] = v2.x;
+						customAttribute.array[ offset_custom + 5  ] = v2.y;
+						customAttribute.array[ offset_custom + 6  ] = v2.z;
+						customAttribute.array[ offset_custom + 7  ] = v2.w;
+
+						customAttribute.array[ offset_custom + 8  ] = v3.x;
+						customAttribute.array[ offset_custom + 9  ] = v3.y;
+						customAttribute.array[ offset_custom + 10 ] = v3.z;
+						customAttribute.array[ offset_custom + 11 ] = v3.w;
+
+						customAttribute.array[ offset_custom + 12 ] = v4.x;
+						customAttribute.array[ offset_custom + 13 ] = v4.y;
+						customAttribute.array[ offset_custom + 14 ] = v4.z;
+						customAttribute.array[ offset_custom + 15 ] = v4.w;
+
+						offset_custom += 16;
+
+					}
+
+				} else if ( customAttribute.boundTo === "faces" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces3[ f ] ];
+
+						v1 = value;
+						v2 = value;
+						v3 = value;
+
+						customAttribute.array[ offset_custom  ] 	= v1.x;
+						customAttribute.array[ offset_custom + 1  ] = v1.y;
+						customAttribute.array[ offset_custom + 2  ] = v1.z;
+						customAttribute.array[ offset_custom + 3  ] = v1.w;
+
+						customAttribute.array[ offset_custom + 4  ] = v2.x;
+						customAttribute.array[ offset_custom + 5  ] = v2.y;
+						customAttribute.array[ offset_custom + 6  ] = v2.z;
+						customAttribute.array[ offset_custom + 7  ] = v2.w;
+
+						customAttribute.array[ offset_custom + 8  ] = v3.x;
+						customAttribute.array[ offset_custom + 9  ] = v3.y;
+						customAttribute.array[ offset_custom + 10 ] = v3.z;
+						customAttribute.array[ offset_custom + 11 ] = v3.w;
+
+						offset_custom += 12;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces4[ f ] ];
+
+						v1 = value;
+						v2 = value;
+						v3 = value;
+						v4 = value;
+
+						customAttribute.array[ offset_custom  ] 	= v1.x;
+						customAttribute.array[ offset_custom + 1  ] = v1.y;
+						customAttribute.array[ offset_custom + 2  ] = v1.z;
+						customAttribute.array[ offset_custom + 3  ] = v1.w;
+
+						customAttribute.array[ offset_custom + 4  ] = v2.x;
+						customAttribute.array[ offset_custom + 5  ] = v2.y;
+						customAttribute.array[ offset_custom + 6  ] = v2.z;
+						customAttribute.array[ offset_custom + 7  ] = v2.w;
+
+						customAttribute.array[ offset_custom + 8  ] = v3.x;
+						customAttribute.array[ offset_custom + 9  ] = v3.y;
+						customAttribute.array[ offset_custom + 10 ] = v3.z;
+						customAttribute.array[ offset_custom + 11 ] = v3.w;
+
+						customAttribute.array[ offset_custom + 12 ] = v4.x;
+						customAttribute.array[ offset_custom + 13 ] = v4.y;
+						customAttribute.array[ offset_custom + 14 ] = v4.z;
+						customAttribute.array[ offset_custom + 15 ] = v4.w;
+
+						offset_custom += 16;
+
+					}
+
+				} else if ( customAttribute.boundTo === "faceVertices" ) {
+
+					for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces3[ f ] ];
+
+						v1 = value[ 0 ];
+						v2 = value[ 1 ];
+						v3 = value[ 2 ];
+
+						customAttribute.array[ offset_custom  ] 	= v1.x;
+						customAttribute.array[ offset_custom + 1  ] = v1.y;
+						customAttribute.array[ offset_custom + 2  ] = v1.z;
+						customAttribute.array[ offset_custom + 3  ] = v1.w;
+
+						customAttribute.array[ offset_custom + 4  ] = v2.x;
+						customAttribute.array[ offset_custom + 5  ] = v2.y;
+						customAttribute.array[ offset_custom + 6  ] = v2.z;
+						customAttribute.array[ offset_custom + 7  ] = v2.w;
+
+						customAttribute.array[ offset_custom + 8  ] = v3.x;
+						customAttribute.array[ offset_custom + 9  ] = v3.y;
+						customAttribute.array[ offset_custom + 10 ] = v3.z;
+						customAttribute.array[ offset_custom + 11 ] = v3.w;
+
+						offset_custom += 12;
+
+					}
+
+					for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
+
+						value = customAttribute.value[ chunk_faces4[ f ] ];
+
+						v1 = value[ 0 ];
+						v2 = value[ 1 ];
+						v3 = value[ 2 ];
+						v4 = value[ 3 ];
+
+						customAttribute.array[ offset_custom  ] 	= v1.x;
+						customAttribute.array[ offset_custom + 1  ] = v1.y;
+						customAttribute.array[ offset_custom + 2  ] = v1.z;
+						customAttribute.array[ offset_custom + 3  ] = v1.w;
+
+						customAttribute.array[ offset_custom + 4  ] = v2.x;
+						customAttribute.array[ offset_custom + 5  ] = v2.y;
+						customAttribute.array[ offset_custom + 6  ] = v2.z;
+						customAttribute.array[ offset_custom + 7  ] = v2.w;
+
+						customAttribute.array[ offset_custom + 8  ] = v3.x;
+						customAttribute.array[ offset_custom + 9  ] = v3.y;
+						customAttribute.array[ offset_custom + 10 ] = v3.z;
+						customAttribute.array[ offset_custom + 11 ] = v3.w;
+
+						customAttribute.array[ offset_custom + 12 ] = v4.x;
+						customAttribute.array[ offset_custom + 13 ] = v4.y;
+						customAttribute.array[ offset_custom + 14 ] = v4.z;
+						customAttribute.array[ offset_custom + 15 ] = v4.w;
+
+						offset_custom += 16;
+
+					}
+
+				}
+
+			}
+
+			renderer.setDynamicArrayBuffer( customAttribute.buffer, customAttribute.array);
+
+		}
+
+	}
+
+	if ( dispose ) {
+
+		delete geometryGroup.__inittedArrays;
+		delete geometryGroup.__colorArray;
+		delete geometryGroup.__normalArray;
+		delete geometryGroup.__tangentArray;
+		delete geometryGroup.__uvArray;
+		delete geometryGroup.__uv2Array;
+		delete geometryGroup.__faceArray;
+		delete geometryGroup.__vertexArray;
+		delete geometryGroup.__lineArray;
+		delete geometryGroup.__skinIndexArray;
+		delete geometryGroup.__skinWeightArray;
+
+	}
+
+};

+ 124 - 0
src/renderers/webgl/Objects/Object3DRenderer.js

@@ -0,0 +1,124 @@
+
+
+THREE.Object3DRenderer = function(lowlevelrenderer, info){
+	this.renderer = lowlevelrenderer;
+	this.info = info;
+};
+
+THREE.Object3DRenderer.prototype.getBufferMaterial = function( object, geometryGroup ) {
+
+	return object.material instanceof THREE.MeshFaceMaterial
+		? object.material.materials[ geometryGroup.materialIndex ]
+		: object.material;
+
+};
+
+THREE.Object3DRenderer.prototype.bufferGuessUVType = function( material ) {
+
+	// material must use some texture to require uvs
+
+	if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
+
+		return true;
+
+	}
+
+	return false;
+
+};
+
+THREE.Object3DRenderer.prototype.bufferGuessNormalType = function ( material ) {
+
+	// only MeshBasicMaterial and MeshDepthMaterial don't need normals
+
+	if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
+
+		return false;
+
+	}
+
+	if ( this.materialNeedsSmoothNormals( material ) ) {
+
+		return THREE.SmoothShading;
+
+	} else {
+
+		return THREE.FlatShading;
+
+	}
+
+};
+
+THREE.Object3DRenderer.prototype.materialNeedsSmoothNormals = function ( material ) {
+
+	return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
+
+};
+
+
+THREE.Object3DRenderer.prototype.bufferGuessVertexColorType = function ( material ) {
+
+	if ( material.vertexColors ) {
+
+		return material.vertexColors;
+
+	}
+
+	return false;
+
+};
+
+
+THREE.Object3DRenderer.prototype.initCustomAttributes = function( geometry, object ) {
+
+	var nvertices = geometry.vertices.length;
+
+	var material = object.material;
+
+	if ( material.attributes ) {
+
+		if ( geometry.__webglCustomAttributesList === undefined ) {
+
+			geometry.__webglCustomAttributesList = [];
+
+		}
+
+		for ( var a in material.attributes ) {
+
+			var attribute = material.attributes[ a ];
+
+			if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
+
+				attribute.__webglInitialized = true;
+
+				var size = 1;		// "f" and "i"
+
+				if ( attribute.type === "v2" ) size = 2;
+				else if ( attribute.type === "v3" ) size = 3;
+				else if ( attribute.type === "v4" ) size = 4;
+				else if ( attribute.type === "c"  ) size = 3;
+
+				attribute.size = size;
+
+				attribute.array = new Float32Array( nvertices * size );
+
+				attribute.buffer = this.renderer.createBuffer();
+				attribute.buffer.belongsToAttribute = a;
+
+				attribute.needsUpdate = true;
+
+			}
+
+			geometry.__webglCustomAttributesList.push( attribute );
+
+		}
+
+	}
+
+};
+
+THREE.Object3DRenderer.prototype.numericalSort = function( a, b ) {
+
+	return b[ 0 ] - a[ 0 ];
+
+};

+ 361 - 0
src/renderers/webgl/Objects/ParticleRenderer.js

@@ -0,0 +1,361 @@
+
+
+THREE.ParticleRenderer = function(lowlevelrenderer, info){
+	THREE.Object3DRenderer.call( this, lowlevelrenderer, info );
+	
+
+};
+
+
+THREE.ParticleRenderer.prototype = Object.create( THREE.Object3DRenderer.prototype );
+
+THREE.ParticleRenderer.prototype.createBuffers = function( geometry ) {
+	
+	var renderer = this.renderer;
+	geometry.__webglVertexBuffer = renderer.createBuffer();
+	geometry.__webglColorBuffer = renderer.createBuffer();
+
+	this.info.memory.geometries ++;
+};
+
+THREE.ParticleRenderer.prototype.initBuffers = function( geometry, object ) {
+
+	var nvertices = geometry.vertices.length;
+
+	geometry.__vertexArray = new Float32Array( nvertices * 3 );
+	geometry.__colorArray = new Float32Array( nvertices * 3 );
+
+	geometry.__sortArray = [];
+
+	geometry.__webglParticleCount = nvertices;
+
+	this.initCustomAttributes ( geometry, object );
+
+};
+
+
+THREE.ParticleRenderer.prototype.setBuffers = function( geometry, object , projectionScreenMatrix) {
+
+	var renderer = this.renderer;
+	var v, c, vertex, offset, index, color,
+
+	vertices = geometry.vertices,
+	vl = vertices.length,
+
+	colors = geometry.colors,
+	cl = colors.length,
+
+	vertexArray = geometry.__vertexArray,
+	colorArray = geometry.__colorArray,
+
+	sortArray = geometry.__sortArray,
+
+	dirtyVertices = geometry.verticesNeedUpdate,
+	dirtyElements = geometry.elementsNeedUpdate,
+	dirtyColors = geometry.colorsNeedUpdate,
+
+	customAttributes = geometry.__webglCustomAttributesList,
+	i, il,
+	a, ca, cal, value,
+	customAttribute;
+	
+	var _projScreenMatrixPS = THREE.ParticleRenderer._m1,
+		_vector3 = THREE.ParticleRenderer._v1;
+
+	if ( object.sortParticles ) {
+
+		_projScreenMatrixPS.copy( projectionScreenMatrix );
+		_projScreenMatrixPS.multiplySelf( object.matrixWorld );
+
+		for ( v = 0; v < vl; v ++ ) {
+
+			vertex = vertices[ v ];
+
+			_vector3.copy( vertex );
+			_projScreenMatrixPS.multiplyVector3( _vector3 );
+
+			sortArray[ v ] = [ _vector3.z, v ];
+
+		}
+
+		sortArray.sort( this.numericalSort );
+
+		for ( v = 0; v < vl; v ++ ) {
+
+			vertex = vertices[ sortArray[v][1] ];
+
+			offset = v * 3;
+
+			vertexArray[ offset ]     = vertex.x;
+			vertexArray[ offset + 1 ] = vertex.y;
+			vertexArray[ offset + 2 ] = vertex.z;
+
+		}
+
+		for ( c = 0; c < cl; c ++ ) {
+
+			offset = c * 3;
+
+			color = colors[ sortArray[c][1] ];
+
+			colorArray[ offset ]     = color.r;
+			colorArray[ offset + 1 ] = color.g;
+			colorArray[ offset + 2 ] = color.b;
+
+		}
+
+		if ( customAttributes ) {
+
+			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+				customAttribute = customAttributes[ i ];
+
+				if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
+
+				offset = 0;
+
+				cal = customAttribute.value.length;
+
+				if ( customAttribute.size === 1 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						index = sortArray[ ca ][ 1 ];
+
+						customAttribute.array[ ca ] = customAttribute.value[ index ];
+
+					}
+
+				} else if ( customAttribute.size === 2 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						index = sortArray[ ca ][ 1 ];
+
+						value = customAttribute.value[ index ];
+
+						customAttribute.array[ offset ] 	= value.x;
+						customAttribute.array[ offset + 1 ] = value.y;
+
+						offset += 2;
+
+					}
+
+				} else if ( customAttribute.size === 3 ) {
+
+					if ( customAttribute.type === "c" ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							index = sortArray[ ca ][ 1 ];
+
+							value = customAttribute.value[ index ];
+
+							customAttribute.array[ offset ]     = value.r;
+							customAttribute.array[ offset + 1 ] = value.g;
+							customAttribute.array[ offset + 2 ] = value.b;
+
+							offset += 3;
+
+						}
+
+					} else {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							index = sortArray[ ca ][ 1 ];
+
+							value = customAttribute.value[ index ];
+
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
+							customAttribute.array[ offset + 2 ] = value.z;
+
+							offset += 3;
+
+						}
+
+					}
+
+				} else if ( customAttribute.size === 4 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						index = sortArray[ ca ][ 1 ];
+
+						value = customAttribute.value[ index ];
+
+						customAttribute.array[ offset ]      = value.x;
+						customAttribute.array[ offset + 1  ] = value.y;
+						customAttribute.array[ offset + 2  ] = value.z;
+						customAttribute.array[ offset + 3  ] = value.w;
+
+						offset += 4;
+
+					}
+
+				}
+
+			}
+
+		}
+
+	} else {
+
+		if ( dirtyVertices ) {
+
+			for ( v = 0; v < vl; v ++ ) {
+
+				vertex = vertices[ v ];
+
+				offset = v * 3;
+
+				vertexArray[ offset ]     = vertex.x;
+				vertexArray[ offset + 1 ] = vertex.y;
+				vertexArray[ offset + 2 ] = vertex.z;
+
+			}
+
+		}
+
+		if ( dirtyColors ) {
+
+			for ( c = 0; c < cl; c ++ ) {
+
+				color = colors[ c ];
+
+				offset = c * 3;
+
+				colorArray[ offset ]     = color.r;
+				colorArray[ offset + 1 ] = color.g;
+				colorArray[ offset + 2 ] = color.b;
+
+			}
+
+		}
+
+		if ( customAttributes ) {
+
+			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+				customAttribute = customAttributes[ i ];
+
+				if ( customAttribute.needsUpdate &&
+					 ( customAttribute.boundTo === undefined ||
+					   customAttribute.boundTo === "vertices") ) {
+
+					cal = customAttribute.value.length;
+
+					offset = 0;
+
+					if ( customAttribute.size === 1 ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							customAttribute.array[ ca ] = customAttribute.value[ ca ];
+
+						}
+
+					} else if ( customAttribute.size === 2 ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
+
+							offset += 2;
+
+						}
+
+					} else if ( customAttribute.size === 3 ) {
+
+						if ( customAttribute.type === "c" ) {
+
+							for ( ca = 0; ca < cal; ca ++ ) {
+
+								value = customAttribute.value[ ca ];
+
+								customAttribute.array[ offset ] 	= value.r;
+								customAttribute.array[ offset + 1 ] = value.g;
+								customAttribute.array[ offset + 2 ] = value.b;
+
+								offset += 3;
+
+							}
+
+						} else {
+
+							for ( ca = 0; ca < cal; ca ++ ) {
+
+								value = customAttribute.value[ ca ];
+
+								customAttribute.array[ offset ] 	= value.x;
+								customAttribute.array[ offset + 1 ] = value.y;
+								customAttribute.array[ offset + 2 ] = value.z;
+
+								offset += 3;
+
+							}
+
+						}
+
+					} else if ( customAttribute.size === 4 ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ]      = value.x;
+							customAttribute.array[ offset + 1  ] = value.y;
+							customAttribute.array[ offset + 2  ] = value.z;
+							customAttribute.array[ offset + 3  ] = value.w;
+
+							offset += 4;
+
+						}
+
+					}
+
+				}
+
+			}
+
+		}
+
+	}
+
+	if ( dirtyVertices || object.sortParticles ) {
+		
+		renderer.setDynamicArrayBuffer(geometry.__webglVertexBuffer,vertexArray);
+
+	}
+
+	if ( dirtyColors || object.sortParticles ) {
+		
+		renderer.setDynamicArrayBuffer(geometry.__webglColorBuffer,colorArray);
+
+	}
+
+	if ( customAttributes ) {
+
+		for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+			customAttribute = customAttributes[ i ];
+
+			if ( customAttribute.needsUpdate || object.sortParticles ) {
+		
+				renderer.setDynamicArrayBuffer(customAttribute.buffer,customAttribute.array);
+
+			}
+
+		}
+
+	}
+
+
+};
+
+THREE.ParticleRenderer._m1 = new THREE.Matrix4();
+THREE.ParticleRenderer._v1 = new THREE.Vector3();

+ 206 - 0
src/renderers/webgl/Objects/RibbonRenderer.js

@@ -0,0 +1,206 @@
+
+
+THREE.RibbonRenderer = function(lowlevelrenderer, info){
+	THREE.Object3DRenderer.call( this, lowlevelrenderer, info );
+};
+
+
+THREE.RibbonRenderer.prototype = Object.create( THREE.Object3DRenderer.prototype );
+
+THREE.RibbonRenderer.prototype.createBuffers = function( geometry ) {
+	
+	var renderer = this.renderer;
+	geometry.__webglVertexBuffer = renderer.createBuffer();
+	geometry.__webglColorBuffer = renderer.createBuffer();
+	geometry.__webglNormalBuffer = renderer.createBuffer();
+
+	this.info.memory.geometries ++;
+};
+
+THREE.RibbonRenderer.prototype.initBuffers = function( geometry, object ) {
+	
+	var nvertices = geometry.vertices.length;
+	
+	geometry.__vertexArray = new Float32Array( nvertices * 3 );
+	geometry.__colorArray = new Float32Array( nvertices * 3 );
+	geometry.__normalArray = new Float32Array( nvertices * 3 );
+
+	geometry.__webglVertexCount = nvertices;
+
+	this.initCustomAttributes ( geometry, object );
+	
+};
+
+
+THREE.RibbonRenderer.prototype.setBuffers = function( geometry, object , projectionScreenMatrix) {
+	
+	var renderer = this.renderer;
+	var v, c, n, vertex, offset, color, normal,
+
+	i, il, ca, cal, customAttribute, value,
+
+	vertices = geometry.vertices,
+	colors = geometry.colors,
+	normals = geometry.normals,
+
+	vl = vertices.length,
+	cl = colors.length,
+	nl = normals.length,
+
+	vertexArray = geometry.__vertexArray,
+	colorArray = geometry.__colorArray,
+	normalArray = geometry.__normalArray,
+
+	dirtyVertices = geometry.verticesNeedUpdate,
+	dirtyColors = geometry.colorsNeedUpdate,
+	dirtyNormals = geometry.normalsNeedUpdate,
+
+	customAttributes = geometry.__webglCustomAttributesList;
+
+	if ( dirtyVertices ) {
+
+		for ( v = 0; v < vl; v ++ ) {
+
+			vertex = vertices[ v ];
+
+			offset = v * 3;
+
+			vertexArray[ offset ]     = vertex.x;
+			vertexArray[ offset + 1 ] = vertex.y;
+			vertexArray[ offset + 2 ] = vertex.z;
+
+		}
+
+		renderer.setDynamicArrayBuffer( geometry.__webglVertexBuffer,vertexArray);
+
+	}
+
+	if ( dirtyColors ) {
+
+		for ( c = 0; c < cl; c ++ ) {
+
+			color = colors[ c ];
+
+			offset = c * 3;
+
+			colorArray[ offset ]     = color.r;
+			colorArray[ offset + 1 ] = color.g;
+			colorArray[ offset + 2 ] = color.b;
+
+		}
+
+		renderer.setDynamicArrayBuffer( geometry.__webglColorBuffer, colorArray);
+
+	}
+
+	if ( dirtyNormals ) {
+
+		for ( n = 0; n < nl; n ++ ) {
+
+			normal = normals[ n ];
+
+			offset = n * 3;
+
+			normalArray[ offset ]     = normal.x;
+			normalArray[ offset + 1 ] = normal.y;
+			normalArray[ offset + 2 ] = normal.z;
+
+		}
+
+		renderer.setDynamicArrayBuffer( geometry.__webglNormalBuffer, normalArray);
+
+	}
+
+	if ( customAttributes ) {
+
+		for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
+
+			customAttribute = customAttributes[ i ];
+
+			if ( customAttribute.needsUpdate &&
+				 ( customAttribute.boundTo === undefined ||
+				   customAttribute.boundTo === "vertices" ) ) {
+
+				offset = 0;
+
+				cal = customAttribute.value.length;
+
+				if ( customAttribute.size === 1 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						customAttribute.array[ ca ] = customAttribute.value[ ca ];
+
+					}
+
+				} else if ( customAttribute.size === 2 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						value = customAttribute.value[ ca ];
+
+						customAttribute.array[ offset ] 	= value.x;
+						customAttribute.array[ offset + 1 ] = value.y;
+
+						offset += 2;
+
+					}
+
+				} else if ( customAttribute.size === 3 ) {
+
+					if ( customAttribute.type === "c" ) {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	= value.r;
+							customAttribute.array[ offset + 1 ] = value.g;
+							customAttribute.array[ offset + 2 ] = value.b;
+
+							offset += 3;
+
+						}
+
+					} else {
+
+						for ( ca = 0; ca < cal; ca ++ ) {
+
+							value = customAttribute.value[ ca ];
+
+							customAttribute.array[ offset ] 	= value.x;
+							customAttribute.array[ offset + 1 ] = value.y;
+							customAttribute.array[ offset + 2 ] = value.z;
+
+							offset += 3;
+
+						}
+
+					}
+
+				} else if ( customAttribute.size === 4 ) {
+
+					for ( ca = 0; ca < cal; ca ++ ) {
+
+						value = customAttribute.value[ ca ];
+
+						customAttribute.array[ offset ] 	 = value.x;
+						customAttribute.array[ offset + 1  ] = value.y;
+						customAttribute.array[ offset + 2  ] = value.z;
+						customAttribute.array[ offset + 3  ] = value.w;
+
+						offset += 4;
+
+					}
+
+				}
+
+				renderer.setDynamicArrayBuffer( customAttribute.buffer, customAttribute.array);
+
+			}
+
+		}
+
+	}
+
+};

+ 0 - 218
src/renderers/webgl/mesh.js

@@ -1,218 +0,0 @@
-
-
-
-THREE.WebGLRenderer2.Mesh = {
-	
-	createBuffers : function(renderer,geometryGroup,info){
-
-		geometryGroup.__webglVertexBuffer = renderer.createBuffer();
-		geometryGroup.__webglNormalBuffer = renderer.createBuffer();
-		geometryGroup.__webglTangentBuffer = renderer.createBuffer();
-		geometryGroup.__webglColorBuffer = renderer.createBuffer();
-		geometryGroup.__webglUVBuffer = renderer.createBuffer();
-		geometryGroup.__webglUV2Buffer = renderer.createBuffer();
-
-		geometryGroup.__webglSkinIndicesBuffer = renderer.createBuffer();
-		geometryGroup.__webglSkinWeightsBuffer = renderer.createBuffer();
-
-		geometryGroup.__webglFaceBuffer = renderer.createBuffer();
-		geometryGroup.__webglLineBuffer = renderer.createBuffer();
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			geometryGroup.__webglMorphTargetsBuffers = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				geometryGroup.__webglMorphTargetsBuffers.push( renderer.createBuffer() );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			geometryGroup.__webglMorphNormalsBuffers = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				geometryGroup.__webglMorphNormalsBuffers.push( renderer.createBuffer() );
-
-			}
-
-		}
-
-		info.memory.geometries ++;
-
-	
-	},
-	
-	initBuffers: function(renderer,geometryGroup, object){
-
-		var geometry = object.geometry,
-			faces3 = geometryGroup.faces3,
-			faces4 = geometryGroup.faces4,
-
-			nvertices = faces3.length * 3 + faces4.length * 4,
-			ntris     = faces3.length * 1 + faces4.length * 2,
-			nlines    = faces3.length * 3 + faces4.length * 4,
-
-			material = getBufferMaterial( object, geometryGroup ),
-
-			uvType = bufferGuessUVType( material ),
-			normalType = bufferGuessNormalType( material ),
-			vertexColorType = bufferGuessVertexColorType( material );
-
-		//console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
-
-		geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
-
-		if ( normalType ) {
-
-			geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
-
-		}
-
-		if ( geometry.hasTangents ) {
-
-			geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
-
-		}
-
-		if ( vertexColorType ) {
-
-			geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
-
-		}
-
-		if ( uvType ) {
-
-			if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
-
-				geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
-
-			}
-
-			if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
-
-				geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
-
-			}
-
-		}
-
-		if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
-
-			geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
-			geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
-
-		}
-
-		geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
-		geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			geometryGroup.__morphTargetsArrays = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			geometryGroup.__morphNormalsArrays = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
-
-			}
-
-		}
-
-		geometryGroup.__webglFaceCount = ntris * 3;
-		geometryGroup.__webglLineCount = nlines * 2;
-
-
-		// custom attributes
-
-		if ( material.attributes ) {
-
-			if ( geometryGroup.__webglCustomAttributesList === undefined ) {
-
-				geometryGroup.__webglCustomAttributesList = [];
-
-			}
-
-			for ( var a in material.attributes ) {
-
-				// Do a shallow copy of the attribute object so different geometryGroup chunks use different
-				// attribute buffers which are correctly indexed in the setMeshBuffers function
-
-				var originalAttribute = material.attributes[ a ];
-
-				var attribute = {};
-
-				for ( var property in originalAttribute ) {
-
-					attribute[ property ] = originalAttribute[ property ];
-
-				}
-
-				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
-
-					attribute.__webglInitialized = true;
-
-					var size = 1;		// "f" and "i"
-
-					if( attribute.type === "v2" ) size = 2;
-					else if( attribute.type === "v3" ) size = 3;
-					else if( attribute.type === "v4" ) size = 4;
-					else if( attribute.type === "c"  ) size = 3;
-
-					attribute.size = size;
-
-					attribute.array = new Float32Array( nvertices * size );
-
-					attribute.buffer = renderer.createBuffer();
-					attribute.buffer.belongsToAttribute = a;
-
-					originalAttribute.needsUpdate = true;
-					attribute.__original = originalAttribute;
-
-				}
-
-				geometryGroup.__webglCustomAttributesList.push( attribute );
-
-			}
-
-		}
-
-		geometryGroup.__inittedArrays = true;
-
-	
-	},
-	
-	bufferGuessUVType: function( material ) {
-
-		// material must use some texture to require uvs
-
-		if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
-
-			return true;
-
-		}
-
-		return false;
-
-	}
-};

+ 5 - 0
utils/includes/common.json

@@ -79,6 +79,11 @@
 	"../src/renderers/WebGLRenderer.js",
 	"../src/renderers/WebGLRenderer2.js",
 	"../src/renderers/webgl/renderer.js",
+	"../src/renderers/webgl/Objects/Object3DRenderer.js",
+	"../src/renderers/webgl/Objects/MeshRenderer.js",
+	"../src/renderers/webgl/Objects/ParticleRenderer.js",
+	"../src/renderers/webgl/Objects/LineRenderer.js",
+	"../src/renderers/webgl/Objects/RibbonRenderer.js",
 	"../src/renderers/WebGLRenderTarget.js",
 	"../src/renderers/WebGLRenderTargetCube.js",
 	"../src/renderers/renderables/RenderableVertex.js",

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