InstancedMesh.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js';
  2. import { Mesh } from './Mesh.js';
  3. import { Matrix4 } from '../math/Matrix4.js';
  4. const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
  5. const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
  6. const _instanceIntersects = [];
  7. const _mesh = /*@__PURE__*/ new Mesh();
  8. class InstancedMesh extends Mesh {
  9. constructor( geometry, material, count ) {
  10. super( geometry, material );
  11. this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
  12. this.instanceColor = null;
  13. this.count = count;
  14. this.frustumCulled = false;
  15. }
  16. copy( source ) {
  17. super.copy( source );
  18. this.instanceMatrix.copy( source.instanceMatrix );
  19. if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
  20. this.count = source.count;
  21. return this;
  22. }
  23. getColorAt( index, color ) {
  24. color.fromArray( this.instanceColor.array, index * 3 );
  25. }
  26. getMatrixAt( index, matrix ) {
  27. matrix.fromArray( this.instanceMatrix.array, index * 16 );
  28. }
  29. raycast( raycaster, intersects ) {
  30. const matrixWorld = this.matrixWorld;
  31. const raycastTimes = this.count;
  32. _mesh.geometry = this.geometry;
  33. _mesh.material = this.material;
  34. if ( _mesh.material === undefined ) return;
  35. for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
  36. // calculate the world matrix for each instance
  37. this.getMatrixAt( instanceId, _instanceLocalMatrix );
  38. _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
  39. // the mesh represents this single instance
  40. _mesh.matrixWorld = _instanceWorldMatrix;
  41. _mesh.raycast( raycaster, _instanceIntersects );
  42. // process the result of raycast
  43. for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
  44. const intersect = _instanceIntersects[ i ];
  45. intersect.instanceId = instanceId;
  46. intersect.object = this;
  47. intersects.push( intersect );
  48. }
  49. _instanceIntersects.length = 0;
  50. }
  51. }
  52. setColorAt( index, color ) {
  53. if ( this.instanceColor === null ) {
  54. this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
  55. }
  56. color.toArray( this.instanceColor.array, index * 3 );
  57. }
  58. setMatrixAt( index, matrix ) {
  59. matrix.toArray( this.instanceMatrix.array, index * 16 );
  60. }
  61. updateMorphTargets() {
  62. }
  63. dispose() {
  64. this.dispatchEvent( { type: 'dispose' } );
  65. }
  66. }
  67. InstancedMesh.prototype.isInstancedMesh = true;
  68. export { InstancedMesh };