import { BufferGeometry , Color , Material , Quaternion , Vector3 } from 'three' ; import * as THREE from 'three' ; import index from '@bitowl/three-instanced-mesh' ; const ThreeInstancedMesh = index ( THREE ) ; const farAway = new Vector3 ( 1000000000 , 0 , 0 ) ; export interface InstancedMeshElement { pathName : string ; visible : boolean ; position : Vector3 ; quat : Quaternion ; scale : Vector3 ; color : Color ; } /**
 * Wrapper around InstancedMesh that handles passing in the arguments
 *
 * Defines a group of instances that use the same geometry
 */ export default class InstancedMeshGroup { private material : Material ; public instancedMesh ? : typeof ThreeInstancedMesh ; private geometry : BufferGeometry ; public nodes : InstancedMeshElement [ ] = [ ] ; constructor ( material , geometry ) { this . material = material ; this . geometry = geometry ; } public add ( node ) { const index = this . nodes . length ; this . nodes . push ( node ) ; return index ; } public buildInstancedMesh ( ) { this . instancedMesh = new ThreeInstancedMesh ( this . geometry , this . material , this . nodes . length , true , true , false ) ; this . fillAttributes ( ) ; return this . instancedMesh ; } public setTransform ( index , position , quaternion , scale ) { if ( this . instancedMesh === undefined ) { return ; } this . nodes [ index ] . position = position ; this . nodes [ index ] . quat = quaternion ; this . nodes [ index ] . scale = scale ; if ( this . nodes [ index ] . visible ) { this . instancedMesh . setPositionAt ( index , position ) ; } else { this . instancedMesh . setPositionAt ( index , farAway ) ; } this . instancedMesh . setQuaternionAt ( index , quaternion ) ; this . instancedMesh . setScaleAt ( index , scale ) ; this . instancedMesh . needsUpdate ( 'position' ) ; this . instancedMesh . needsUpdate ( 'quaternion' ) ; this . instancedMesh . needsUpdate ( 'scale' ) ; } public setVisible ( index , visible ) { if ( this . instancedMesh === undefined ) { return ; } this . nodes [ index ] . visible = visible ; if ( visible === true ) { this . instancedMesh . setPositionAt ( index , this . nodes [ index ] . position ) ; } else { this . instancedMesh . setPositionAt ( index , farAway ) ; } this . instancedMesh . needsUpdate ( 'position' ) ; } public setGeometry ( geometry ) { if ( this . instancedMesh === undefined ) { return ; } this . instancedMesh . geometry = geometry ; } public setColor ( index , color ) { if ( this . instancedMesh === undefined ) { return ; } this . instancedMesh . setColorAt ( index , color ) ; this . instancedMesh . needsUpdate ( 'colors' ) ; } public rebuild ( ) { this . instancedMesh ! . numInstances = this . nodes . length ; this . fillAttributes ( ) ; } private fillAttributes ( ) { for ( let i = 0 ; i < this . nodes . length ; i ++ ) { const node = this . nodes [ i ] ; this . instancedMesh ! . setQuaternionAt ( i , node . quat ) ; if ( node . visible === true ) { this . instancedMesh ! . setPositionAt ( i , node . position ) ; } else { this . instancedMesh ! . setPositionAt ( i , farAway ) ; } this . instancedMesh ! . setScaleAt ( i , node . scale ) ; this . instancedMesh ! . setColorAt ( i , node . color ) ; } } public dispose ( ) { } }