three#InstancedMesh JavaScript Examples

The following examples show how to use three#InstancedMesh. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Entities.js    From webmc with MIT License 5 votes vote down vote up
constructor (game) {
    this.game = game

    this.mobMaterial = new MeshStandardMaterial({
      color: new Color('red')
    })
    this.mobGeometry = new BoxGeometry(1, 1, 1)
    this.mobMaxCount = 1000
    this.mobMesh = new InstancedMesh(
      this.mobGeometry,
      this.mobMaterial,
      this.mobMaxCount
    )
    this.mobMesh.instanceMatrix.setUsage(DynamicDrawUsage)
    this.game.scene.add(this.mobMesh)

    this.playerMaterial = new MeshStandardMaterial({
      color: new Color('blue')
    })
    this.playerGeometry = new BoxGeometry(1, 1, 1)
    this.playerMaxCount = 1000
    this.playerMesh = new InstancedMesh(
      this.playerGeometry,
      this.playerMaterial,
      this.playerMaxCount
    )
    this.playerMesh.instanceMatrix.setUsage(DynamicDrawUsage)
    this.game.scene.add(this.playerMesh)

    this.objectMaterial = new MeshStandardMaterial({
      color: new Color('green')
    })
    this.objectGeometry = new BoxGeometry(0.25, 0.25, 0.25)
    this.objectMaxCount = 1000
    this.objectMesh = new InstancedMesh(
      this.objectGeometry,
      this.objectMaterial,
      this.objectMaxCount
    )
    this.objectMesh.instanceMatrix.setUsage(DynamicDrawUsage)
    this.game.scene.add(this.objectMesh)

    this.dummy = new Object3D()
  }
