mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
68 lines (58 loc) • 2.36 kB
text/typescript
import { createEffect } from "@lincode/reactivity"
import { Box3 } from "three"
import { emitBeforeCameraLoop } from "../../../../events/onBeforeCameraLoop"
import { onBeforeRender } from "../../../../events/onBeforeRender"
import { getBVHMap } from "../../../../states/useBVHMap"
import getWorldDirection from "../../../utils/getWorldDirection"
import { box3, line3, vector3, vector3_ } from "../../../utils/reusables"
import { bvhCameraSet } from "./bvhCameraSet"
createEffect(() => {
const bvhArray = getBVHMap()
if (!bvhArray.length) {
const handle = onBeforeRender(emitBeforeCameraLoop)
return () => {
handle.cancel()
}
}
const handle = onBeforeRender(() => {
emitBeforeCameraLoop()
for (const cam of bvhCameraSet) {
const capsuleRadius = 0.5
cam.updateMatrixWorld()
const direction = getWorldDirection(cam)
const { start, end } = line3
end.copy(start.copy(cam.position))
box3.makeEmpty()
box3.expandByPoint(start)
box3.min.addScalar(-capsuleRadius)
box3.max.addScalar(capsuleRadius)
const triPoint = vector3
const capsulePoint = vector3_
let distance = 0
let depth = 0
for (const boundsTree of bvhArray)
boundsTree.shapecast({
intersectsBounds: (box: Box3) => box.intersectsBox(box3),
intersectsTriangle: (tri: any) => {
distance = tri.closestPointToSegment(
line3,
triPoint,
capsulePoint
)
if (distance < capsuleRadius) {
depth = capsuleRadius - distance
start.addScaledVector(direction, depth)
end.addScaledVector(direction, depth)
}
}
})
const deltaVector = start.sub(cam.position)
const offset = Math.max(0.0, deltaVector.length() - 1e-5)
deltaVector.normalize().multiplyScalar(offset)
cam.position.add(deltaVector)
}
})
return () => {
handle.cancel()
}
}, [getBVHMap])