Remove player collision logic from runtime-three module
This commit is contained in:
@@ -1,149 +0,0 @@
|
||||
import type { Vec3 } from "../core/vector";
|
||||
|
||||
import type { RuntimeBoxCollider } from "./runtime-scene-build";
|
||||
|
||||
export interface FirstPersonPlayerShape {
|
||||
radius: number;
|
||||
height: number;
|
||||
eyeHeight: number;
|
||||
}
|
||||
|
||||
export interface ResolvedPlayerMotion {
|
||||
feetPosition: Vec3;
|
||||
grounded: boolean;
|
||||
collidedAxes: {
|
||||
x: boolean;
|
||||
y: boolean;
|
||||
z: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const FIRST_PERSON_PLAYER_SHAPE: FirstPersonPlayerShape = {
|
||||
radius: 0.3,
|
||||
height: 1.8,
|
||||
eyeHeight: 1.6
|
||||
};
|
||||
|
||||
type Axis = "x" | "y" | "z";
|
||||
|
||||
interface RuntimeAabb {
|
||||
min: Vec3;
|
||||
max: Vec3;
|
||||
}
|
||||
|
||||
function createPlayerAabb(feetPosition: Vec3, shape: FirstPersonPlayerShape): RuntimeAabb {
|
||||
return {
|
||||
min: {
|
||||
x: feetPosition.x - shape.radius,
|
||||
y: feetPosition.y,
|
||||
z: feetPosition.z - shape.radius
|
||||
},
|
||||
max: {
|
||||
x: feetPosition.x + shape.radius,
|
||||
y: feetPosition.y + shape.height,
|
||||
z: feetPosition.z + shape.radius
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function rangesOverlap(minA: number, maxA: number, minB: number, maxB: number): boolean {
|
||||
return minA < maxB && maxA > minB;
|
||||
}
|
||||
|
||||
function resolveAxis(
|
||||
axis: Axis,
|
||||
nextFeetPosition: Vec3,
|
||||
delta: number,
|
||||
shape: FirstPersonPlayerShape,
|
||||
colliders: RuntimeBoxCollider[]
|
||||
): { collided: boolean; grounded: boolean } {
|
||||
if (delta === 0) {
|
||||
return {
|
||||
collided: false,
|
||||
grounded: false
|
||||
};
|
||||
}
|
||||
|
||||
nextFeetPosition[axis] += delta;
|
||||
|
||||
let collided = false;
|
||||
let grounded = false;
|
||||
|
||||
for (const collider of colliders) {
|
||||
const playerAabb = createPlayerAabb(nextFeetPosition, shape);
|
||||
const overlapsOtherAxes =
|
||||
axis === "x"
|
||||
? rangesOverlap(playerAabb.min.y, playerAabb.max.y, collider.min.y, collider.max.y) &&
|
||||
rangesOverlap(playerAabb.min.z, playerAabb.max.z, collider.min.z, collider.max.z)
|
||||
: axis === "y"
|
||||
? rangesOverlap(playerAabb.min.x, playerAabb.max.x, collider.min.x, collider.max.x) &&
|
||||
rangesOverlap(playerAabb.min.z, playerAabb.max.z, collider.min.z, collider.max.z)
|
||||
: rangesOverlap(playerAabb.min.x, playerAabb.max.x, collider.min.x, collider.max.x) &&
|
||||
rangesOverlap(playerAabb.min.y, playerAabb.max.y, collider.min.y, collider.max.y);
|
||||
|
||||
if (!overlapsOtherAxes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (axis) {
|
||||
case "x":
|
||||
if (delta > 0 && playerAabb.max.x > collider.min.x && playerAabb.min.x < collider.min.x) {
|
||||
nextFeetPosition.x = collider.min.x - shape.radius;
|
||||
collided = true;
|
||||
} else if (delta < 0 && playerAabb.min.x < collider.max.x && playerAabb.max.x > collider.max.x) {
|
||||
nextFeetPosition.x = collider.max.x + shape.radius;
|
||||
collided = true;
|
||||
}
|
||||
break;
|
||||
case "y":
|
||||
if (delta > 0 && playerAabb.max.y > collider.min.y && playerAabb.min.y < collider.min.y) {
|
||||
nextFeetPosition.y = collider.min.y - shape.height;
|
||||
collided = true;
|
||||
} else if (delta < 0 && playerAabb.min.y < collider.max.y && playerAabb.max.y > collider.max.y) {
|
||||
nextFeetPosition.y = collider.max.y;
|
||||
collided = true;
|
||||
grounded = true;
|
||||
}
|
||||
break;
|
||||
case "z":
|
||||
if (delta > 0 && playerAabb.max.z > collider.min.z && playerAabb.min.z < collider.min.z) {
|
||||
nextFeetPosition.z = collider.min.z - shape.radius;
|
||||
collided = true;
|
||||
} else if (delta < 0 && playerAabb.min.z < collider.max.z && playerAabb.max.z > collider.max.z) {
|
||||
nextFeetPosition.z = collider.max.z + shape.radius;
|
||||
collided = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
collided,
|
||||
grounded
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveFirstPersonMotion(
|
||||
feetPosition: Vec3,
|
||||
motion: Vec3,
|
||||
shape: FirstPersonPlayerShape,
|
||||
colliders: RuntimeBoxCollider[]
|
||||
): ResolvedPlayerMotion {
|
||||
const nextFeetPosition = {
|
||||
...feetPosition
|
||||
};
|
||||
|
||||
const xResolution = resolveAxis("x", nextFeetPosition, motion.x, shape, colliders);
|
||||
const zResolution = resolveAxis("z", nextFeetPosition, motion.z, shape, colliders);
|
||||
const yResolution = resolveAxis("y", nextFeetPosition, motion.y, shape, colliders);
|
||||
|
||||
return {
|
||||
feetPosition: nextFeetPosition,
|
||||
grounded: yResolution.grounded,
|
||||
collidedAxes: {
|
||||
x: xResolution.collided,
|
||||
y: yResolution.collided,
|
||||
z: zResolution.collided
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user