(bounds, { force = false } = {})
| 663 | } |
| 664 | |
| 665 | updateCameraFrame(bounds, { force = false } = {}) { |
| 666 | if (!bounds || !Number.isFinite(bounds.min.x) || !Number.isFinite(bounds.max.x)) { |
| 667 | return; |
| 668 | } |
| 669 | |
| 670 | const size = new THREE.Vector3(); |
| 671 | bounds.getSize(size); |
| 672 | const center = new THREE.Vector3(); |
| 673 | bounds.getCenter(center); |
| 674 | |
| 675 | const maxSpan = Math.max(size.x, size.y, size.z, 1); |
| 676 | this.sceneCenter.copy(center); |
| 677 | this.sceneRadius = Math.max(maxSpan * 0.5, 1); |
| 678 | this.frustumSize = Math.max(SPREAD, this.sceneRadius * 4); |
| 679 | |
| 680 | this.perspectiveCamera.near = Math.max(0.1, this.sceneRadius * 0.01); |
| 681 | this.perspectiveCamera.far = Math.max(2000, this.sceneRadius * 20); |
| 682 | this.orthographicCamera.near = 0.1; |
| 683 | this.orthographicCamera.far = Math.max(4000, this.sceneRadius * 20); |
| 684 | |
| 685 | this.handleResize(); |
| 686 | |
| 687 | if (!force) { |
| 688 | return; |
| 689 | } |
| 690 | |
| 691 | if (this.cameraView === "free") { |
| 692 | const distance = Math.max(this.sceneRadius * 3, 25); |
| 693 | const offsetDirection = new THREE.Vector3(1, 0.8, 1).normalize(); |
| 694 | const offset = offsetDirection.multiplyScalar(distance); |
| 695 | |
| 696 | this.cameraMode = "perspective"; |
| 697 | this.activeCamera = this.perspectiveCamera; |
| 698 | this.controls.object = this.activeCamera; |
| 699 | this.perspectiveCamera.position.copy(center).add(offset); |
| 700 | this.controls.enableRotate = true; |
| 701 | this.controls.target.copy(center); |
| 702 | this.perspectiveCamera.lookAt(center); |
| 703 | this.controls.update(); |
| 704 | this.saveCurrentCameraState(); |
| 705 | return; |
| 706 | } |
| 707 | |
| 708 | this.applyView(this.cameraView); |
| 709 | this.saveCurrentCameraState(); |
| 710 | } |
| 711 | |
| 712 | getMaterial(color) { |
| 713 | const key = color.toLowerCase(); |
no test coverage detected