mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
127 lines • 5.77 kB
JavaScript
import { createEffect } from "@lincode/reactivity";
import { forceGet } from "@lincode/utils";
import { onBeforeRender } from "../../../../events/onBeforeRender";
import { getBVHMap } from "../../../../states/useBVHMap";
import { getCentripetal } from "../../../../states/useCentripetal";
import { getGravity } from "../../../../states/useGravity";
import { getRepulsion } from "../../../../states/useRepulsion";
import { box3, line3, vector3, vector3_, vector3_0, vector3__ } from "../../../utils/reusables";
import bvhContactMap from "./bvhContactMap";
import getWorldPosition from "../../../utils/getWorldPosition";
import { getEditing } from "../../../../states/useEditing";
import { bvhCharacterSet } from "./bvhCharacterSet";
import { bvhManagerMap } from "./bvhManagerMap";
import { fpsRatio } from "../../../../engine/eventLoop";
import { getFirstLoad } from "../../../../states/useFirstLoad";
import { getBVHComputing } from "../../../../states/useBVHComputingCount";
const makeWeakSet = () => new WeakSet();
createEffect(function () {
if (getEditing() || !getFirstLoad() || getBVHComputing())
return;
const bvhArray = getBVHMap();
if (!bvhArray.length)
return;
const gravity = getGravity();
const repulsion = getRepulsion();
const delta = 0.02;
const centripetal = getCentripetal();
const handle = onBeforeRender(() => {
bvhContactMap.clear();
for (const characterManager of bvhCharacterSet) {
const playerVelocity = characterManager.bvhVelocity;
const player = characterManager.outerObject3d;
const capsuleHalfHeight = characterManager.bvhHalfHeight;
const capsuleRadius = centripetal
? capsuleHalfHeight
: characterManager.bvhRadius;
if (centripetal) {
playerVelocity.add(characterManager.bvhOnGround ||
characterManager._gravity === false
? vector3_0
: getWorldPosition(player)
.normalize()
.multiplyScalar(delta * -gravity * fpsRatio[0]));
}
else
playerVelocity.y +=
characterManager.bvhOnGround ||
characterManager._gravity === false
? 0
: delta * -gravity * fpsRatio[0];
const updatePosition = characterManager.positionUpdate;
updatePosition.x && (playerVelocity.x = 0);
updatePosition.y && (playerVelocity.y = 0);
updatePosition.z && (playerVelocity.z = 0);
updatePosition.reset();
player.position.addScaledVector(playerVelocity, delta);
player.updateMatrixWorld();
const { start, end } = line3;
end.copy(start.copy(player.position));
const yOffset = Math.max(capsuleHalfHeight - capsuleRadius, 0);
end.y += yOffset;
start.y -= yOffset;
const startOld = start.clone();
box3.setFromCenterAndSize(player.position, vector3__.set(capsuleRadius * 2, capsuleHalfHeight * 2, capsuleRadius * 2));
const triPoint = vector3;
const capsulePoint = vector3_;
let distance = 0;
let direction;
let contact = false;
let mapManager;
for (const boundsTree of bvhArray) {
mapManager = bvhManagerMap.get(boundsTree);
boundsTree.shapecast({
intersectsBounds: (box) => box.intersectsBox(box3),
intersectsTriangle: (tri) => {
distance = tri.closestPointToSegment(line3, triPoint, capsulePoint);
if (distance < capsuleRadius) {
contact = true;
direction = capsulePoint
.sub(triPoint)
.normalize()
.multiplyScalar(capsuleRadius - distance);
start.add(direction);
end.add(direction);
}
}
});
}
if (contact && mapManager)
forceGet(bvhContactMap, characterManager, makeWeakSet).add(mapManager);
const deltaVector = start.sub(startOld);
if (centripetal)
characterManager.bvhOnGround = contact;
else {
characterManager.bvhOnGround =
deltaVector.y >
Math.abs(delta * playerVelocity.y * 0.25);
if (repulsion &&
characterManager.bvhOnGround &&
Math.abs(deltaVector.y /
(deltaVector.x + deltaVector.z + Number.EPSILON)) < repulsion)
characterManager.bvhOnGround = false;
}
const offset = Math.max(0.0, deltaVector.length() - 1e-5);
deltaVector.normalize().multiplyScalar(offset);
player.position.add(deltaVector);
if (!characterManager.bvhOnGround) {
deltaVector.normalize();
playerVelocity.addScaledVector(deltaVector, -deltaVector.dot(playerVelocity));
}
else
playerVelocity.set(0, 0, 0);
}
});
return () => {
handle.cancel();
};
}, [
getBVHMap,
getGravity,
getRepulsion,
getCentripetal,
getEditing,
getFirstLoad,
getBVHComputing
]);
//# sourceMappingURL=bvhLoop.js.map