|
@@ -1,4 +1,4 @@
|
|
-import { ref, watch } from "vue";
|
|
|
|
|
|
+import { ref, watch, watchEffect } from "vue";
|
|
import {
|
|
import {
|
|
installThreeGlobalVar,
|
|
installThreeGlobalVar,
|
|
useCamera,
|
|
useCamera,
|
|
@@ -8,9 +8,12 @@ import {
|
|
import { OrbitControls } from "three/examples/jsm/Addons.js";
|
|
import { OrbitControls } from "three/examples/jsm/Addons.js";
|
|
import { listener } from "@/utils/event";
|
|
import { listener } from "@/utils/event";
|
|
import { PerspectiveCamera, Vector3 } from "three";
|
|
import { PerspectiveCamera, Vector3 } from "three";
|
|
-import { mergeFuns } from "@/utils/shared";
|
|
|
|
|
|
+import { frameEebounce, frameInterval, mergeFuns } from "@/utils/shared";
|
|
import { useMouseEventRegister } from "./use-event";
|
|
import { useMouseEventRegister } from "./use-event";
|
|
import { subgroupName } from "../container";
|
|
import { subgroupName } from "../container";
|
|
|
|
+import { useCameraAnimation } from "./use-animation";
|
|
|
|
+import { getDownKeys } from "@/core/hook/use-global-vars";
|
|
|
|
+import { getMoveDirectrionByKeys } from "./use-downkeys";
|
|
|
|
|
|
const getModelControls = (
|
|
const getModelControls = (
|
|
container: HTMLDivElement,
|
|
container: HTMLDivElement,
|
|
@@ -42,19 +45,17 @@ const getModelControls = (
|
|
enable() {
|
|
enable() {
|
|
controls.enabled = true;
|
|
controls.enabled = true;
|
|
},
|
|
},
|
|
- recover() {
|
|
|
|
- if (prevOrigin && prevDire) {
|
|
|
|
- camera.position.copy(prevOrigin);
|
|
|
|
- camera.lookAt(prevOrigin.add(prevDire));
|
|
|
|
- controls.update();
|
|
|
|
- render();
|
|
|
|
- }
|
|
|
|
|
|
+ get current() {
|
|
|
|
+ return {
|
|
|
|
+ prevOrigin,
|
|
|
|
+ prevDire,
|
|
|
|
+ };
|
|
},
|
|
},
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
const getRoamingControls = (
|
|
const getRoamingControls = (
|
|
-container: HTMLDivElement,
|
|
|
|
|
|
+ container: HTMLDivElement,
|
|
camera: PerspectiveCamera,
|
|
camera: PerspectiveCamera,
|
|
render: () => void
|
|
render: () => void
|
|
) => {
|
|
) => {
|
|
@@ -73,15 +74,41 @@ container: HTMLDivElement,
|
|
let prevDire: Vector3 | null = null;
|
|
let prevDire: Vector3 | null = null;
|
|
|
|
|
|
const unListener = listener(controls as any, "change", render);
|
|
const unListener = listener(controls as any, "change", render);
|
|
|
|
+ const { direction, onDestory: onDownDestory } = getMoveDirectrionByKeys();
|
|
|
|
+ const stopWatchDirection = watch(direction, (dire, _, onCleanup) => {
|
|
|
|
+ if (!controls.enabled || !dire) return;
|
|
|
|
+ onCleanup(frameInterval(() => {
|
|
|
|
+ const cameraDire = camera.getWorldDirection(new Vector3())
|
|
|
|
+ cameraDire.y = 0
|
|
|
|
+ cameraDire.normalize()
|
|
|
|
+
|
|
|
|
+ const rightDire = new Vector3(0, 1, 0).cross(cameraDire)
|
|
|
|
+ const moveDire = new Vector3()
|
|
|
|
+ if (dire.y) {
|
|
|
|
+ moveDire.addScaledVector(cameraDire, dire.y)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (dire.x) {
|
|
|
|
+ moveDire.addScaledVector(rightDire, -dire.x)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (moveDire.length() > 0) {
|
|
|
|
+ camera.position.addScaledVector(moveDire.normalize(), 2)
|
|
|
|
+ syncCamera();
|
|
|
|
+ render();
|
|
|
|
+ }
|
|
|
|
+ }));
|
|
|
|
+ });
|
|
|
|
|
|
return {
|
|
return {
|
|
controls,
|
|
controls,
|
|
onDestory() {
|
|
onDestory() {
|
|
controls.dispose();
|
|
controls.dispose();
|
|
unListener();
|
|
unListener();
|
|
|
|
+ onDownDestory();
|
|
|
|
+ stopWatchDirection();
|
|
},
|
|
},
|
|
syncCamera,
|
|
syncCamera,
|
|
-
|
|
|
|
disable() {
|
|
disable() {
|
|
prevOrigin = camera.position.clone();
|
|
prevOrigin = camera.position.clone();
|
|
prevDire = camera.getWorldDirection(new Vector3());
|
|
prevDire = camera.getWorldDirection(new Vector3());
|
|
@@ -91,15 +118,11 @@ container: HTMLDivElement,
|
|
controls.enabled = true;
|
|
controls.enabled = true;
|
|
render();
|
|
render();
|
|
},
|
|
},
|
|
- recover() {
|
|
|
|
- if (prevOrigin && prevDire) {
|
|
|
|
- camera.position.copy(prevOrigin);
|
|
|
|
- camera.lookAt(prevOrigin.add(prevDire));
|
|
|
|
- prevOrigin = prevDire = null;
|
|
|
|
-
|
|
|
|
- syncCamera();
|
|
|
|
- render();
|
|
|
|
- }
|
|
|
|
|
|
+ get current() {
|
|
|
|
+ return {
|
|
|
|
+ prevOrigin,
|
|
|
|
+ prevDire,
|
|
|
|
+ };
|
|
},
|
|
},
|
|
};
|
|
};
|
|
};
|
|
};
|
|
@@ -164,53 +187,55 @@ export const useControls = installThreeGlobalVar(() => {
|
|
export const useFlyRoaming = installThreeGlobalVar(() => {
|
|
export const useFlyRoaming = installThreeGlobalVar(() => {
|
|
const camera = useCamera();
|
|
const camera = useCamera();
|
|
const { type, value: controls } = useControls();
|
|
const { type, value: controls } = useControls();
|
|
|
|
+ const cameraAnimation = useCameraAnimation();
|
|
|
|
|
|
- return (point: Vector3) => {
|
|
|
|
|
|
+ return async (point: Vector3) => {
|
|
type.value = undefined;
|
|
type.value = undefined;
|
|
const position = point.clone().add({ x: 0, y: 100, z: 0 });
|
|
const position = point.clone().add({ x: 0, y: 100, z: 0 });
|
|
const direction = camera.getWorldDirection(new Vector3());
|
|
const direction = camera.getWorldDirection(new Vector3());
|
|
const target = position.clone().add(direction);
|
|
const target = position.clone().add(direction);
|
|
- camera.position.copy(position);
|
|
|
|
- camera.lookAt(target);
|
|
|
|
-
|
|
|
|
|
|
+ await cameraAnimation(position, target);
|
|
type.value = "roaming";
|
|
type.value = "roaming";
|
|
controls.value!.syncCamera();
|
|
controls.value!.syncCamera();
|
|
};
|
|
};
|
|
-})
|
|
|
|
|
|
+});
|
|
|
|
|
|
export const useFlyModel = installThreeGlobalVar(() => {
|
|
export const useFlyModel = installThreeGlobalVar(() => {
|
|
const camera = useCamera();
|
|
const camera = useCamera();
|
|
const { type, value: controls } = useControls();
|
|
const { type, value: controls } = useControls();
|
|
|
|
+ const cameraAnimation = useCameraAnimation();
|
|
|
|
|
|
- return (set?: {point: Vector3, direction: Vector3}) => {
|
|
|
|
|
|
+ return async (set: { point?: Vector3; direction?: Vector3 } = {}) => {
|
|
type.value = "model";
|
|
type.value = "model";
|
|
- if (set) {
|
|
|
|
- const position = set.point.clone().add({ x: 0, y: 100, z: 0 });
|
|
|
|
- const direction = set.direction
|
|
|
|
- const target = position.clone().add(direction);
|
|
|
|
- camera.position.copy(position);
|
|
|
|
- camera.lookAt(target);
|
|
|
|
- controls.value?.syncCamera()
|
|
|
|
- } else {
|
|
|
|
- controls.value!.recover();
|
|
|
|
|
|
+ const prev = controls.value!.current;
|
|
|
|
+ if (!set.point) {
|
|
|
|
+ set.point = prev.prevOrigin || camera.position.clone();
|
|
|
|
+ }
|
|
|
|
+ if (!set.direction) {
|
|
|
|
+ set.direction = prev.prevDire || camera.getWorldDirection(new Vector3());
|
|
}
|
|
}
|
|
- }
|
|
|
|
-})
|
|
|
|
|
|
+
|
|
|
|
+ const direction = set.direction;
|
|
|
|
+ const target = set.point.clone().add(direction);
|
|
|
|
+ await cameraAnimation(set.point, target);
|
|
|
|
+ controls.value?.syncCamera();
|
|
|
|
+ };
|
|
|
|
+});
|
|
|
|
|
|
export const installAutoSwitchControls = installThreeGlobalVar(() => {
|
|
export const installAutoSwitchControls = installThreeGlobalVar(() => {
|
|
const { type } = useControls();
|
|
const { type } = useControls();
|
|
const mouseRegister = useMouseEventRegister();
|
|
const mouseRegister = useMouseEventRegister();
|
|
- const flyRoaming = useFlyRoaming()
|
|
|
|
- const flyModel = useFlyModel()
|
|
|
|
|
|
+ const flyRoaming = useFlyRoaming();
|
|
|
|
+ const flyModel = useFlyModel();
|
|
|
|
|
|
type.value = "model";
|
|
type.value = "model";
|
|
const onDestroy = mergeFuns(
|
|
const onDestroy = mergeFuns(
|
|
listener(document.documentElement, "keydown", (ev) => {
|
|
listener(document.documentElement, "keydown", (ev) => {
|
|
if (ev.key === "Escape" && type.value !== "model") {
|
|
if (ev.key === "Escape" && type.value !== "model") {
|
|
- flyModel()
|
|
|
|
|
|
+ flyModel();
|
|
}
|
|
}
|
|
}),
|
|
}),
|
|
- mouseRegister(subgroupName, "dblclick", ({ point }) => flyRoaming(point)),
|
|
|
|
|
|
+ mouseRegister(subgroupName, "dblclick", ({ point }) => flyRoaming(point))
|
|
);
|
|
);
|
|
|
|
|
|
return { onDestroy };
|
|
return { onDestroy };
|