File size: 2,454 Bytes
2b7aae2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js';
import { Mesh } from './Mesh.js';
import { Matrix4 } from '../math/Matrix4.js';

const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();

const _instanceIntersects = [];

const _mesh = /*@__PURE__*/ new Mesh();

class InstancedMesh extends Mesh {
	constructor(geometry, material, count) {
		super(geometry, material);

		this.instanceMatrix = new InstancedBufferAttribute(new Float32Array(count * 16), 16);
		this.instanceColor = null;

		this.count = count;

		this.frustumCulled = false;
	}

	copy(source) {
		super.copy(source);

		this.instanceMatrix.copy(source.instanceMatrix);

		if (source.instanceColor !== null) this.instanceColor = source.instanceColor.clone();

		this.count = source.count;

		return this;
	}

	getColorAt(index, color) {
		color.fromArray(this.instanceColor.array, index * 3);
	}

	getMatrixAt(index, matrix) {
		matrix.fromArray(this.instanceMatrix.array, index * 16);
	}

	raycast(raycaster, intersects) {
		const matrixWorld = this.matrixWorld;
		const raycastTimes = this.count;

		_mesh.geometry = this.geometry;
		_mesh.material = this.material;

		if (_mesh.material === undefined) return;

		for (let instanceId = 0; instanceId < raycastTimes; instanceId++) {
			// calculate the world matrix for each instance

			this.getMatrixAt(instanceId, _instanceLocalMatrix);

			_instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix);

			// the mesh represents this single instance

			_mesh.matrixWorld = _instanceWorldMatrix;

			_mesh.raycast(raycaster, _instanceIntersects);

			// process the result of raycast

			for (let i = 0, l = _instanceIntersects.length; i < l; i++) {
				const intersect = _instanceIntersects[i];
				intersect.instanceId = instanceId;
				intersect.object = this;
				intersects.push(intersect);
			}

			_instanceIntersects.length = 0;
		}
	}

	setColorAt(index, color) {
		if (this.instanceColor === null) {
			this.instanceColor = new InstancedBufferAttribute(new Float32Array(this.instanceMatrix.count * 3), 3);
		}

		color.toArray(this.instanceColor.array, index * 3);
	}

	setMatrixAt(index, matrix) {
		matrix.toArray(this.instanceMatrix.array, index * 16);
	}

	updateMorphTargets() {}

	dispose() {
		this.dispatchEvent({ type: 'dispose' });
	}
}

InstancedMesh.prototype.isInstancedMesh = true;

export { InstancedMesh };