소스 검색

Let MMDLoader generate BufferGeometry (#9921)

* Let MMDLoader generate BufferGeometry

* Remove unnecessary lines from MMDLoader
Takahiro 8 년 전
부모
커밋
3140f4a61e
1개의 변경된 파일139개의 추가작업 그리고 100개의 파일을 삭제
  1. 139 100
      examples/js/loaders/MMDLoader.js

+ 139 - 100
examples/js/loaders/MMDLoader.js

@@ -1231,6 +1231,22 @@ THREE.MMDLoader.prototype.parsePmx = function ( buffer ) {
 					m.uv = dv.getFloat32Array( 4 );
 					p.elements.push( m );
 
+				} else if ( p.type === 4 ) {  // additional uv1
+
+					// TODO: implement
+
+				} else if ( p.type === 5 ) {  // additional uv2
+
+					// TODO: implement
+
+				} else if ( p.type === 6 ) {  // additional uv3
+
+					// TODO: implement
+
+				} else if ( p.type === 7 ) {  // additional uv4
+
+					// TODO: implement
+
 				} else if ( p.type === 8 ) {  // material morph
 
 					var m = {};
@@ -1681,41 +1697,54 @@ THREE.MMDLoader.prototype.parseVpd = function ( text ) {
 THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress, onError ) {
 
 	var scope = this;
-	var geometry = new THREE.Geometry();
-        var material = new THREE.MultiMaterial();
+	var geometry = new THREE.BufferGeometry();
+	var material = new THREE.MultiMaterial();
 	var helper = new THREE.MMDLoader.DataCreationHelper();
 
+	var buffer = {};
+
+	buffer.vertices = [];
+	buffer.uvs = [];
+	buffer.normals = [];
+	buffer.skinIndices = [];
+	buffer.skinWeights = [];
+	buffer.indices = [];
+
 	var initVartices = function () {
 
 		for ( var i = 0; i < model.metadata.vertexCount; i++ ) {
 
 			var v = model.vertices[ i ];
 
-			geometry.vertices.push(
-				new THREE.Vector3(
-					v.position[ 0 ],
-					v.position[ 1 ],
-					v.position[ 2 ]
-				)
-			);
+			for ( var j = 0, jl = v.position.length; j < jl; j ++ ) {
 
-			geometry.skinIndices.push(
-				new THREE.Vector4(
-					v.skinIndices.length >= 1 ? v.skinIndices[ 0 ] : 0.0,
-					v.skinIndices.length >= 2 ? v.skinIndices[ 1 ] : 0.0,
-					v.skinIndices.length >= 3 ? v.skinIndices[ 2 ] : 0.0,
-					v.skinIndices.length >= 4 ? v.skinIndices[ 3 ] : 0.0
-				)
-			);
+				buffer.vertices.push( v.position[ j ] );
 
-			geometry.skinWeights.push(
-				new THREE.Vector4(
-					v.skinWeights.length >= 1 ? v.skinWeights[ 0 ] : 0.0,
-					v.skinWeights.length >= 2 ? v.skinWeights[ 1 ] : 0.0,
-					v.skinWeights.length >= 3 ? v.skinWeights[ 2 ] : 0.0,
-					v.skinWeights.length >= 4 ? v.skinWeights[ 3 ] : 0.0
-				)
-			);
+			}
+
+			for ( var j = 0, jl = v.normal.length; j < jl; j ++ ) {
+
+				buffer.normals.push( v.normal[ j ] );
+
+			}
+
+			for ( var j = 0, jl = v.uv.length; j < jl; j ++ ) {
+
+				buffer.uvs.push( v.uv[ j ] );
+
+			}
+
+			for ( var j = 0; j < 4; j ++ ) {
+
+				buffer.skinIndices.push( v.skinIndices.length - 1 >= j ? v.skinIndices[ j ] : 0.0 );
+
+			}
+
+			for ( var j = 0; j < 4; j ++ ) {
+
+				buffer.skinWeights.push( v.skinWeights.length - 1 >= j ? v.skinWeights[ j ] : 0.0 );
+
+			}
 
 		}
 
@@ -1725,22 +1754,11 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 		for ( var i = 0; i < model.metadata.faceCount; i++ ) {
 
-			geometry.faces.push(
-				new THREE.Face3(
-					model.faces[ i ].indices[ 0 ],
-					model.faces[ i ].indices[ 1 ],
-					model.faces[ i ].indices[ 2 ]
-				)
-			);
+			var f = model.faces[ i ];
 
-			for ( var j = 0; j < 3; j++ ) {
+			for ( var j = 0, jl = f.indices.length; j < jl; j ++ ) {
 
-				geometry.faces[ i ].vertexNormals[ j ] =
-					new THREE.Vector3(
-						model.vertices[ model.faces[ i ].indices[ j ] ].normal[ 0 ],
-						model.vertices[ model.faces[ i ].indices[ j ] ].normal[ 1 ],
-						model.vertices[ model.faces[ i ].indices[ j ] ].normal[ 2 ]
-					);
+				buffer.indices.push( f.indices[ j ] );
 
 			}
 
@@ -1905,15 +1923,15 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 	var initMorphs = function () {
 
-		function updateVertex ( params, index, v, ratio ) {
+		function updateVertex( attribute, index, v, ratio ) {
 
-			params.vertices[ index ].x += v.position[ 0 ] * ratio;
-			params.vertices[ index ].y += v.position[ 1 ] * ratio;
-			params.vertices[ index ].z += v.position[ 2 ] * ratio;
+			attribute.array[ index * 3 + 0 ] += v.position[ 0 ] * ratio;
+			attribute.array[ index * 3 + 1 ] += v.position[ 1 ] * ratio;
+			attribute.array[ index * 3 + 2 ] += v.position[ 2 ] * ratio;
 
 		};
 
-		function updateVertices ( params, m, ratio ) {
+		function updateVertices( attribute, m, ratio ) {
 
 			for ( var i = 0; i < m.elementCount; i++ ) {
 
@@ -1931,26 +1949,25 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 				}
 
-				updateVertex( params, index, v, ratio );
+				updateVertex( attribute, index, v, ratio );
 
 			}
 
 		};
 
+		var morphTargets = [];
+		var attributes = [];
+
 		for ( var i = 0; i < model.metadata.morphCount; i++ ) {
 
 			var m = model.morphs[ i ];
-			var params = {};
+			var params = { name: m.name };
 
-			params.name = m.name;
-			params.vertices = [];
+			var attribute = new THREE.Float32Attribute( model.metadata.vertexCount * 3, 3 );
 
-			for ( var j = 0; j < model.metadata.vertexCount; j++ ) {
+			for ( var j = 0; j < model.metadata.vertexCount * 3; j++ ) {
 
-				params.vertices[ j ] = new THREE.Vector3( 0, 0, 0 );
-				params.vertices[ j ].x = geometry.vertices[ j ].x;
-				params.vertices[ j ].y = geometry.vertices[ j ].y;
-				params.vertices[ j ].z = geometry.vertices[ j ].z;
+				attribute.array[ j ] = buffer.vertices[ j ];
 
 			}
 
@@ -1958,13 +1975,13 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 				if ( i !== 0 ) {
 
-					updateVertices( params, m, 1.0 );
+					updateVertices( attribute, m, 1.0 );
 
 				}
 
 			} else {
 
-				if ( m.type === 0 ) {
+				if ( m.type === 0 ) {    // group
 
 					for ( var j = 0; j < m.elementCount; j++ ) {
 
@@ -1973,25 +1990,60 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 						if ( m2.type === 1 ) {
 
-							updateVertices( params, m2, ratio );
+							updateVertices( attribute, m2, ratio );
+
+						} else {
+
+							// TODO: implement
 
 						}
 
 					}
 
-				} else if ( m.type === 1 ) {
+				} else if ( m.type === 1 ) {    // vertex
+
+					updateVertices( attribute, m, 1.0 );
+
+				} else if ( m.type === 2 ) {    // bone
 
-					updateVertices( params, m, 1.0 );
+					// TODO: implement
+
+				} else if ( m.type === 3 ) {    // uv
+
+					// TODO: implement
+
+				} else if ( m.type === 4 ) {    // additional uv1
+
+					// TODO: implement
+
+				} else if ( m.type === 5 ) {    // additional uv2
+
+					// TODO: implement
+
+				} else if ( m.type === 6 ) {    // additional uv3
+
+					// TODO: implement
+
+				} else if ( m.type === 7 ) {    // additional uv4
+
+					// TODO: implement
+
+				} else if ( m.type === 8 ) {    // material
+
+					// TODO: implement
 
 				}
 
 			}
 
-			// TODO: skip if this's non-vertex morphing of PMX to reduce CPU/Memory use
-			geometry.morphTargets.push( params );
+			morphTargets.push( params );
+			attributes.push( attribute );
 
 		}
 
+		geometry.morphTargets = morphTargets;
+		geometry.morphAttributes.position = attributes;
+
 	};
 
 	var initMaterials = function () {
@@ -2066,12 +2118,6 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 		};
 
-		for ( var i = 0; i < model.metadata.materialCount; i++ ) {
-
-			geometry.faceVertexUvs.push( [] );
-
-		}
-
 		for ( var i = 0; i < model.metadata.materialCount; i++ ) {
 
 			var m = model.materials[ i ];
@@ -2080,24 +2126,7 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 			params.faceOffset = offset;
 			params.faceNum = m.faceCount;
 
-			for ( var j = 0; j < m.faceCount; j++ ) {
-
-				geometry.faces[ offset ].materialIndex = i;
-
-				var uvs = [];
-
-				for ( var k = 0; k < 3; k++ ) {
-
-					var v = model.vertices[ model.faces[ offset ].indices[ k ] ];
-					uvs.push( new THREE.Vector2( v.uv[ 0 ], v.uv[ 1 ] ) );
-
-				}
-
-				geometry.faceVertexUvs[ 0 ].push( uvs );
-
-				offset++;
-
-			}
+			offset += m.faceCount;
 
 			params.name = m.name;
 			params.color = color.fromArray( [ m.diffuse[ 0 ], m.diffuse[ 1 ], m.diffuse[ 2 ] ] ).clone();
@@ -2217,8 +2246,7 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 				fragmentShader: shader.fragmentShader
 			} );
 
-			m.faceOffset = p.faceOffset;
-			m.faceNum = p.faceNum;
+			geometry.addGroup( p.faceOffset * 3, p.faceNum * 3, i );
 
 			if ( p.name !== undefined ) m.name = p.name;
 
@@ -2237,6 +2265,9 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 			if ( p.map !== undefined ) {
 
+				m.faceOffset = p.faceOffset;
+				m.faceNum = p.faceNum;
+
 				// Check if this part of the texture image the material uses requires transparency
 				function checkTextureTransparency ( m ) {
 
@@ -2256,7 +2287,7 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 						};
 
-						function detectTextureTransparency ( image, uvs ) {
+						function detectTextureTransparency( image, uvs, indices ) {
 
 							var width = image.width;
 							var height = image.height;
@@ -2269,13 +2300,14 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 							}
 
-							for ( var i = 0; i < uvs.length; i++ ) {
+							for ( var i = 0; i < indices.length; i += 3 ) {
 
 								var centerUV = { x: 0.0, y: 0.0 };
 
 								for ( var j = 0; j < 3; j++ ) {
 
-									var uv = uvs[ i ][ j ];
+									var index = indices[ i * 3 + j ];
+									var uv = { x: uvs[ index * 2 + 0 ], y: uvs[ index * 2 + 1 ] };
 
 									if ( getAlphaByUv( image, uv ) < threshold ) {
 
@@ -2291,7 +2323,6 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 								centerUV.x /= 3;
 								centerUV.y /= 3;
 
-
 								if ( getAlphaByUv( image, centerUV ) < threshold ) {
 
 									return true;
@@ -2338,9 +2369,9 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 						};
 
 						var imageData = t.image.data !== undefined ? t.image : createImageData( t.image );
-						var uvs = geometry.faceVertexUvs[ 0 ].slice( m.faceOffset, m.faceOffset + m.faceNum );
+						var indices = geometry.index.array.slice( m.faceOffset * 3, m.faceOffset * 3 + m.faceNum * 3 );
 
-						if ( detectTextureTransparency( imageData, uvs ) ) m.transparent = true;
+						if ( detectTextureTransparency( imageData, geometry.attributes.uv.array, indices ) ) m.transparent = true;
 
 						delete m.faceOffset;
 						delete m.faceNum;
@@ -2582,8 +2613,7 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 			var bodyB = rigidBodies[ p.rigidBodyIndex2 ];
 
 			/*
-			 * Refer http://www20.atpages.jp/katwat/wp/?p=4135
-			 * for what this is for
+			 * Refer to http://www20.atpages.jp/katwat/wp/?p=4135
 			 */
 			if ( bodyA.type !== 0 && bodyB.type === 2 ) {
 
@@ -2605,6 +2635,20 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 
 	};
 
+	var initGeometry = function () {
+
+		geometry.setIndex( ( buffer.indices.length > 65535 ? THREE.Uint32Attribute : THREE.Uint16Attribute )( buffer.indices, 1 ) );
+		geometry.addAttribute( 'position', THREE.Float32Attribute( buffer.vertices, 3 ) );
+		geometry.addAttribute( 'normal', THREE.Float32Attribute( buffer.normals, 3 ) );
+		geometry.addAttribute( 'uv', THREE.Float32Attribute( buffer.uvs, 2 ) );
+		geometry.addAttribute( 'skinIndex', THREE.Float32Attribute( buffer.skinIndices, 4 ) );
+		geometry.addAttribute( 'skinWeight', THREE.Float32Attribute( buffer.skinWeights, 4 ) );
+
+		geometry.computeBoundingSphere();
+		geometry.mmdFormat = model.metadata.format;
+
+	};
+
 	this.leftToRightModel( model );
 
 	initVartices();
@@ -2615,12 +2659,7 @@ THREE.MMDLoader.prototype.createMesh = function ( model, texturePath, onProgress
 	initMorphs();
 	initMaterials();
 	initPhysics();
-
-	geometry.computeFaceNormals();
-	geometry.verticesNeedUpdate = true;
-	geometry.normalsNeedUpdate = true;
-	geometry.uvsNeedUpdate = true;
-	geometry.mmdFormat = model.metadata.format;
+	initGeometry();
 
 	var mesh = new THREE.SkinnedMesh( geometry, material );