mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
77 lines • 3.33 kB
JavaScript
import store, { createEffect } from "@lincode/reactivity";
import { OrthographicCamera, PerspectiveCamera } from "three";
import interpolationCamera from "../engine/interpolationCamera";
import mainCamera from "../engine/mainCamera";
import { getCameraStack } from "./useCameraStack";
import { last } from "@lincode/utils";
import { onBeforeRender } from "../events/onBeforeRender";
import { getResolution } from "./useResolution";
import { ORTHOGRAPHIC_FRUSTUM } from "../globals";
import getWorldPosition from "../display/utils/getWorldPosition";
import getWorldQuaternion from "../display/utils/getWorldQuaternion";
import fpsAlpha from "../display/utils/fpsAlpha";
import { getWebXR } from "./useWebXR";
export const [setCameraRendered, getCameraRendered] = store(mainCamera);
export const updateCameraAspect = (camera) => {
const [resX, resY] = getResolution();
const aspect = resX / resY;
if (camera instanceof PerspectiveCamera && !getWebXR()) {
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
else if (camera instanceof OrthographicCamera) {
;
[camera.left, camera.right, camera.top, camera.bottom] = [
aspect * ORTHOGRAPHIC_FRUSTUM * -0.5,
aspect * ORTHOGRAPHIC_FRUSTUM * 0.5,
ORTHOGRAPHIC_FRUSTUM * 0.5,
ORTHOGRAPHIC_FRUSTUM * -0.5
];
camera.updateProjectionMatrix();
}
return [resX, resY, aspect];
};
const lerp = (a, b, t) => a + (b - a) * t;
let cameraLast;
createEffect(() => {
const cameraFrom = getCameraRendered() === interpolationCamera
? interpolationCamera
: cameraLast;
const cameraTo = (cameraLast = last(getCameraStack()));
const transition = cameraTo.userData.transition;
if (!cameraFrom ||
!transition ||
cameraFrom === cameraTo ||
cameraFrom === mainCamera ||
cameraTo === mainCamera) {
setCameraRendered(cameraTo);
return;
}
setCameraRendered(interpolationCamera);
const positionFrom = getWorldPosition(cameraFrom);
const quaternionFrom = getWorldQuaternion(cameraFrom);
interpolationCamera.zoom = cameraFrom.zoom;
interpolationCamera.fov = cameraFrom.fov;
updateCameraAspect(interpolationCamera);
let ratio = 0;
const diffMax = typeof transition === "number" ? transition : Infinity;
const handle = onBeforeRender(() => {
const positionTo = getWorldPosition(cameraTo);
const quaternionTo = getWorldQuaternion(cameraTo);
interpolationCamera.position.lerpVectors(positionFrom, positionTo, ratio);
interpolationCamera.quaternion.slerpQuaternions(quaternionFrom, quaternionTo, ratio);
interpolationCamera.zoom = lerp(cameraFrom.zoom, cameraTo.zoom, ratio);
interpolationCamera.fov = lerp(cameraFrom.fov, cameraTo.fov, ratio);
interpolationCamera.updateProjectionMatrix();
ratio = Math.min((1 - ratio) * fpsAlpha(0.1), diffMax) + ratio;
if (ratio < 0.9999)
return;
setCameraRendered(cameraTo);
updateCameraAspect(cameraTo);
handle.cancel();
});
return () => {
handle.cancel();
};
}, [getCameraStack]);
//# sourceMappingURL=useCameraRendered.js.map