Procházet zdrojové kódy

GLTFExporter: Support EXT_mesh_gpu_instancing to export InstancedMesh. (#26854)

* Support EXT_mesh_gpu_instancing in GLTFExporter to export InstancedMesh.

* Update screen for misc_exporter_gltf example.

* Use _COLOR_0 in GLTFMeshGpuInstancing
Palash Bansal před 1 rokem
rodič
revize
b72b7dbd58

+ 69 - 1
examples/jsm/exporters/GLTFExporter.js

@@ -22,7 +22,8 @@ import {
 	Source,
 	SRGBColorSpace,
 	CompressedTexture,
-	Vector3
+	Vector3,
+	Quaternion,
 } from 'three';
 import { decompress } from './../utils/TextureUtils.js';
 
@@ -134,6 +135,12 @@ class GLTFExporter {
 
 		} );
 
+		this.register( function ( writer ) {
+
+			return new GLTFMeshGpuInstancing( writer );
+
+		} );
+
 	}
 
 	register( callback ) {
@@ -2962,6 +2969,67 @@ class GLTFMaterialsEmissiveStrengthExtension {
 
 }
 
+/**
+ * GPU Instancing Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
+ */
+class GLTFMeshGpuInstancing {
+
+	constructor( writer ) {
+
+		this.writer = writer;
+		this.name = 'EXT_mesh_gpu_instancing';
+
+	}
+
+	writeNode( object, nodeDef ) {
+
+		if ( ! object.isInstancedMesh ) return;
+
+		const writer = this.writer;
+
+		const mesh = object;
+
+		const translationAttr = new Float32Array( mesh.count * 3 );
+		const rotationAttr = new Float32Array( mesh.count * 4 );
+		const scaleAttr = new Float32Array( mesh.count * 3 );
+
+		const matrix = new Matrix4();
+		const position = new Vector3();
+		const quaternion = new Quaternion();
+		const scale = new Vector3();
+
+		for ( let i = 0; i < mesh.count; i ++ ) {
+
+			mesh.getMatrixAt( i, matrix );
+			matrix.decompose( position, quaternion, scale );
+
+			position.toArray( translationAttr, i * 3 );
+			quaternion.toArray( rotationAttr, i * 4 );
+			scale.toArray( scaleAttr, i * 3 );
+
+		}
+
+		const attributes = {
+			TRANSLATION: writer.processAccessor( new BufferAttribute( translationAttr, 3 ) ),
+			ROTATION: writer.processAccessor( new BufferAttribute( rotationAttr, 4 ) ),
+			SCALE: writer.processAccessor( new BufferAttribute( scaleAttr, 3 ) ),
+		};
+
+		if ( mesh.instanceColor )
+			attributes._COLOR_0 = writer.processAccessor( mesh.instanceColor );
+
+		nodeDef.extensions = nodeDef.extensions || {};
+		nodeDef.extensions[ this.name ] = { attributes };
+
+		writer.extensionsUsed[ this.name ] = true;
+		writer.extensionsRequired[ this.name ] = true;
+
+	}
+
+}
+
 /**
  * Static utility functions
  */

+ 8 - 2
examples/jsm/loaders/GLTFLoader.js

@@ -62,7 +62,8 @@ import {
 	Vector2,
 	Vector3,
 	VectorKeyframeTrack,
-	SRGBColorSpace
+	SRGBColorSpace,
+	InstancedBufferAttribute
 } from 'three';
 import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js';
 
@@ -1679,7 +1680,12 @@ class GLTFMeshGpuInstancing {
 				// Add instance attributes to the geometry, excluding TRS.
 				for ( const attributeName in attributes ) {
 
-					if ( attributeName !== 'TRANSLATION' &&
+					if ( attributeName === '_COLOR_0' ) {
+
+						const attr = attributes[ attributeName ];
+						instancedMesh.instanceColor = new InstancedBufferAttribute( attr.array, attr.itemSize, attr.normalized );
+
+					} else if ( attributeName !== 'TRANSLATION' &&
 						 attributeName !== 'ROTATION' &&
 						 attributeName !== 'SCALE' ) {
 

+ 21 - 0
examples/misc_exporter_gltf.html

@@ -427,6 +427,27 @@
 
 				} );
 
+				// ---------------------------------------------------------------------
+				// Model requiring KHR_mesh_quantization
+				// ---------------------------------------------------------------------
+
+				material = new THREE.MeshBasicMaterial( {
+					color: 0xffffff,
+				} );
+				object = new THREE.InstancedMesh( new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 ), material, 50 );
+				const matrix = new THREE.Matrix4();
+				const color = new THREE.Color();
+				for ( let i = 0; i < 50; i ++ ) {
+
+					matrix.setPosition( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 );
+					object.setMatrixAt( i, matrix );
+					object.setColorAt( i, color.setHSL( i / 50, 1, 0.5 ) );
+
+				}
+
+				object.position.set( 400, 0, 200 );
+				scene1.add( object );
+
 				// ---------------------------------------------------------------------
 				// 2nd THREE.Scene
 				// ---------------------------------------------------------------------

binární
examples/screenshots/misc_exporter_gltf.jpg