@tonybfox/threejs-tools 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/camera/index.cjs +2 -10
- package/dist/camera/index.cjs.map +1 -1
- package/dist/camera/index.mjs +1 -1
- package/dist/{chunk-R64RVBRM.mjs → chunk-4KUCMK3Q.mjs} +17 -11
- package/dist/chunk-4KUCMK3Q.mjs.map +1 -0
- package/dist/{chunk-BYRZCHE7.mjs → chunk-WMHEIUXE.mjs} +3 -11
- package/dist/chunk-WMHEIUXE.mjs.map +1 -0
- package/dist/index.cjs +18 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/view-helper/index.cjs +16 -10
- package/dist/view-helper/index.cjs.map +1 -1
- package/dist/view-helper/index.d.mts +1 -0
- package/dist/view-helper/index.d.ts +1 -0
- package/dist/view-helper/index.mjs +1 -1
- package/package.json +6 -4
- package/dist/chunk-BYRZCHE7.mjs.map +0 -1
- package/dist/chunk-R64RVBRM.mjs.map +0 -1
package/dist/camera/index.cjs
CHANGED
|
@@ -73,11 +73,7 @@ var DualCameraControls = class extends import_camera_controls.default {
|
|
|
73
73
|
perspectiveConfig.far ?? 2e3
|
|
74
74
|
);
|
|
75
75
|
perspectiveCamera.position.copy(
|
|
76
|
-
toVector3(
|
|
77
|
-
perspectiveConfig.position,
|
|
78
|
-
[12, 12, 12],
|
|
79
|
-
new THREE.Vector3()
|
|
80
|
-
)
|
|
76
|
+
toVector3(perspectiveConfig.position, [12, 12, 12], new THREE.Vector3())
|
|
81
77
|
);
|
|
82
78
|
if (perspectiveConfig.zoom !== void 0) {
|
|
83
79
|
perspectiveCamera.zoom = perspectiveConfig.zoom;
|
|
@@ -94,11 +90,7 @@ var DualCameraControls = class extends import_camera_controls.default {
|
|
|
94
90
|
orthographicConfig.far ?? 2e3
|
|
95
91
|
);
|
|
96
92
|
orthographicCamera.position.copy(
|
|
97
|
-
toVector3(
|
|
98
|
-
orthographicConfig.position,
|
|
99
|
-
[12, 12, 12],
|
|
100
|
-
new THREE.Vector3()
|
|
101
|
-
)
|
|
93
|
+
toVector3(orthographicConfig.position, [12, 12, 12], new THREE.Vector3())
|
|
102
94
|
);
|
|
103
95
|
if (orthographicConfig.zoom !== void 0) {
|
|
104
96
|
orthographicCamera.zoom = orthographicConfig.zoom;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../packages/camera/src/index.ts","../../packages/camera/src/DualCameraControls.ts"],"sourcesContent":["export * from './DualCameraControls'\n","import * as THREE from 'three'\nimport CameraControls from 'camera-controls'\n\ntype Vector3Tuple = [number, number, number]\ntype Vector3Like = THREE.Vector3 | Vector3Tuple\n\nexport type CameraMode = 'perspective' | 'orthographic'\n\nexport interface PerspectiveCameraConfig {\n fov?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface OrthographicCameraConfig {\n size?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface DualCameraControlsOptions {\n domElement?: HTMLElement\n initialMode?: CameraMode\n initialTarget?: Vector3Like\n perspective?: PerspectiveCameraConfig\n orthographic?: OrthographicCameraConfig\n}\n\nexport interface ModeChangedEvent {\n type: 'modechange'\n mode: CameraMode\n previousMode: CameraMode\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n}\n\nlet controlsInstalled = false\n\nconst tempVec3A = new THREE.Vector3()\nconst tempVec3B = new THREE.Vector3()\nconst tempVec2 = new THREE.Vector2()\n\nfunction ensureCameraControlsInstalled() {\n if (!controlsInstalled) {\n CameraControls.install({ THREE })\n controlsInstalled = true\n }\n}\n\nfunction toVector3(\n value: Vector3Like | undefined,\n fallback: Vector3Tuple,\n target: THREE.Vector3\n) {\n if (!value) {\n target.set(fallback[0], fallback[1], fallback[2])\n return target\n }\n\n if (Array.isArray(value)) {\n target.set(value[0], value[1], value[2])\n return target\n }\n\n target.copy(value)\n return target\n}\n\n/**\n * Camera controls that manage both perspective and orthographic cameras while\n * extending {@link CameraControls}. Provides helpers to toggle between the\n * camera types and keep the framing consistent.\n */\nexport class DualCameraControls extends CameraControls {\n readonly perspectiveCamera: THREE.PerspectiveCamera\n readonly orthographicCamera: THREE.OrthographicCamera\n\n private readonly renderer: THREE.WebGLRenderer\n private readonly domElementRef: HTMLElement\n private activeMode: CameraMode\n private readonly minOrthoHalfHeight: number\n private readonly updateClock = new THREE.Clock()\n\n constructor(\n renderer: THREE.WebGLRenderer,\n options: DualCameraControlsOptions = {}\n ) {\n ensureCameraControlsInstalled()\n\n const { domElement = renderer.domElement } = options\n const aspect = resolveAspect(renderer, domElement)\n\n const perspectiveConfig = options.perspective ?? {}\n const orthographicConfig = options.orthographic ?? {}\n\n const perspectiveCamera = new THREE.PerspectiveCamera(\n perspectiveConfig.fov ?? 60,\n aspect,\n perspectiveConfig.near ?? 0.1,\n perspectiveConfig.far ?? 2000\n )\n\n perspectiveCamera.position.copy(\n toVector3(\n perspectiveConfig.position,\n [12, 12, 12],\n new THREE.Vector3()\n )\n )\n\n if (perspectiveConfig.zoom !== undefined) {\n perspectiveCamera.zoom = perspectiveConfig.zoom\n perspectiveCamera.updateProjectionMatrix()\n }\n\n const orthoHalfHeight = Math.max(orthographicConfig.size ?? 20, 0.001) * 0.5\n const orthoHalfWidth = orthoHalfHeight * aspect\n\n const orthographicCamera = new THREE.OrthographicCamera(\n -orthoHalfWidth,\n orthoHalfWidth,\n orthoHalfHeight,\n -orthoHalfHeight,\n orthographicConfig.near ?? 0.1,\n orthographicConfig.far ?? 2000\n )\n\n orthographicCamera.position.copy(\n toVector3(\n orthographicConfig.position,\n [12, 12, 12],\n new THREE.Vector3()\n )\n )\n\n if (orthographicConfig.zoom !== undefined) {\n orthographicCamera.zoom = orthographicConfig.zoom\n orthographicCamera.updateProjectionMatrix()\n }\n\n const initialMode = options.initialMode ?? 'perspective'\n const initialCamera =\n initialMode === 'orthographic' ? orthographicCamera : perspectiveCamera\n\n super(initialCamera, domElement)\n\n const initialTarget = toVector3(\n options.initialTarget,\n [0, 0, 0],\n new THREE.Vector3()\n )\n void this.setLookAt(\n initialCamera.position.x,\n initialCamera.position.y,\n initialCamera.position.z,\n initialTarget.x,\n initialTarget.y,\n initialTarget.z,\n false\n )\n\n this.renderer = renderer\n this.domElementRef = domElement\n this.perspectiveCamera = perspectiveCamera\n this.orthographicCamera = orthographicCamera\n this.activeMode = initialMode\n this.minOrthoHalfHeight = orthoHalfHeight\n\n this.updateInputBindingsForMode(initialMode)\n }\n\n get mode(): CameraMode {\n return this.activeMode\n }\n\n /**\n * Returns the currently active camera instance.\n */\n get activeCamera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return this.camera\n }\n\n /**\n * Switch to the perspective camera while keeping the current framing.\n */\n switchToPerspective(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.position.copy(position)\n this.perspectiveCamera.quaternion.copy(this.camera.quaternion)\n this.perspectiveCamera.up.copy(this.camera.up)\n this.perspectiveCamera.updateProjectionMatrix()\n\n this.camera = this.perspectiveCamera\n this.activeMode = 'perspective'\n this.updateInputBindingsForMode('perspective')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'orthographic',\n camera: this.perspectiveCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Switch to the orthographic camera while keeping the current framing.\n */\n switchToOrthographic(enableTransition = false) {\n if (this.activeMode === 'orthographic') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.updateOrthographicFrustum(position, target, aspect)\n\n this.orthographicCamera.position.copy(position)\n this.orthographicCamera.quaternion.copy(this.camera.quaternion)\n this.orthographicCamera.up.copy(this.camera.up)\n this.orthographicCamera.updateProjectionMatrix()\n\n this.camera = this.orthographicCamera\n this.activeMode = 'orthographic'\n this.updateInputBindingsForMode('orthographic')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'perspective',\n camera: this.orthographicCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Toggles between perspective and orthographic camera modes.\n */\n toggleCameraMode(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n this.switchToOrthographic(enableTransition)\n } else {\n this.switchToPerspective(enableTransition)\n }\n }\n\n /**\n * Update camera projection parameters when the viewport size changes.\n */\n handleResize(width: number, height: number) {\n const aspect = height === 0 ? 1 : width / height\n\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.updateProjectionMatrix()\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n this.updateOrthographicFrustum(position, target, aspect)\n\n if (this.activeMode === 'orthographic') {\n this.camera = this.orthographicCamera\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n false\n )\n }\n }\n\n /**\n * Moves the camera to a new position and target.\n */\n moveCamera(\n position: Vector3Like,\n target: Vector3Like,\n enableTransition = true\n ) {\n toVector3(position, [0, 0, 0], tempVec3A)\n toVector3(target, [0, 0, 0], tempVec3B)\n\n return this.setLookAt(\n tempVec3A.x,\n tempVec3A.y,\n tempVec3A.z,\n tempVec3B.x,\n tempVec3B.y,\n tempVec3B.z,\n enableTransition\n )\n }\n\n /**\n * Updates the controls using an internally managed clock.\n * Useful when you don't want to pass delta time each frame.\n */\n updateDelta(): ReturnType<CameraControls['update']> {\n const delta = this.updateClock.getDelta()\n return super.update(delta)\n }\n\n private updateInputBindingsForMode(mode: CameraMode) {\n const { ACTION } = CameraControls\n\n if (mode === 'orthographic') {\n this.mouseButtons.left = ACTION.TRUCK\n this.mouseButtons.right = ACTION.ROTATE\n this.mouseButtons.wheel = ACTION.ZOOM\n this.touches.one = ACTION.TOUCH_TRUCK\n this.touches.two = ACTION.TOUCH_ZOOM_TRUCK\n } else {\n this.mouseButtons.left = ACTION.ROTATE\n this.mouseButtons.right = ACTION.TRUCK\n this.mouseButtons.wheel = ACTION.DOLLY\n this.touches.one = ACTION.TOUCH_ROTATE\n this.touches.two = ACTION.TOUCH_DOLLY_TRUCK\n }\n }\n\n private updateOrthographicFrustum(\n position: THREE.Vector3,\n target: THREE.Vector3,\n aspect: number\n ) {\n const distance = Math.max(position.distanceTo(target), 0.001)\n const fov = this.perspectiveCamera.fov\n const halfHeight = Math.max(\n distance * Math.tan(THREE.MathUtils.degToRad(fov * 0.5)),\n this.minOrthoHalfHeight\n )\n const halfWidth = halfHeight * aspect\n\n this.orthographicCamera.left = -halfWidth\n this.orthographicCamera.right = halfWidth\n this.orthographicCamera.top = halfHeight\n this.orthographicCamera.bottom = -halfHeight\n this.orthographicCamera.updateProjectionMatrix()\n }\n}\n\nfunction resolveAspect(\n renderer: THREE.WebGLRenderer,\n domElement: HTMLElement\n): number {\n const size = renderer.getSize(tempVec2)\n if (size.y > 0) {\n return size.x / size.y\n }\n\n const { clientWidth, clientHeight } = domElement\n if (clientHeight > 0) {\n return clientWidth / clientHeight\n }\n\n return 1\n}\n"],"mappings":"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","names":["CameraControls"]}
|
|
1
|
+
{"version":3,"sources":["../../packages/camera/src/index.ts","../../packages/camera/src/DualCameraControls.ts"],"sourcesContent":["export * from './DualCameraControls'\n","import * as THREE from 'three'\nimport CameraControls from 'camera-controls'\n\ntype Vector3Tuple = [number, number, number]\ntype Vector3Like = THREE.Vector3 | Vector3Tuple\n\nexport type CameraMode = 'perspective' | 'orthographic'\n\nexport interface PerspectiveCameraConfig {\n fov?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface OrthographicCameraConfig {\n size?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface DualCameraControlsOptions {\n domElement?: HTMLElement\n initialMode?: CameraMode\n initialTarget?: Vector3Like\n perspective?: PerspectiveCameraConfig\n orthographic?: OrthographicCameraConfig\n}\n\nexport interface ModeChangedEvent {\n type: 'modechange'\n mode: CameraMode\n previousMode: CameraMode\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n}\n\nlet controlsInstalled = false\n\nconst tempVec3A = new THREE.Vector3()\nconst tempVec3B = new THREE.Vector3()\nconst tempVec2 = new THREE.Vector2()\n\nfunction ensureCameraControlsInstalled() {\n if (!controlsInstalled) {\n CameraControls.install({ THREE })\n controlsInstalled = true\n }\n}\n\nfunction toVector3(\n value: Vector3Like | undefined,\n fallback: Vector3Tuple,\n target: THREE.Vector3\n) {\n if (!value) {\n target.set(fallback[0], fallback[1], fallback[2])\n return target\n }\n\n if (Array.isArray(value)) {\n target.set(value[0], value[1], value[2])\n return target\n }\n\n target.copy(value)\n return target\n}\n\n/**\n * Camera controls that manage both perspective and orthographic cameras while\n * extending {@link CameraControls}. Provides helpers to toggle between the\n * camera types and keep the framing consistent.\n */\nexport class DualCameraControls extends CameraControls {\n readonly perspectiveCamera: THREE.PerspectiveCamera\n readonly orthographicCamera: THREE.OrthographicCamera\n\n private readonly renderer: THREE.WebGLRenderer\n private readonly domElementRef: HTMLElement\n private activeMode: CameraMode\n private readonly minOrthoHalfHeight: number\n private readonly updateClock = new THREE.Clock()\n\n constructor(\n renderer: THREE.WebGLRenderer,\n options: DualCameraControlsOptions = {}\n ) {\n ensureCameraControlsInstalled()\n\n const { domElement = renderer.domElement } = options\n const aspect = resolveAspect(renderer, domElement)\n\n const perspectiveConfig = options.perspective ?? {}\n const orthographicConfig = options.orthographic ?? {}\n\n const perspectiveCamera = new THREE.PerspectiveCamera(\n perspectiveConfig.fov ?? 60,\n aspect,\n perspectiveConfig.near ?? 0.1,\n perspectiveConfig.far ?? 2000\n )\n\n perspectiveCamera.position.copy(\n toVector3(perspectiveConfig.position, [12, 12, 12], new THREE.Vector3())\n )\n\n if (perspectiveConfig.zoom !== undefined) {\n perspectiveCamera.zoom = perspectiveConfig.zoom\n perspectiveCamera.updateProjectionMatrix()\n }\n\n const orthoHalfHeight = Math.max(orthographicConfig.size ?? 20, 0.001) * 0.5\n const orthoHalfWidth = orthoHalfHeight * aspect\n\n const orthographicCamera = new THREE.OrthographicCamera(\n -orthoHalfWidth,\n orthoHalfWidth,\n orthoHalfHeight,\n -orthoHalfHeight,\n orthographicConfig.near ?? 0.1,\n orthographicConfig.far ?? 2000\n )\n\n orthographicCamera.position.copy(\n toVector3(orthographicConfig.position, [12, 12, 12], new THREE.Vector3())\n )\n\n if (orthographicConfig.zoom !== undefined) {\n orthographicCamera.zoom = orthographicConfig.zoom\n orthographicCamera.updateProjectionMatrix()\n }\n\n const initialMode = options.initialMode ?? 'perspective'\n const initialCamera =\n initialMode === 'orthographic' ? orthographicCamera : perspectiveCamera\n\n super(initialCamera, domElement)\n\n const initialTarget = toVector3(\n options.initialTarget,\n [0, 0, 0],\n new THREE.Vector3()\n )\n void this.setLookAt(\n initialCamera.position.x,\n initialCamera.position.y,\n initialCamera.position.z,\n initialTarget.x,\n initialTarget.y,\n initialTarget.z,\n false\n )\n\n this.renderer = renderer\n this.domElementRef = domElement\n this.perspectiveCamera = perspectiveCamera\n this.orthographicCamera = orthographicCamera\n this.activeMode = initialMode\n this.minOrthoHalfHeight = orthoHalfHeight\n\n this.updateInputBindingsForMode(initialMode)\n }\n\n get mode(): CameraMode {\n return this.activeMode\n }\n\n /**\n * Returns the currently active camera instance.\n */\n get activeCamera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return this.camera\n }\n\n /**\n * Switch to the perspective camera while keeping the current framing.\n */\n switchToPerspective(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.position.copy(position)\n this.perspectiveCamera.quaternion.copy(this.camera.quaternion)\n this.perspectiveCamera.up.copy(this.camera.up)\n this.perspectiveCamera.updateProjectionMatrix()\n\n this.camera = this.perspectiveCamera\n this.activeMode = 'perspective'\n this.updateInputBindingsForMode('perspective')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'orthographic',\n camera: this.perspectiveCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Switch to the orthographic camera while keeping the current framing.\n */\n switchToOrthographic(enableTransition = false) {\n if (this.activeMode === 'orthographic') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.updateOrthographicFrustum(position, target, aspect)\n\n this.orthographicCamera.position.copy(position)\n this.orthographicCamera.quaternion.copy(this.camera.quaternion)\n this.orthographicCamera.up.copy(this.camera.up)\n this.orthographicCamera.updateProjectionMatrix()\n\n this.camera = this.orthographicCamera\n this.activeMode = 'orthographic'\n this.updateInputBindingsForMode('orthographic')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'perspective',\n camera: this.orthographicCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Toggles between perspective and orthographic camera modes.\n */\n toggleCameraMode(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n this.switchToOrthographic(enableTransition)\n } else {\n this.switchToPerspective(enableTransition)\n }\n }\n\n /**\n * Update camera projection parameters when the viewport size changes.\n */\n handleResize(width: number, height: number) {\n const aspect = height === 0 ? 1 : width / height\n\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.updateProjectionMatrix()\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n this.updateOrthographicFrustum(position, target, aspect)\n\n if (this.activeMode === 'orthographic') {\n this.camera = this.orthographicCamera\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n false\n )\n }\n }\n\n /**\n * Moves the camera to a new position and target.\n */\n moveCamera(\n position: Vector3Like,\n target: Vector3Like,\n enableTransition = true\n ) {\n toVector3(position, [0, 0, 0], tempVec3A)\n toVector3(target, [0, 0, 0], tempVec3B)\n\n return this.setLookAt(\n tempVec3A.x,\n tempVec3A.y,\n tempVec3A.z,\n tempVec3B.x,\n tempVec3B.y,\n tempVec3B.z,\n enableTransition\n )\n }\n\n /**\n * Updates the controls using an internally managed clock.\n * Useful when you don't want to pass delta time each frame.\n */\n updateDelta(): ReturnType<CameraControls['update']> {\n const delta = this.updateClock.getDelta()\n return super.update(delta)\n }\n\n private updateInputBindingsForMode(mode: CameraMode) {\n const { ACTION } = CameraControls\n\n if (mode === 'orthographic') {\n this.mouseButtons.left = ACTION.TRUCK\n this.mouseButtons.right = ACTION.ROTATE\n this.mouseButtons.wheel = ACTION.ZOOM\n this.touches.one = ACTION.TOUCH_TRUCK\n this.touches.two = ACTION.TOUCH_ZOOM_TRUCK\n } else {\n this.mouseButtons.left = ACTION.ROTATE\n this.mouseButtons.right = ACTION.TRUCK\n this.mouseButtons.wheel = ACTION.DOLLY\n this.touches.one = ACTION.TOUCH_ROTATE\n this.touches.two = ACTION.TOUCH_DOLLY_TRUCK\n }\n }\n\n private updateOrthographicFrustum(\n position: THREE.Vector3,\n target: THREE.Vector3,\n aspect: number\n ) {\n const distance = Math.max(position.distanceTo(target), 0.001)\n const fov = this.perspectiveCamera.fov\n const halfHeight = Math.max(\n distance * Math.tan(THREE.MathUtils.degToRad(fov * 0.5)),\n this.minOrthoHalfHeight\n )\n const halfWidth = halfHeight * aspect\n\n this.orthographicCamera.left = -halfWidth\n this.orthographicCamera.right = halfWidth\n this.orthographicCamera.top = halfHeight\n this.orthographicCamera.bottom = -halfHeight\n this.orthographicCamera.updateProjectionMatrix()\n }\n}\n\nfunction resolveAspect(\n renderer: THREE.WebGLRenderer,\n domElement: HTMLElement\n): number {\n const size = renderer.getSize(tempVec2)\n if (size.y > 0) {\n return size.x / size.y\n }\n\n const { clientWidth, clientHeight } = domElement\n if (clientHeight > 0) {\n return clientWidth / clientHeight\n }\n\n return 1\n}\n"],"mappings":"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","names":["CameraControls"]}
|
package/dist/camera/index.mjs
CHANGED
|
@@ -203,7 +203,7 @@ var ViewHelper = class extends THREE.EventDispatcher {
|
|
|
203
203
|
renderer.autoClear = false;
|
|
204
204
|
renderer.setScissorTest(true);
|
|
205
205
|
renderer.setScissor(x, y, size, size);
|
|
206
|
-
renderer.clear(
|
|
206
|
+
renderer.clear(true, true, true);
|
|
207
207
|
renderer.render(this.scene, this.orthoCamera);
|
|
208
208
|
renderer.setScissorTest(false);
|
|
209
209
|
renderer.autoClear = autoClear;
|
|
@@ -308,18 +308,24 @@ var ViewHelper = class extends THREE.EventDispatcher {
|
|
|
308
308
|
if (!controls) {
|
|
309
309
|
return;
|
|
310
310
|
}
|
|
311
|
+
controls.enabled = false;
|
|
311
312
|
controls.stop?.();
|
|
312
313
|
this.animating = true;
|
|
313
314
|
this.dispatchEvent({ type: "animationStart" });
|
|
314
|
-
const applyLookAt = () =>
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
315
|
+
const applyLookAt = () => {
|
|
316
|
+
controls.setLookAt(
|
|
317
|
+
this.targetPosition.x,
|
|
318
|
+
this.targetPosition.y,
|
|
319
|
+
this.targetPosition.z,
|
|
320
|
+
focusPoint.x,
|
|
321
|
+
focusPoint.y,
|
|
322
|
+
focusPoint.z,
|
|
323
|
+
true
|
|
324
|
+
);
|
|
325
|
+
setTimeout(() => {
|
|
326
|
+
controls.enabled = true;
|
|
327
|
+
}, 100);
|
|
328
|
+
};
|
|
323
329
|
try {
|
|
324
330
|
void Promise.resolve(applyLookAt()).catch((error) => {
|
|
325
331
|
console.warn("ViewHelper: Unable to set camera look-at.", error);
|
|
@@ -391,4 +397,4 @@ var ViewHelper = class extends THREE.EventDispatcher {
|
|
|
391
397
|
export {
|
|
392
398
|
ViewHelper
|
|
393
399
|
};
|
|
394
|
-
//# sourceMappingURL=chunk-
|
|
400
|
+
//# sourceMappingURL=chunk-4KUCMK3Q.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/view-helper/src/ViewHelper.ts"],"sourcesContent":["import * as THREE from 'three'\n\n// Hard-coded axis colors matching TransformControls\nconst AXIS_COLORS = {\n x: '#ed4358',\n y: '#82cc19',\n z: '#3185eb',\n} as const\n\nexport interface ViewHelperCameraController {\n camera: THREE.Camera\n getPosition(target: THREE.Vector3): THREE.Vector3\n getTarget(target: THREE.Vector3): THREE.Vector3\n setLookAt(\n positionX: number,\n positionY: number,\n positionZ: number,\n targetX: number,\n targetY: number,\n targetZ: number,\n enableTransition?: boolean\n ): Promise<void> | void\n stop?(): void\n enabled: boolean\n}\n\nexport interface ViewHelperOptions {\n container?: HTMLElement\n size?: number\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n offset?: { x: number; y: number }\n center?: THREE.Vector3\n labels?: {\n x?: string\n y?: string\n z?: string\n }\n controls?: ViewHelperCameraController\n}\n\n// Define event types for the view helper\ninterface ViewHelperEventMap {\n animationStart: {}\n animationEnd: {}\n}\n\nexport interface ViewHelperEvent {\n type: 'animationStart' | 'animationEnd'\n}\n\nexport class ViewHelper extends THREE.EventDispatcher<ViewHelperEventMap> {\n private camera: THREE.Camera\n private domElement: HTMLElement\n private options: Required<Omit<ViewHelperOptions, 'controls'>>\n private scene: THREE.Scene\n private orthoCamera: THREE.OrthographicCamera\n private renderer?: THREE.WebGLRenderer\n private viewport: THREE.Vector4 = new THREE.Vector4()\n private controls?: ViewHelperCameraController\n private pointerDownHandler!: (event: PointerEvent) => void\n\n // Animation properties\n public animating: boolean = false\n public center: THREE.Vector3\n private targetPosition: THREE.Vector3 = new THREE.Vector3()\n private targetQuaternion: THREE.Quaternion = new THREE.Quaternion()\n private q1: THREE.Quaternion = new THREE.Quaternion()\n private q2: THREE.Quaternion = new THREE.Quaternion()\n private dummy: THREE.Object3D = new THREE.Object3D()\n private radius: number = 0\n private turnRate: number = 2 * Math.PI // turn rate in angles per second\n private tempVecA: THREE.Vector3 = new THREE.Vector3()\n\n // Interactive elements\n private interactiveObjects: THREE.Object3D[] = []\n private raycaster: THREE.Raycaster = new THREE.Raycaster()\n private mouse: THREE.Vector2 = new THREE.Vector2()\n\n // Helper objects\n private axes!: {\n x: THREE.Mesh\n y: THREE.Mesh\n z: THREE.Mesh\n }\n private sprites!: {\n posX: THREE.Sprite\n posY: THREE.Sprite\n posZ: THREE.Sprite\n negX: THREE.Sprite\n negY: THREE.Sprite\n negZ: THREE.Sprite\n }\n\n constructor(\n camera: THREE.Camera,\n domElement?: HTMLElement,\n options: ViewHelperOptions = {}\n ) {\n super()\n this.controls = options.controls\n this.camera = this.controls?.camera ?? camera\n this.domElement = domElement || document.body\n\n const defaultCenter =\n options.center ??\n (this.controls\n ? this.controls.getTarget(new THREE.Vector3())\n : new THREE.Vector3())\n\n // Set default options\n this.options = {\n container: options.container || document.body,\n size: options.size || 128,\n position: options.position || 'bottom-right',\n offset: options.offset || { x: 20, y: 20 },\n center: defaultCenter.clone(),\n labels: {\n x: options.labels?.x || '',\n y: options.labels?.y || '',\n z: options.labels?.z || '',\n ...options.labels,\n },\n }\n\n this.center = this.options.center.clone()\n\n this.scene = new THREE.Scene()\n this.scene.background = null // Make background transparent\n this.orthoCamera = new THREE.OrthographicCamera(-2, 2, 2, -2, 0, 4)\n this.orthoCamera.position.set(0, 0, 2)\n\n this.createAxes()\n this.createSprites()\n this.setupEventListeners()\n }\n\n private syncActiveCamera(): THREE.Camera {\n if (this.controls) {\n this.camera = this.controls.camera\n }\n return this.camera\n }\n\n private getCameraPosition(target: THREE.Vector3): THREE.Vector3 {\n if (this.controls) {\n return this.controls.getPosition(target)\n }\n return target.copy(this.camera.position)\n }\n\n private createAxes(): void {\n const geometry = new THREE.CylinderGeometry(0.04, 0.04, 0.8, 5)\n .rotateZ(-Math.PI / 2)\n .translate(0.4, 0, 0)\n\n const xAxisMaterial = new THREE.MeshBasicMaterial({\n color: AXIS_COLORS.x,\n toneMapped: false,\n })\n const yAxisMaterial = new THREE.MeshBasicMaterial({\n color: AXIS_COLORS.y,\n toneMapped: false,\n })\n const zAxisMaterial = new THREE.MeshBasicMaterial({\n color: AXIS_COLORS.z,\n toneMapped: false,\n })\n\n this.axes = {\n x: new THREE.Mesh(geometry.clone(), xAxisMaterial),\n y: new THREE.Mesh(geometry.clone(), yAxisMaterial),\n z: new THREE.Mesh(geometry.clone(), zAxisMaterial),\n }\n\n this.axes.y.rotation.z = Math.PI / 2\n this.axes.z.rotation.y = -Math.PI / 2\n\n this.scene.add(this.axes.x)\n this.scene.add(this.axes.y)\n this.scene.add(this.axes.z)\n }\n\n private createSprites(): void {\n const posXSprite = this.createSprite(AXIS_COLORS.x, this.options.labels.x)\n const posYSprite = this.createSprite(AXIS_COLORS.y, this.options.labels.y)\n const posZSprite = this.createSprite(AXIS_COLORS.z, this.options.labels.z)\n // Use faded versions of the axis colors for negative axes\n const negXSprite = this.createSprite(AXIS_COLORS.x)\n const negYSprite = this.createSprite(AXIS_COLORS.y)\n const negZSprite = this.createSprite(AXIS_COLORS.z)\n\n this.sprites = {\n posX: posXSprite,\n posY: posYSprite,\n posZ: posZSprite,\n negX: negXSprite,\n negY: negYSprite,\n negZ: negZSprite,\n }\n\n // Position sprites\n this.sprites.posX.position.set(1, 0, 0)\n this.sprites.posY.position.set(0, 1, 0)\n this.sprites.posZ.position.set(0, 0, 1)\n this.sprites.negX.position.set(-1, 0, 0)\n this.sprites.negY.position.set(0, -1, 0)\n this.sprites.negZ.position.set(0, 0, -1)\n\n // Set opacity for negative axes\n this.sprites.negX.material.opacity = 0.2\n this.sprites.negY.material.opacity = 0.2\n this.sprites.negZ.material.opacity = 0.2\n\n // Set user data for interaction\n this.sprites.posX.userData.type = 'posX'\n this.sprites.posY.userData.type = 'posY'\n this.sprites.posZ.userData.type = 'posZ'\n this.sprites.negX.userData.type = 'negX'\n this.sprites.negY.userData.type = 'negY'\n this.sprites.negZ.userData.type = 'negZ'\n\n // Add to scene and interactive objects\n Object.values(this.sprites).forEach((sprite) => {\n this.scene.add(sprite)\n this.interactiveObjects.push(sprite)\n })\n }\n\n private createSprite(color: string, text?: string): THREE.Sprite {\n // Use higher resolution for crisp rendering\n const pixelRatio = window.devicePixelRatio || 1\n const size = 128 * pixelRatio\n const radius = 28 * pixelRatio\n\n const canvas = document.createElement('canvas')\n canvas.width = size\n canvas.height = size\n\n const context = canvas.getContext('2d')!\n\n // Enable high-quality rendering\n context.imageSmoothingEnabled = true\n context.imageSmoothingQuality = 'high'\n\n // Scale for device pixel ratio\n context.scale(pixelRatio, pixelRatio)\n\n const center = size / (2 * pixelRatio)\n const actualRadius = radius / pixelRatio\n\n // Draw circle background\n context.beginPath()\n context.arc(center, center, actualRadius, 0, 2 * Math.PI)\n context.closePath()\n context.fillStyle = color\n context.fill()\n\n if (text) {\n context.font = 'bold 48px Arial, sans-serif'\n context.textAlign = 'center'\n context.textBaseline = 'middle'\n context.fillStyle = '#ffffff'\n\n // Add text stroke for better visibility\n context.strokeStyle = '#000000'\n context.lineWidth = 2\n context.strokeText(text, center, center)\n context.fillText(text, center, center)\n }\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace\n texture.generateMipmaps = false\n texture.minFilter = THREE.LinearFilter\n texture.magFilter = THREE.LinearFilter\n\n return new THREE.Sprite(\n new THREE.SpriteMaterial({\n map: texture,\n toneMapped: false,\n alphaTest: 0.1,\n })\n )\n }\n\n private setupEventListeners(): void {\n this.pointerDownHandler = (event: PointerEvent) => {\n this.handleClick(event)\n }\n this.domElement.addEventListener('pointerdown', this.pointerDownHandler)\n }\n\n public render(renderer: THREE.WebGLRenderer): void {\n this.renderer = renderer\n\n const activeCamera = this.syncActiveCamera()\n\n // Update helper orientation to match camera\n this.scene.quaternion.copy(activeCamera.quaternion).invert()\n this.scene.updateMatrixWorld()\n\n const size = this.options.size\n const canvasWidth = renderer.domElement.width / renderer.getPixelRatio()\n const canvasHeight = renderer.domElement.height / renderer.getPixelRatio()\n\n let x: number, y: number\n\n switch (this.options.position) {\n case 'top-left':\n x = this.options.offset.x\n y = canvasHeight - size - this.options.offset.y\n break\n case 'top-right':\n x = canvasWidth - size - this.options.offset.x\n y = canvasHeight - size - this.options.offset.y\n break\n case 'bottom-left':\n x = this.options.offset.x\n y = this.options.offset.y\n break\n case 'bottom-right':\n default:\n x = canvasWidth - size - this.options.offset.x\n y = this.options.offset.y\n break\n }\n\n // Store current viewport and autoClear setting\n renderer.getViewport(this.viewport)\n const autoClear = renderer.autoClear\n\n // Set viewport for helper and disable autoClear\n renderer.setViewport(x, y, size, size)\n renderer.autoClear = false\n\n // Clear only depth buffer in the helper area\n renderer.setScissorTest(true)\n renderer.setScissor(x, y, size, size)\n renderer.clear(true, true, true)\n\n // Render helper\n renderer.render(this.scene, this.orthoCamera)\n // Restore settings\n renderer.setScissorTest(false)\n renderer.autoClear = autoClear\n renderer.setViewport(\n this.viewport.x,\n this.viewport.y,\n this.viewport.z,\n this.viewport.w\n )\n }\n\n public handleClick(event: PointerEvent): boolean {\n if (this.animating || !this.renderer) return false\n\n this.syncActiveCamera()\n\n const rect = this.domElement.getBoundingClientRect()\n const size = this.options.size // Use logical size for click detection\n\n // Calculate helper viewport bounds\n let offsetX: number, offsetY: number\n\n switch (this.options.position) {\n case 'top-left':\n offsetX = rect.left + this.options.offset.x\n offsetY = rect.top + this.options.offset.y\n break\n case 'top-right':\n offsetX = rect.left + rect.width - size - this.options.offset.x\n offsetY = rect.top + this.options.offset.y\n break\n case 'bottom-left':\n offsetX = rect.left + this.options.offset.x\n offsetY = rect.top + rect.height - size - this.options.offset.y\n break\n case 'bottom-right':\n default:\n offsetX = rect.left + rect.width - size - this.options.offset.x\n offsetY = rect.top + rect.height - size - this.options.offset.y\n break\n }\n\n // Convert click coordinates to helper-relative coordinates\n this.mouse.x = ((event.clientX - offsetX) / size) * 2 - 1\n this.mouse.y = -((event.clientY - offsetY) / size) * 2 + 1\n\n // Check if click is within helper bounds\n if (\n this.mouse.x < -1 ||\n this.mouse.x > 1 ||\n this.mouse.y < -1 ||\n this.mouse.y > 1\n ) {\n return false\n }\n\n this.raycaster.setFromCamera(this.mouse, this.orthoCamera)\n const intersects = this.raycaster.intersectObjects(this.interactiveObjects)\n\n if (intersects.length > 0) {\n const intersection = intersects[0]\n const object = intersection.object\n this.prepareAnimationData(object, this.center)\n if (this.controls) {\n this.startControlsAnimation(this.center)\n } else {\n this.animating = true\n this.dispatchEvent({ type: 'animationStart' })\n }\n return true\n }\n\n return false\n }\n\n private prepareAnimationData(\n object: THREE.Object3D,\n focusPoint: THREE.Vector3\n ): void {\n switch (object.userData.type) {\n case 'posX':\n this.targetPosition.set(1, 0, 0)\n this.targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI * 0.5, 0))\n break\n case 'posY':\n this.targetPosition.set(0, 1, 0)\n this.targetQuaternion.setFromEuler(\n new THREE.Euler(-Math.PI * 0.5, 0, 0)\n )\n break\n case 'posZ':\n this.targetPosition.set(0, 0, 1)\n this.targetQuaternion.setFromEuler(new THREE.Euler())\n break\n case 'negX':\n this.targetPosition.set(-1, 0, 0)\n this.targetQuaternion.setFromEuler(\n new THREE.Euler(0, -Math.PI * 0.5, 0)\n )\n break\n case 'negY':\n this.targetPosition.set(0, -1, 0)\n this.targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.5, 0, 0))\n break\n case 'negZ':\n this.targetPosition.set(0, 0, -1)\n this.targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI, 0))\n break\n default:\n console.error('ViewHelper: Invalid axis.')\n return\n }\n\n const cameraPosition = this.getCameraPosition(this.tempVecA)\n this.radius = cameraPosition.distanceTo(focusPoint)\n this.targetPosition.multiplyScalar(this.radius).add(focusPoint)\n\n this.dummy.position.copy(focusPoint)\n this.dummy.lookAt(cameraPosition)\n this.q1.copy(this.dummy.quaternion)\n\n this.dummy.lookAt(this.targetPosition)\n this.q2.copy(this.dummy.quaternion)\n }\n\n private startControlsAnimation(focusPoint: THREE.Vector3): void {\n const controls = this.controls\n if (!controls) {\n return\n }\n controls.enabled = false\n controls.stop?.()\n this.animating = true\n this.dispatchEvent({ type: 'animationStart' })\n\n const applyLookAt = () => {\n controls.setLookAt(\n this.targetPosition.x,\n this.targetPosition.y,\n this.targetPosition.z,\n focusPoint.x,\n focusPoint.y,\n focusPoint.z,\n true\n )\n\n setTimeout(() => {\n controls.enabled = true\n }, 100)\n }\n try {\n void Promise.resolve(applyLookAt())\n .catch((error) => {\n console.warn('ViewHelper: Unable to set camera look-at.', error)\n })\n .finally(() => {\n this.animating = false\n this.dispatchEvent({ type: 'animationEnd' })\n })\n } catch (error) {\n console.warn('ViewHelper: Unable to set camera look-at.', error)\n this.animating = false\n this.dispatchEvent({ type: 'animationEnd' })\n }\n }\n\n public update(delta: number): void {\n this.syncActiveCamera()\n\n if (this.controls) {\n return\n }\n\n if (!this.animating) return\n\n const step = delta * this.turnRate\n\n // Animate position by doing a slerp and then scaling the position on the unit sphere\n this.q1.rotateTowards(this.q2, step)\n this.camera.position\n .set(0, 0, 1)\n .applyQuaternion(this.q1)\n .multiplyScalar(this.radius)\n .add(this.center)\n\n // Animate orientation\n this.camera.quaternion.rotateTowards(this.targetQuaternion, step)\n\n if (this.q1.angleTo(this.q2) === 0) {\n this.animating = false\n this.dispatchEvent({ type: 'animationEnd' })\n }\n }\n\n public setLabels(labelX?: string, labelY?: string, labelZ?: string): void {\n if (labelX !== undefined) this.options.labels.x = labelX\n if (labelY !== undefined) this.options.labels.y = labelY\n if (labelZ !== undefined) this.options.labels.z = labelZ\n\n this.updateLabels()\n }\n\n private updateLabels(): void {\n // Dispose old materials\n this.sprites.posX.material.map?.dispose()\n this.sprites.posY.material.map?.dispose()\n this.sprites.posZ.material.map?.dispose()\n this.sprites.posX.material.dispose()\n this.sprites.posY.material.dispose()\n this.sprites.posZ.material.dispose()\n\n // Create new sprites with updated labels\n const newPosX = this.createSprite(AXIS_COLORS.x, this.options.labels.x)\n const newPosY = this.createSprite(AXIS_COLORS.y, this.options.labels.y)\n const newPosZ = this.createSprite(AXIS_COLORS.z, this.options.labels.z)\n\n // Update sprites\n this.sprites.posX.material = newPosX.material\n this.sprites.posY.material = newPosY.material\n this.sprites.posZ.material = newPosZ.material\n }\n\n public dispose(): void {\n // Dispose geometries\n this.axes.x.geometry.dispose()\n this.axes.y.geometry.dispose()\n this.axes.z.geometry.dispose()\n\n // Dispose materials\n ;(this.axes.x.material as THREE.Material).dispose()\n ;(this.axes.y.material as THREE.Material).dispose()\n ;(this.axes.z.material as THREE.Material).dispose()\n\n // Dispose sprite materials and textures\n Object.values(this.sprites).forEach((sprite) => {\n sprite.material.map?.dispose()\n sprite.material.dispose()\n })\n\n // Remove event listeners\n if (this.pointerDownHandler) {\n this.domElement.removeEventListener(\n 'pointerdown',\n this.pointerDownHandler\n )\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -37,11 +37,7 @@ var DualCameraControls = class extends CameraControls {
|
|
|
37
37
|
perspectiveConfig.far ?? 2e3
|
|
38
38
|
);
|
|
39
39
|
perspectiveCamera.position.copy(
|
|
40
|
-
toVector3(
|
|
41
|
-
perspectiveConfig.position,
|
|
42
|
-
[12, 12, 12],
|
|
43
|
-
new THREE.Vector3()
|
|
44
|
-
)
|
|
40
|
+
toVector3(perspectiveConfig.position, [12, 12, 12], new THREE.Vector3())
|
|
45
41
|
);
|
|
46
42
|
if (perspectiveConfig.zoom !== void 0) {
|
|
47
43
|
perspectiveCamera.zoom = perspectiveConfig.zoom;
|
|
@@ -58,11 +54,7 @@ var DualCameraControls = class extends CameraControls {
|
|
|
58
54
|
orthographicConfig.far ?? 2e3
|
|
59
55
|
);
|
|
60
56
|
orthographicCamera.position.copy(
|
|
61
|
-
toVector3(
|
|
62
|
-
orthographicConfig.position,
|
|
63
|
-
[12, 12, 12],
|
|
64
|
-
new THREE.Vector3()
|
|
65
|
-
)
|
|
57
|
+
toVector3(orthographicConfig.position, [12, 12, 12], new THREE.Vector3())
|
|
66
58
|
);
|
|
67
59
|
if (orthographicConfig.zoom !== void 0) {
|
|
68
60
|
orthographicCamera.zoom = orthographicConfig.zoom;
|
|
@@ -274,4 +266,4 @@ function resolveAspect(renderer, domElement) {
|
|
|
274
266
|
export {
|
|
275
267
|
DualCameraControls
|
|
276
268
|
};
|
|
277
|
-
//# sourceMappingURL=chunk-
|
|
269
|
+
//# sourceMappingURL=chunk-WMHEIUXE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../packages/camera/src/DualCameraControls.ts"],"sourcesContent":["import * as THREE from 'three'\nimport CameraControls from 'camera-controls'\n\ntype Vector3Tuple = [number, number, number]\ntype Vector3Like = THREE.Vector3 | Vector3Tuple\n\nexport type CameraMode = 'perspective' | 'orthographic'\n\nexport interface PerspectiveCameraConfig {\n fov?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface OrthographicCameraConfig {\n size?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface DualCameraControlsOptions {\n domElement?: HTMLElement\n initialMode?: CameraMode\n initialTarget?: Vector3Like\n perspective?: PerspectiveCameraConfig\n orthographic?: OrthographicCameraConfig\n}\n\nexport interface ModeChangedEvent {\n type: 'modechange'\n mode: CameraMode\n previousMode: CameraMode\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n}\n\nlet controlsInstalled = false\n\nconst tempVec3A = new THREE.Vector3()\nconst tempVec3B = new THREE.Vector3()\nconst tempVec2 = new THREE.Vector2()\n\nfunction ensureCameraControlsInstalled() {\n if (!controlsInstalled) {\n CameraControls.install({ THREE })\n controlsInstalled = true\n }\n}\n\nfunction toVector3(\n value: Vector3Like | undefined,\n fallback: Vector3Tuple,\n target: THREE.Vector3\n) {\n if (!value) {\n target.set(fallback[0], fallback[1], fallback[2])\n return target\n }\n\n if (Array.isArray(value)) {\n target.set(value[0], value[1], value[2])\n return target\n }\n\n target.copy(value)\n return target\n}\n\n/**\n * Camera controls that manage both perspective and orthographic cameras while\n * extending {@link CameraControls}. Provides helpers to toggle between the\n * camera types and keep the framing consistent.\n */\nexport class DualCameraControls extends CameraControls {\n readonly perspectiveCamera: THREE.PerspectiveCamera\n readonly orthographicCamera: THREE.OrthographicCamera\n\n private readonly renderer: THREE.WebGLRenderer\n private readonly domElementRef: HTMLElement\n private activeMode: CameraMode\n private readonly minOrthoHalfHeight: number\n private readonly updateClock = new THREE.Clock()\n\n constructor(\n renderer: THREE.WebGLRenderer,\n options: DualCameraControlsOptions = {}\n ) {\n ensureCameraControlsInstalled()\n\n const { domElement = renderer.domElement } = options\n const aspect = resolveAspect(renderer, domElement)\n\n const perspectiveConfig = options.perspective ?? {}\n const orthographicConfig = options.orthographic ?? {}\n\n const perspectiveCamera = new THREE.PerspectiveCamera(\n perspectiveConfig.fov ?? 60,\n aspect,\n perspectiveConfig.near ?? 0.1,\n perspectiveConfig.far ?? 2000\n )\n\n perspectiveCamera.position.copy(\n toVector3(perspectiveConfig.position, [12, 12, 12], new THREE.Vector3())\n )\n\n if (perspectiveConfig.zoom !== undefined) {\n perspectiveCamera.zoom = perspectiveConfig.zoom\n perspectiveCamera.updateProjectionMatrix()\n }\n\n const orthoHalfHeight = Math.max(orthographicConfig.size ?? 20, 0.001) * 0.5\n const orthoHalfWidth = orthoHalfHeight * aspect\n\n const orthographicCamera = new THREE.OrthographicCamera(\n -orthoHalfWidth,\n orthoHalfWidth,\n orthoHalfHeight,\n -orthoHalfHeight,\n orthographicConfig.near ?? 0.1,\n orthographicConfig.far ?? 2000\n )\n\n orthographicCamera.position.copy(\n toVector3(orthographicConfig.position, [12, 12, 12], new THREE.Vector3())\n )\n\n if (orthographicConfig.zoom !== undefined) {\n orthographicCamera.zoom = orthographicConfig.zoom\n orthographicCamera.updateProjectionMatrix()\n }\n\n const initialMode = options.initialMode ?? 'perspective'\n const initialCamera =\n initialMode === 'orthographic' ? orthographicCamera : perspectiveCamera\n\n super(initialCamera, domElement)\n\n const initialTarget = toVector3(\n options.initialTarget,\n [0, 0, 0],\n new THREE.Vector3()\n )\n void this.setLookAt(\n initialCamera.position.x,\n initialCamera.position.y,\n initialCamera.position.z,\n initialTarget.x,\n initialTarget.y,\n initialTarget.z,\n false\n )\n\n this.renderer = renderer\n this.domElementRef = domElement\n this.perspectiveCamera = perspectiveCamera\n this.orthographicCamera = orthographicCamera\n this.activeMode = initialMode\n this.minOrthoHalfHeight = orthoHalfHeight\n\n this.updateInputBindingsForMode(initialMode)\n }\n\n get mode(): CameraMode {\n return this.activeMode\n }\n\n /**\n * Returns the currently active camera instance.\n */\n get activeCamera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return this.camera\n }\n\n /**\n * Switch to the perspective camera while keeping the current framing.\n */\n switchToPerspective(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.position.copy(position)\n this.perspectiveCamera.quaternion.copy(this.camera.quaternion)\n this.perspectiveCamera.up.copy(this.camera.up)\n this.perspectiveCamera.updateProjectionMatrix()\n\n this.camera = this.perspectiveCamera\n this.activeMode = 'perspective'\n this.updateInputBindingsForMode('perspective')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'orthographic',\n camera: this.perspectiveCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Switch to the orthographic camera while keeping the current framing.\n */\n switchToOrthographic(enableTransition = false) {\n if (this.activeMode === 'orthographic') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.updateOrthographicFrustum(position, target, aspect)\n\n this.orthographicCamera.position.copy(position)\n this.orthographicCamera.quaternion.copy(this.camera.quaternion)\n this.orthographicCamera.up.copy(this.camera.up)\n this.orthographicCamera.updateProjectionMatrix()\n\n this.camera = this.orthographicCamera\n this.activeMode = 'orthographic'\n this.updateInputBindingsForMode('orthographic')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'perspective',\n camera: this.orthographicCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Toggles between perspective and orthographic camera modes.\n */\n toggleCameraMode(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n this.switchToOrthographic(enableTransition)\n } else {\n this.switchToPerspective(enableTransition)\n }\n }\n\n /**\n * Update camera projection parameters when the viewport size changes.\n */\n handleResize(width: number, height: number) {\n const aspect = height === 0 ? 1 : width / height\n\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.updateProjectionMatrix()\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n this.updateOrthographicFrustum(position, target, aspect)\n\n if (this.activeMode === 'orthographic') {\n this.camera = this.orthographicCamera\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n false\n )\n }\n }\n\n /**\n * Moves the camera to a new position and target.\n */\n moveCamera(\n position: Vector3Like,\n target: Vector3Like,\n enableTransition = true\n ) {\n toVector3(position, [0, 0, 0], tempVec3A)\n toVector3(target, [0, 0, 0], tempVec3B)\n\n return this.setLookAt(\n tempVec3A.x,\n tempVec3A.y,\n tempVec3A.z,\n tempVec3B.x,\n tempVec3B.y,\n tempVec3B.z,\n enableTransition\n )\n }\n\n /**\n * Updates the controls using an internally managed clock.\n * Useful when you don't want to pass delta time each frame.\n */\n updateDelta(): ReturnType<CameraControls['update']> {\n const delta = this.updateClock.getDelta()\n return super.update(delta)\n }\n\n private updateInputBindingsForMode(mode: CameraMode) {\n const { ACTION } = CameraControls\n\n if (mode === 'orthographic') {\n this.mouseButtons.left = ACTION.TRUCK\n this.mouseButtons.right = ACTION.ROTATE\n this.mouseButtons.wheel = ACTION.ZOOM\n this.touches.one = ACTION.TOUCH_TRUCK\n this.touches.two = ACTION.TOUCH_ZOOM_TRUCK\n } else {\n this.mouseButtons.left = ACTION.ROTATE\n this.mouseButtons.right = ACTION.TRUCK\n this.mouseButtons.wheel = ACTION.DOLLY\n this.touches.one = ACTION.TOUCH_ROTATE\n this.touches.two = ACTION.TOUCH_DOLLY_TRUCK\n }\n }\n\n private updateOrthographicFrustum(\n position: THREE.Vector3,\n target: THREE.Vector3,\n aspect: number\n ) {\n const distance = Math.max(position.distanceTo(target), 0.001)\n const fov = this.perspectiveCamera.fov\n const halfHeight = Math.max(\n distance * Math.tan(THREE.MathUtils.degToRad(fov * 0.5)),\n this.minOrthoHalfHeight\n )\n const halfWidth = halfHeight * aspect\n\n this.orthographicCamera.left = -halfWidth\n this.orthographicCamera.right = halfWidth\n this.orthographicCamera.top = halfHeight\n this.orthographicCamera.bottom = -halfHeight\n this.orthographicCamera.updateProjectionMatrix()\n }\n}\n\nfunction resolveAspect(\n renderer: THREE.WebGLRenderer,\n domElement: HTMLElement\n): number {\n const size = renderer.getSize(tempVec2)\n if (size.y > 0) {\n return size.x / size.y\n }\n\n const { clientWidth, clientHeight } = domElement\n if (clientHeight > 0) {\n return clientWidth / clientHeight\n }\n\n return 1\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -421,11 +421,7 @@ var DualCameraControls = class extends import_camera_controls.default {
|
|
|
421
421
|
perspectiveConfig.far ?? 2e3
|
|
422
422
|
);
|
|
423
423
|
perspectiveCamera.position.copy(
|
|
424
|
-
toVector3(
|
|
425
|
-
perspectiveConfig.position,
|
|
426
|
-
[12, 12, 12],
|
|
427
|
-
new THREE2.Vector3()
|
|
428
|
-
)
|
|
424
|
+
toVector3(perspectiveConfig.position, [12, 12, 12], new THREE2.Vector3())
|
|
429
425
|
);
|
|
430
426
|
if (perspectiveConfig.zoom !== void 0) {
|
|
431
427
|
perspectiveCamera.zoom = perspectiveConfig.zoom;
|
|
@@ -442,11 +438,7 @@ var DualCameraControls = class extends import_camera_controls.default {
|
|
|
442
438
|
orthographicConfig.far ?? 2e3
|
|
443
439
|
);
|
|
444
440
|
orthographicCamera.position.copy(
|
|
445
|
-
toVector3(
|
|
446
|
-
orthographicConfig.position,
|
|
447
|
-
[12, 12, 12],
|
|
448
|
-
new THREE2.Vector3()
|
|
449
|
-
)
|
|
441
|
+
toVector3(orthographicConfig.position, [12, 12, 12], new THREE2.Vector3())
|
|
450
442
|
);
|
|
451
443
|
if (orthographicConfig.zoom !== void 0) {
|
|
452
444
|
orthographicCamera.zoom = orthographicConfig.zoom;
|
|
@@ -4846,7 +4838,7 @@ var ViewHelper = class extends THREE8.EventDispatcher {
|
|
|
4846
4838
|
renderer.autoClear = false;
|
|
4847
4839
|
renderer.setScissorTest(true);
|
|
4848
4840
|
renderer.setScissor(x, y, size, size);
|
|
4849
|
-
renderer.clear(
|
|
4841
|
+
renderer.clear(true, true, true);
|
|
4850
4842
|
renderer.render(this.scene, this.orthoCamera);
|
|
4851
4843
|
renderer.setScissorTest(false);
|
|
4852
4844
|
renderer.autoClear = autoClear;
|
|
@@ -4951,18 +4943,24 @@ var ViewHelper = class extends THREE8.EventDispatcher {
|
|
|
4951
4943
|
if (!controls) {
|
|
4952
4944
|
return;
|
|
4953
4945
|
}
|
|
4946
|
+
controls.enabled = false;
|
|
4954
4947
|
controls.stop?.();
|
|
4955
4948
|
this.animating = true;
|
|
4956
4949
|
this.dispatchEvent({ type: "animationStart" });
|
|
4957
|
-
const applyLookAt = () =>
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4950
|
+
const applyLookAt = () => {
|
|
4951
|
+
controls.setLookAt(
|
|
4952
|
+
this.targetPosition.x,
|
|
4953
|
+
this.targetPosition.y,
|
|
4954
|
+
this.targetPosition.z,
|
|
4955
|
+
focusPoint.x,
|
|
4956
|
+
focusPoint.y,
|
|
4957
|
+
focusPoint.z,
|
|
4958
|
+
true
|
|
4959
|
+
);
|
|
4960
|
+
setTimeout(() => {
|
|
4961
|
+
controls.enabled = true;
|
|
4962
|
+
}, 100);
|
|
4963
|
+
};
|
|
4966
4964
|
try {
|
|
4967
4965
|
void Promise.resolve(applyLookAt()).catch((error) => {
|
|
4968
4966
|
console.warn("ViewHelper: Unable to set camera look-at.", error);
|