Example #2
Source File: I3DMLoader.js    From 3DTilesRendererJS with Apache License 2.0 4 votes vote down vote up
parse( buffer ) {

		return super
			.parse( buffer )
			.then( i3dm => {

				const { featureTable, batchTable } = i3dm;
				const gltfBuffer = i3dm.glbBytes.slice().buffer;
				return new Promise( ( resolve, reject ) => {

					const fetchOptions = this.fetchOptions;
					const manager = this.manager;
					const loader = manager.getHandler( 'path.gltf' ) || new GLTFLoader( manager );

					if ( fetchOptions.credentials === 'include' && fetchOptions.mode === 'cors' ) {

						loader.setCrossOrigin( 'use-credentials' );

					}

					if ( 'credentials' in fetchOptions ) {

						loader.setWithCredentials( fetchOptions.credentials === 'include' );

					}

					if ( fetchOptions.headers ) {

						loader.setRequestHeader( fetchOptions.headers );

					}

					// GLTFLoader assumes the working path ends in a slash
					let workingPath = this.workingPath;
					if ( ! /[\\/]$/.test( workingPath ) ) {

						workingPath += '/';

					}

					const adjustmentTransform = this.adjustmentTransform;

					loader.parse( gltfBuffer, workingPath, model => {

						const INSTANCES_LENGTH = featureTable.getData( 'INSTANCES_LENGTH' );
						const POSITION = featureTable.getData( 'POSITION', INSTANCES_LENGTH, 'FLOAT', 'VEC3' );
						const NORMAL_UP = featureTable.getData( 'NORMAL_UP', INSTANCES_LENGTH, 'FLOAT', 'VEC3' );
						const NORMAL_RIGHT = featureTable.getData( 'NORMAL_RIGHT', INSTANCES_LENGTH, 'FLOAT', 'VEC3' );
						const SCALE_NON_UNIFORM = featureTable.getData( 'SCALE_NON_UNIFORM', INSTANCES_LENGTH, 'FLOAT', 'VEC3' );
						const SCALE = featureTable.getData( 'SCALE', INSTANCES_LENGTH, 'FLOAT', 'SCALAR' );

						[
							'RTC_CENTER',
							'QUANTIZED_VOLUME_OFFSET',
							'QUANTIZED_VOLUME_SCALE',
							'EAST_NORTH_UP',
							'POSITION_QUANTIZED',
							'NORMAL_UP_OCT32P',
							'NORMAL_RIGHT_OCT32P',
						].forEach( feature => {

							if ( feature in featureTable.header ) {

								console.warn( `I3DMLoader: Unsupported FeatureTable feature "${ feature }" detected.` );

							}

						} );

						const instanceMap = new Map();
						const instances = [];
						model.scene.traverse( child => {

							if ( child.isMesh ) {

								const { geometry, material } = child;
								const instancedMesh = new InstancedMesh( geometry, material, INSTANCES_LENGTH );
								instancedMesh.position.copy( child.position );
								instancedMesh.rotation.copy( child.rotation );
								instancedMesh.scale.copy( child.scale );
								instances.push( instancedMesh );
								instanceMap.set( child, instancedMesh );

							}

						} );

						const averageVector = new Vector3();
						for ( let i = 0; i < INSTANCES_LENGTH; i ++ ) {

							averageVector.x += POSITION[ i * 3 + 0 ] / INSTANCES_LENGTH;
							averageVector.y += POSITION[ i * 3 + 1 ] / INSTANCES_LENGTH;
							averageVector.z += POSITION[ i * 3 + 2 ] / INSTANCES_LENGTH;

						}

						// replace the meshes with instanced meshes
						instanceMap.forEach( ( instancedMesh, mesh ) => {

							const parent = mesh.parent;
							if ( parent ) {

								// Mesh have no children
								parent.remove( mesh );
								parent.add( instancedMesh );

								// Center the instance around an average point to avoid jitter at large scales.
								// Transform the average vector by matrix world so we can account for any existing
								// transforms of the instanced mesh.
								instancedMesh.updateMatrixWorld();
								instancedMesh
									.position
									.copy( averageVector )
									.applyMatrix4( instancedMesh.matrixWorld );

							}

						} );

						for ( let i = 0; i < INSTANCES_LENGTH; i ++ ) {

							// position
							tempPos.set(
								POSITION[ i * 3 + 0 ] - averageVector.x,
								POSITION[ i * 3 + 1 ] - averageVector.y,
								POSITION[ i * 3 + 2 ] - averageVector.z,
							);

							// rotation
							if ( NORMAL_UP ) {

								tempUp.set(
									NORMAL_UP[ i * 3 + 0 ],
									NORMAL_UP[ i * 3 + 1 ],
									NORMAL_UP[ i * 3 + 2 ],
								);

								tempRight.set(
									NORMAL_RIGHT[ i * 3 + 0 ],
									NORMAL_RIGHT[ i * 3 + 1 ],
									NORMAL_RIGHT[ i * 3 + 2 ],
								);

								tempFwd.crossVectors( tempRight, tempUp )
									.normalize();

								tempMat.makeBasis(
									tempRight,
									tempUp,
									tempFwd,
								);

								tempQuat.setFromRotationMatrix( tempMat );

							} else {

								tempQuat.set( 0, 0, 0, 1 );

							}

							// scale
							if ( SCALE ) {

								tempSca.setScalar( SCALE[ i ] );

							} else if ( SCALE_NON_UNIFORM ) {

								tempSca.set(
									SCALE_NON_UNIFORM[ i * 3 + 0 ],
									SCALE_NON_UNIFORM[ i * 3 + 1 ],
									SCALE_NON_UNIFORM[ i * 3 + 2 ],
								);

							} else {

								tempSca.set( 1, 1, 1 );

							}


							tempMat.compose( tempPos, tempQuat, tempSca ).multiply( adjustmentTransform );

							for ( let j = 0, l = instances.length; j < l; j ++ ) {

								const instance = instances[ j ];
								instance.setMatrixAt( i, tempMat );

							}

						}


						model.batchTable = batchTable;
						model.featureTable = featureTable;

						model.scene.batchTable = batchTable;
						model.scene.featureTable = featureTable;

						resolve( model );

					}, reject );

				} );

			} );

	}