InstancedMesh.js 2.6 KB

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