refacto : cleaning the codebasebase again

This commit is contained in:
Tom Boullay
2026-04-19 16:50:11 +02:00
parent 1c48441535
commit 0f96b5597b
26 changed files with 127 additions and 5726 deletions
+4 -14
View File
@@ -2,35 +2,25 @@ import { useEffect, useRef } from "react";
import { useThree } from "@react-three/fiber";
import { useGLTF } from "@react-three/drei";
import * as THREE from "three";
import { Octree } from "three/addons/math/Octree.js";
import { MAP_DEBUG_BOX_HELPER_COLOR } from "@/data/debugConfig";
import { useOctreeGraphNode } from "@/hooks/useOctreeGraphNode";
import type { OctreeReadyHandler } from "@/types/3d";
import { Debug } from "@/utils/debug/Debug";
const MAP_PATH = "/models/map/model.gltf";
interface MapProps {
onOctreeReady: (octree: Octree) => void;
onOctreeReady: OctreeReadyHandler;
}
export function Map({ onOctreeReady }: MapProps): React.JSX.Element {
const { scene: gltfScene } = useGLTF(MAP_PATH);
const groupRef = useRef<THREE.Group>(null);
const octreeBuilt = useRef(false);
const boxHelpersRef = useRef<THREE.BoxHelper[]>([]);
const { scene } = useThree();
useEffect(() => {
if (octreeBuilt.current || !groupRef.current) return;
octreeBuilt.current = true;
useOctreeGraphNode(groupRef, onOctreeReady);
groupRef.current.updateMatrixWorld(true);
const octree = new Octree();
octree.fromGraphNode(groupRef.current);
onOctreeReady(octree);
}, [onOctreeReady]);
// BoxHelper wireframes in debug mode — one per mesh in the model
useEffect(() => {
const debug = Debug.getInstance();
if (!debug.active || !groupRef.current) return;
+5 -14
View File
@@ -1,7 +1,6 @@
import { useEffect, useRef } from "react";
import { useRef } from "react";
import { Physics, RigidBody, CuboidCollider } from "@react-three/rapier";
import * as THREE from "three";
import { Octree } from "three/addons/math/Octree.js";
import { GrabbableObject } from "@/components/3d/GrabbableObject";
import { TriggerObject } from "@/components/3d/TriggerObject";
import {
@@ -21,27 +20,19 @@ import {
TEST_SCENE_TRIGGER_SEGMENTS,
TEST_SCENE_TRIGGER_SOUND_PATH,
} from "@/data/testSceneConfig";
import { useOctreeGraphNode } from "@/hooks/useOctreeGraphNode";
import type { OctreeReadyHandler } from "@/types/3d";
interface TestSceneProps {
onOctreeReady: (octree: Octree) => void;
onOctreeReady: OctreeReadyHandler;
}
export function TestScene({
onOctreeReady,
}: TestSceneProps): React.JSX.Element {
const floorRef = useRef<THREE.Group>(null);
const octreeBuilt = useRef(false);
useEffect(() => {
if (octreeBuilt.current || !floorRef.current) return;
octreeBuilt.current = true;
floorRef.current.updateMatrixWorld(true);
const octree = new Octree();
octree.fromGraphNode(floorRef.current);
onOctreeReady(octree);
}, [onOctreeReady]);
useOctreeGraphNode(floorRef, onOctreeReady);
return (
<>
+3 -7
View File
@@ -1,22 +1,18 @@
import { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import type { Octree } from "three/addons/math/Octree.js";
import {
PLAYER_SPAWN_X,
PLAYER_SPAWN_Y_DEFAULT,
PLAYER_SPAWN_Z,
} from "@/data/playerConfig";
import { PLAYER_SPAWN_X, PLAYER_SPAWN_Z } from "@/data/playerConfig";
import { PlayerCamera } from "@/world/player/PlayerCamera";
import { PlayerController } from "@/world/player/PlayerController";
interface PlayerComponentProps {
octree?: Octree | null;
spawnY?: number;
spawnY: number;
}
export function PlayerComponent({
octree = null,
spawnY = PLAYER_SPAWN_Y_DEFAULT,
spawnY,
}: PlayerComponentProps): React.JSX.Element {
const camera = useThree((state) => state.camera);
+1 -12
View File
@@ -60,7 +60,6 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
const onFloor = useRef(false);
const wantsJump = useRef(false);
// Capsule: start = feet, end = eyes
const capsule = useRef(
new Capsule(
new THREE.Vector3(0, PLAYER_CAPSULE_RADIUS, 0),
@@ -69,7 +68,6 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
),
);
// Sync capsule to camera spawn position on mount
useEffect(() => {
const spawnY = camera.position.y;
capsule.current.start.set(
@@ -78,8 +76,7 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
PLAYER_SPAWN_Z,
);
capsule.current.end.set(PLAYER_SPAWN_X, spawnY, PLAYER_SPAWN_Z);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [camera]);
useEffect(() => {
const interaction = InteractionManager.getInstance();
@@ -168,7 +165,6 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
useFrame((_, delta) => {
const dt = Math.min(delta, PLAYER_MAX_DELTA);
// Compute wish direction from camera yaw (XZ only)
camera.getWorldDirection(_forward);
_forward.setY(0);
if (_forward.lengthSq() > 0) {
@@ -183,7 +179,6 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
if (keys.current.right) _wishDir.add(_right);
if (_wishDir.lengthSq() > 0) _wishDir.normalize();
// Accelerate horizontally
const accel = onFloor.current
? PLAYER_WALK_SPEED
: PLAYER_WALK_SPEED * PLAYER_AIR_CONTROL_FACTOR;
@@ -196,7 +191,6 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
velocity.current.x *= damping;
velocity.current.z *= damping;
// Gravity + jump
if (onFloor.current) {
velocity.current.y = Math.max(0, velocity.current.y);
if (wantsJump.current) {
@@ -208,11 +202,9 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
}
wantsJump.current = false;
// Move capsule
_translateVec.copy(velocity.current).multiplyScalar(dt);
capsule.current.translate(_translateVec);
// Resolve collisions against octree
if (octree) {
const result = octree.capsuleIntersect(capsule.current);
onFloor.current = false;
@@ -221,21 +213,18 @@ export function PlayerController({ octree }: PlayerControllerProps): null {
onFloor.current = result.normal.y > 0;
if (!onFloor.current) {
// Cancel velocity component going into the wall
const vn = result.normal.dot(velocity.current);
velocity.current.addScaledVector(result.normal, -vn);
} else {
velocity.current.y = Math.max(0, velocity.current.y);
}
// Push capsule out of geometry
capsule.current.translate(
result.normal.clone().multiplyScalar(result.depth),
);
}
}
// Sync camera to capsule top (eye position)
camera.position.copy(capsule.current.end);
});