fix(world): stabilize lafabrik spawn and vegetation

This commit is contained in:
Tom Boullay
2026-06-01 01:32:21 +02:00
parent 061e0dc677
commit aa2d411b0c
12 changed files with 51 additions and 110 deletions
+5 -1
View File
@@ -15,5 +15,9 @@ export const PLAYER_XZ_DAMPING_FACTOR = 8;
export const PLAYER_FALL_RESPAWN_Y = -20;
export const PLAYER_FALL_RESPAWN_DELAY = 3;
export const PLAYER_SPAWN_POSITION_GAME: Vector3Tuple = LA_FABRIK_PLAYER_SPAWN;
export const PLAYER_SPAWN_POSITION_GAME: Vector3Tuple = [
LA_FABRIK_PLAYER_SPAWN[0] + 5,
LA_FABRIK_PLAYER_SPAWN[1],
LA_FABRIK_PLAYER_SPAWN[2] + 5,
];
export const PLAYER_SPAWN_POSITION_PHYSICS: Vector3Tuple = [0, 3, 0];
@@ -20,7 +20,6 @@ export interface CharacterConfig {
scale: Vector3Tuple;
animations: readonly string[];
defaultAnimation: string;
snapToTerrain?: boolean;
}
export const CHARACTER_CONFIGS = {
+2 -56
View File
@@ -1,4 +1,3 @@
import * as THREE from "three";
import type { Vector3Tuple } from "@/types/three/three";
export const LA_FABRIK_CENTER: Vector3Tuple = [59.4973, 6.2746, 64.6354];
@@ -7,15 +6,10 @@ export const LA_FABRIK_HALF_EXTENTS = {
x: 8.5,
z: 7.5,
} as const;
export const LA_FABRIK_FLOOR_Y = 6.3;
export const LA_FABRIK_PLAYER_SPAWN: Vector3Tuple = [59.5, 8.05, 64.64];
export const LA_FABRIK_PLAYER_SPAWN: Vector3Tuple = [59.5, 7.8, 64.64];
export const LA_FABRIK_INITIAL_LOOK_AT: Vector3Tuple = [58, 7.8, 62.5];
export const LA_FABRIK_INTERIOR_LIGHT_POSITION: Vector3Tuple = [59.5, 9, 64.64];
const _terrainMatrix = new THREE.Matrix4();
const _meshWorldMatrix = new THREE.Matrix4();
const _inverseMeshWorldMatrix = new THREE.Matrix4();
const _worldPosition = new THREE.Vector3();
export function isInsideLaFabrikFootprint(
x: number,
z: number,
@@ -33,51 +27,3 @@ export function isInsideLaFabrikFootprint(
Math.abs(localZ) <= LA_FABRIK_HALF_EXTENTS.z + padding
);
}
export function flattenLaFabrikTerrainFootprint(
object: THREE.Object3D,
position: Vector3Tuple,
rotation: Vector3Tuple,
scale: Vector3Tuple,
): void {
_terrainMatrix.compose(
new THREE.Vector3(...position),
new THREE.Quaternion().setFromEuler(new THREE.Euler(...rotation)),
new THREE.Vector3(...scale),
);
object.updateMatrixWorld(true);
object.traverse((child) => {
if (!(child instanceof THREE.Mesh)) return;
const geometry = child.geometry;
const positions = geometry.getAttribute("position");
if (!positions) return;
_meshWorldMatrix.multiplyMatrices(_terrainMatrix, child.matrixWorld);
_inverseMeshWorldMatrix.copy(_meshWorldMatrix).invert();
for (let index = 0; index < positions.count; index++) {
_worldPosition
.fromBufferAttribute(positions, index)
.applyMatrix4(_meshWorldMatrix);
if (!isInsideLaFabrikFootprint(_worldPosition.x, _worldPosition.z, 0.8)) {
continue;
}
_worldPosition.y = Math.min(_worldPosition.y, LA_FABRIK_FLOOR_Y - 0.35);
_worldPosition.applyMatrix4(_inverseMeshWorldMatrix);
positions.setXYZ(
index,
_worldPosition.x,
_worldPosition.y,
_worldPosition.z,
);
}
positions.needsUpdate = true;
geometry.computeVertexNormals();
geometry.computeBoundingBox();
geometry.computeBoundingSphere();
});
}