Przeglądaj źródła

SceneUtils: Add createMeshesFromMultiMaterialMesh(). (#23762)

Michael Herzog 3 lat temu
rodzic
commit
7dfd164177

+ 8 - 0
docs/examples/en/utils/SceneUtils.html

@@ -22,6 +22,14 @@
 		Creates a new group object that contains a new mesh for each instance of the given instanced mesh.
 		</p>
 
+		<h3>[method:Group createMeshesFromMultiMaterialMesh]( [param:Mesh mesh] )</h3>
+		<p>
+		mesh -- A mesh with multiple materials.
+		</p>
+		<p>
+		Converts the given multi-material mesh into an instance of [page:Group] holding for each material a separate mesh.
+		</p>
+
 		<h3>[method:Group createMultiMaterialObject]( [param:BufferGeometry geometry], [param:Array materials] )</h3>
 		<p>
 		geometry -- The geometry for the set of materials. <br />

+ 8 - 0
docs/examples/zh/utils/SceneUtils.html

@@ -22,6 +22,14 @@
 			为给定的实例化网格的每个实例,创建一个包含新网格的新物体组(Object Group)。
 		</p>
 
+		<h3>[method:Group createMeshesFromMultiMaterialMesh]( [param:Mesh mesh] )</h3>
+		<p>
+		mesh -- A mesh with multiple materials.
+		</p>
+		<p>
+		Converts the given multi-material mesh into an instance of [page:Group] holding for each material a separate mesh.
+		</p>
+
 		<h3>[method:Group createMultiMaterialObject]( [param:BufferGeometry geometry], [param:Array materials] )</h3>
 		<p>
 			geometry -- 材料集的几何形状。 <br />

+ 76 - 2
examples/jsm/utils/SceneUtils.js

@@ -1,9 +1,11 @@
 import {
 	Group,
-	Mesh
+	Mesh,
+	BufferAttribute,
+	BufferGeometry
 } from 'three';
 
-
+import { mergeGroups } from './BufferGeometryUtils.js';
 
 function createMeshesFromInstancedMesh( instancedMesh ) {
 
@@ -31,6 +33,77 @@ function createMeshesFromInstancedMesh( instancedMesh ) {
 
 }
 
+function createMeshesFromMultiMaterialMesh( mesh ) {
+
+	if ( Array.isArray( mesh.material ) === false ) {
+
+		console.warn( 'THREE.SceneUtils.createMeshesFromMultiMaterialMesh(): The given mesh has no multiple materials.' );
+		return mesh;
+
+	}
+
+	const object = new Group();
+	object.copy( mesh );
+
+	// merge groups (which automatically sorts them)
+
+	const geometry = mergeGroups( mesh.geometry );
+
+	const index = geometry.index;
+	const groups = geometry.groups;
+	const attributeNames = Object.keys( geometry.attributes );
+
+	// create a mesh for each group by extracting the buffer data into a new geometry
+
+	for ( let i = 0; i < groups.length; i ++ ) {
+
+		const group = groups[ i ];
+
+		const start = group.start;
+		const end = start + group.count;
+
+		const newGeometry = new BufferGeometry();
+		const newMaterial = mesh.material[ group.materialIndex ];
+
+		// process all buffer attributes
+
+		for ( let j = 0; j < attributeNames.length; j ++ ) {
+
+			const name = attributeNames[ j ];
+			const attribute = geometry.attributes[ name ];
+			const itemSize = attribute.itemSize;
+
+			const newLength = group.count * itemSize;
+			const type = attribute.array.constructor;
+
+			const newArray = new type( newLength );
+			const newAttribute = new BufferAttribute( newArray, itemSize );
+
+			for ( let k = start, n = 0; k < end; k ++, n ++ ) {
+
+				const ind = index.getX( k );
+
+				if ( itemSize >= 1 ) newAttribute.setX( n, attribute.getX( ind ) );
+				if ( itemSize >= 2 ) newAttribute.setY( n, attribute.getY( ind ) );
+				if ( itemSize >= 3 ) newAttribute.setZ( n, attribute.getZ( ind ) );
+				if ( itemSize >= 4 ) newAttribute.setW( n, attribute.getW( ind ) );
+
+			}
+
+
+			newGeometry.setAttribute( name, newAttribute );
+
+		}
+
+		const newMesh = new Mesh( newGeometry, newMaterial );
+		object.add( newMesh );
+
+	}
+
+	return object;
+
+}
+
 function createMultiMaterialObject( geometry, materials ) {
 
 	const group = new Group();
@@ -65,6 +138,7 @@ function attach( child, scene, parent ) {
 
 export {
 	createMeshesFromInstancedMesh,
+	createMeshesFromMultiMaterialMesh,
 	createMultiMaterialObject,
 	detach,
 	attach,