File size: 2,510 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
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
import { Object3D } from '../core/Object3D.js';
import { CylinderGeometry } from '../geometries/CylinderGeometry.js';
import { MeshBasicMaterial } from '../materials/MeshBasicMaterial.js';
import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
import { Mesh } from '../objects/Mesh.js';
import { Line } from '../objects/Line.js';
import { Vector3 } from '../math/Vector3.js';

const _axis = /*@__PURE__*/ new Vector3();
let _lineGeometry, _coneGeometry;

class ArrowHelper extends Object3D {
	// dir is assumed to be normalized

	constructor(
		dir = new Vector3(0, 0, 1),
		origin = new Vector3(0, 0, 0),
		length = 1,
		color = 0xffff00,
		headLength = length * 0.2,
		headWidth = headLength * 0.2
	) {
		super();

		this.type = 'ArrowHelper';

		if (_lineGeometry === undefined) {
			_lineGeometry = new BufferGeometry();
			_lineGeometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3));

			_coneGeometry = new CylinderGeometry(0, 0.5, 1, 5, 1);
			_coneGeometry.translate(0, -0.5, 0);
		}

		this.position.copy(origin);

		this.line = new Line(_lineGeometry, new LineBasicMaterial({ color: color, toneMapped: false }));
		this.line.matrixAutoUpdate = false;
		this.add(this.line);

		this.cone = new Mesh(_coneGeometry, new MeshBasicMaterial({ color: color, toneMapped: false }));
		this.cone.matrixAutoUpdate = false;
		this.add(this.cone);

		this.setDirection(dir);
		this.setLength(length, headLength, headWidth);
	}

	setDirection(dir) {
		// dir is assumed to be normalized

		if (dir.y > 0.99999) {
			this.quaternion.set(0, 0, 0, 1);
		} else if (dir.y < -0.99999) {
			this.quaternion.set(1, 0, 0, 0);
		} else {
			_axis.set(dir.z, 0, -dir.x).normalize();

			const radians = Math.acos(dir.y);

			this.quaternion.setFromAxisAngle(_axis, radians);
		}
	}

	setLength(length, headLength = length * 0.2, headWidth = headLength * 0.2) {
		this.line.scale.set(1, Math.max(0.0001, length - headLength), 1); // see #17458
		this.line.updateMatrix();

		this.cone.scale.set(headWidth, headLength, headWidth);
		this.cone.position.y = length;
		this.cone.updateMatrix();
	}

	setColor(color) {
		this.line.material.color.set(color);
		this.cone.material.color.set(color);
	}

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

		this.line.copy(source.line);
		this.cone.copy(source.cone);

		return this;
	}
}

export { ArrowHelper };