mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
96 lines (81 loc) • 3.48 kB
text/typescript
import { createEffect } from "@lincode/reactivity"
import mainCamera from "../../engine/mainCamera"
import { onBeforeCameraLoop } from "../../events/onBeforeCameraLoop"
import { onBeforeRender } from "../../events/onBeforeRender"
import IThirdPersonCamera, {
thirdPersonCameraDefaults,
thirdPersonCameraSchema
} from "../../interface/IThirdPersonCamera"
import { getCameraRendered } from "../../states/useCameraRendered"
import { getEditing } from "../../states/useEditing"
import { getEditorMounted } from "../../states/useEditorMounted"
import CharacterCamera from "../core/CharacterCamera"
import MeshItem from "../core/MeshItem"
import { bvhCameraSet } from "../core/PhysicsObjectManager/bvh/bvhCameraSet"
import StaticObjectManager from "../core/StaticObjectManager"
import fpsAlpha from "../utils/fpsAlpha"
import getWorldPosition from "../utils/getWorldPosition"
import getWorldQuaternion from "../utils/getWorldQuaternion"
const setVisible = (
target: MeshItem | StaticObjectManager,
visible: boolean
) => {
"visible" in target && (target.visible = visible)
}
let alwaysVisible = false
createEffect(() => {
alwaysVisible =
getEditing() ||
(!!getEditorMounted() && getCameraRendered() === mainCamera)
}, [getEditing, getEditorMounted, getCameraRendered])
export default class ThirdPersonCamera
extends CharacterCamera
implements IThirdPersonCamera
{
public static componentName = "thirdPersonCamera"
public static override defaults = thirdPersonCameraDefaults
public static override schema = thirdPersonCameraSchema
public constructor() {
super()
this.innerZ = 300
this.orbitMode = true
const cam = this.camera
import("../core/PhysicsObjectManager/bvh/bvhCameraLoop").then(() => {
this.createEffect(() => {
const target = this.targetState.get()
if (!target) {
const handle = onBeforeRender(() => {
cam.position.copy(getWorldPosition(this.object3d))
cam.quaternion.copy(getWorldQuaternion(this.object3d))
})
return () => {
handle.cancel()
}
}
bvhCameraSet.add(cam)
let tooCloseOld = true
setVisible(target, !tooCloseOld)
let first = true
const handle = onBeforeCameraLoop(() => {
const origin = getWorldPosition(this.outerObject3d)
const camPos = getWorldPosition(this.object3d)
const dist = camPos.distanceTo(origin)
cam.position.lerp(camPos, first ? 1 : fpsAlpha(0.1))
const ratio = first
? 1
: cam.position.distanceTo(origin) / dist
cam.position.lerpVectors(origin, camPos, ratio)
cam.quaternion.copy(getWorldQuaternion(this.object3d))
const tooClose = alwaysVisible ? false : ratio < 0.35
tooClose !== tooCloseOld && setVisible(target, !tooClose)
tooCloseOld = tooClose
first = false
})
return () => {
handle.cancel()
bvhCameraSet.delete(cam)
}
}, [this.targetState.get])
})
}
}