21 Commits

Author SHA1 Message Date
math-pixel a397febd52 fix zoom
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
2026-05-27 17:23:06 +02:00
math-pixel c15cad2ab0 fix zoom 2026-05-27 17:22:14 +02:00
math-pixel 011e7815a2 update gps 2026-05-27 17:15:08 +02:00
math-pixel 970253801a add map on bike 2026-05-22 18:28:05 +02:00
math-pixel 246da0019a add transparency gps 2026-05-20 16:56:01 +02:00
math-pixel 09a9471814 feature gps works 2026-05-20 15:29:23 +02:00
math-pixel 6e9318457a gps component 2026-05-20 14:45:40 +02:00
math-pixel 54a353de03 first implementation of pathfinding 2026-05-20 14:34:26 +02:00
math-pixel 4faa226326 working move kikle 2026-05-19 17:10:34 +02:00
math-pixel dd66966507 working move kikle 2026-05-19 17:04:01 +02:00
math-pixel 5893afe42a working move kikle 2026-05-19 16:34:48 +02:00
math-pixel 1ead7ab3a7 working move kikle 2026-05-19 16:17:02 +02:00
math-pixel 047c58678b working move kikle 2026-05-19 16:12:58 +02:00
math-pixel ed9051b0dc working move kikle 2026-05-19 16:10:57 +02:00
math-pixel 08be6bee48 add good inclinason cam 2026-05-19 15:54:40 +02:00
math-pixel ce0eb90321 inhance move 2026-05-19 15:50:11 +02:00
math-pixel 96d7ec7fc0 move forward cam 2026-05-19 15:36:50 +02:00
math-pixel 9ab4b4a002 first move with bike 2026-05-19 15:32:59 +02:00
math-pixel d13dd0fda0 wip bike movement 2026-05-17 12:30:40 +02:00
math-pixel fbedb90bca working bike 2026-05-17 08:15:16 +02:00
math-pixel cff7744ad9 wip 2026-05-17 07:41:29 +02:00
403 changed files with 40794 additions and 81843 deletions
+29 -71
View File
@@ -1,58 +1,59 @@
name: 🔁 Branch Promotions
name: 🔁 Weekly Branch Promotions
on:
schedule:
- cron: "0 6 * * 1,4" # Lundi et Jeudi à 6h UTC (design → develop)
- cron: "0 6 * * 1" # Lundi à 6h UTC (develop → main)
- cron: "0 6 * * 1"
workflow_dispatch:
inputs:
promotion:
description: "Which promotion to run"
required: true
type: choice
options:
- design-to-develop
- develop-to-main
- both
permissions:
contents: read
pull-requests: write
concurrency:
group: branch-promotions
group: weekly-branch-promotions
cancel-in-progress: false
jobs:
design-to-develop:
name: Open design → develop
open-promotion-pr:
name: Open ${{ matrix.head }} → ${{ matrix.base }}
runs-on: ubuntu-latest
if: |
(github.event_name == 'schedule') ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.promotion == 'design-to-develop' || github.event.inputs.promotion == 'both'))
strategy:
fail-fast: false
matrix:
include:
- head: develop
base: design
title: "chore: merge develop into design"
- head: design
base: main
title: "chore: merge design into main"
steps:
- name: ⬇️ Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: 🔁 Open promotion PR
env:
GH_TOKEN: ${{ github.token }}
BASE_BRANCH: ${{ matrix.base }}
HEAD_BRANCH: ${{ matrix.head }}
PR_TITLE: ${{ matrix.title }}
run: |
set -euo pipefail
git fetch origin develop design
git fetch origin "$BASE_BRANCH" "$HEAD_BRANCH"
if git merge-base --is-ancestor origin/design origin/develop; then
echo "No promotion needed: develop already contains design."
if git merge-base --is-ancestor "origin/$HEAD_BRANCH" "origin/$BASE_BRANCH"; then
echo "No promotion needed: $BASE_BRANCH already contains $HEAD_BRANCH."
exit 0
fi
existing_pr="$(gh pr list \
--state open \
--base develop \
--head "$GITHUB_REPOSITORY_OWNER:design" \
--base "$BASE_BRANCH" \
--head "$GITHUB_REPOSITORY_OWNER:$HEAD_BRANCH" \
--json number \
--jq '.[0].number // empty')"
@@ -62,50 +63,7 @@ jobs:
fi
gh pr create \
--base develop \
--head design \
--title "chore: merge design into develop" \
--body "Automated promotion PR from \`design\` to \`develop\`."
develop-to-main:
name: Open develop → main
runs-on: ubuntu-latest
if: |
(github.event_name == 'schedule' && github.event.schedule == '0 6 * * 1') ||
(github.event_name == 'workflow_dispatch' && (github.event.inputs.promotion == 'develop-to-main' || github.event.inputs.promotion == 'both'))
steps:
- name: ⬇️ Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🔁 Open promotion PR
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
git fetch origin main develop
if git merge-base --is-ancestor origin/develop origin/main; then
echo "No promotion needed: main already contains develop."
exit 0
fi
existing_pr="$(gh pr list \
--state open \
--base main \
--head "$GITHUB_REPOSITORY_OWNER:develop" \
--json number \
--jq '.[0].number // empty')"
if [ -n "$existing_pr" ]; then
echo "Promotion PR already open: #$existing_pr."
exit 0
fi
gh pr create \
--base main \
--head develop \
--title "chore: merge develop into main" \
--body "Automated weekly promotion PR from \`develop\` to \`main\`."
--base "$BASE_BRANCH" \
--head "$HEAD_BRANCH" \
--title "$PR_TITLE" \
--body "Automated weekly promotion PR from \`$HEAD_BRANCH\` to \`$BASE_BRANCH\`."
-1
View File
@@ -143,7 +143,6 @@ WS ws://localhost:8000/ws
| `docs/technical/hand-tracking.md` | Webcam, backend/browser MediaPipe, glove, and gesture flow |
| `docs/technical/zustand.md` | Game, settings, and subtitle stores |
| `docs/technical/three-debugging.md` | DevTools workflow for stepping into Three.js internals |
| `docs/technical/map-performance.md` | Map draw-call bottlenecks and optimization notes |
| `docs/technical/editor.md` | Editor implementation details |
| `docs/technical/animation.md` | Animated, explodable, and reusable 3D model components |
| `docs/user/features.md` | Implemented feature inventory |
-266
View File
@@ -1,266 +0,0 @@
# Map Performance Notes
This document tracks the current map-rendering performance pass.
## Current Runtime Path
- `public/map.json` is the source of map transforms.
- `src/world/GameMap.tsx` renders regular visual map nodes.
- `src/world/vegetation/VegetationSystem.tsx` already instances dense vegetation.
- `src/world/map-instancing/MapInstancingSystem.tsx` instances selected repeated static map assets.
- `src/world/GameMapCollision.tsx` keeps terrain collision separate for the player octree.
## Draw-Call Bottlenecks Found
The first performance bottleneck was draw calls. Some assets were exported as many small GLTF primitives even when they used only a few materials.
| Model | Instances | Meshes / primitives | Notes |
| ---------------- | --------: | ------------------: | ---------------------------------------------------------------- |
| `generateur` | 3 | 3152 | Worst draw-call offender. Needs asset-side mesh merging. |
| `lafabrik` | 4 | 56 | Moderate draw calls, heavy 2048 texture set. |
| `ecole` | 1 | 107 | One material but many primitives; should be merged. |
| `fermeverticale` | 3 | 1 | Geometry is fine; textures are large for the visible complexity. |
`generateur` was especially expensive because three visible instances could multiply thousands of primitives into thousands of draw calls. Instancing reduces repeated instance cost, but the source asset still needs a cleaner export.
## Runtime Merge Pass
`InstancedMapAsset` now groups source meshes by material and compatible geometry attributes before creating `THREE.InstancedMesh` objects. This reduces the runtime draw groups even when the source GLTF is exported as many small meshes.
Estimated source primitive count versus runtime merged groups:
| Model | Source primitives | Runtime merged groups |
| ------------ | ----------------: | --------------------: |
| `generateur` | 3152 | 8 |
| `ecole` | 107 | 2 |
| `eolienne` | 118 | 8 |
| `lafabrik` | 56 | 14 |
This is a code-side safety net, not a replacement for clean asset exports. Clean GLB exports with merged meshes and fewer textures remain the preferred long-term path.
## Current Triangle Bottleneck
After the runtime merge pass, draw calls can drop dramatically, but FPS can still stay low because the scene now remains triangle-bound. A debug capture after the merge showed roughly:
```txt
138 draw calls
~69.6M triangles
~10 FPS
```
That means the renderer is no longer mostly blocked by draw-call submission. It is mostly drawing too many visible triangles.
Estimated triangle contribution from `map.json` instance counts:
| Model | Instances | Triangles each | Estimated total triangles |
| ------------------- | --------: | -------------: | ------------------------: |
| `buisson` | 646 | 37 500 | ~24.2M |
| `champdesoja` | 1181 | 16 268 | ~19.2M |
| `arbre` | 291 | 38 906 | ~11.3M |
| `champdeble` | 1307 | 6 260 | ~8.2M |
| `champsdetournesol` | 1163 | 3 264 | ~3.8M |
| `sapin` | 93 | 23 972 | ~2.2M |
These vegetation and crop assets account for almost all of the current `~69M` triangle count. By comparison, the previously suspicious static buildings are much smaller in triangle cost:
| Model | Estimated total triangles |
| ---------------- | ------------------------: |
| `generateur` | ~123k |
| `lafabrik` | ~124k |
| `ecole` | ~5k |
| `fermeverticale` | ~1k |
`InstancedMesh` reduces draw calls, but it does not reduce triangle count. If 646 bushes each contain 37 500 triangles, the GPU still has to draw about 24 million bush triangles when those instances are visible.
## Debug Performance Controls
The next useful runtime tool is a debug-only performance folder that can isolate model families. This should be mounted only when `?debug` is enabled.
Proposed controls:
```txt
Performance / Map
- vegetation
- crops
- trees
- buildings
- landmarks
- props
- terrain
- sky
```
Useful per-model toggles:
```txt
buisson
arbre
sapin
champdeble
champdesoja
champsdetournesol
fermeverticale
lafabrik
immeuble1
eolienne
pylone
```
The purpose is diagnostic, not final gameplay behavior. The expected workflow is:
1. Open `/?debug` with R3F perf enabled.
2. Disable one family or model type.
3. Watch `triangles`, `calls`, and FPS.
4. Identify which model groups need LOD, density reduction, or asset re-export.
Recommended implementation files:
```txt
src/managers/stores/useMapPerformanceStore.ts
src/hooks/debug/useMapPerformanceDebug.ts
src/world/vegetation/VegetationSystem.tsx
src/world/map-instancing/MapInstancingSystem.tsx
src/world/GameMap.tsx
```
The store should stay runtime/debug-only. It should not change persisted production map data.
## Triangle-Reduction Follow-Up
Once the expensive model families are isolated, the real triangle fixes are:
1. Lower-poly vegetation and crop exports.
2. LOD variants for trees, bushes, and crop fields.
3. Distance-based culling for vegetation/crop instances.
4. Chunked instancing so Three.js can frustum-cull groups instead of one huge global `InstancedMesh`.
5. Billboard/impostor versions for far vegetation.
Chunked instancing is especially important. A single `InstancedMesh` containing every bush has one global bounding sphere. If that bounding sphere is visible, Three.js may keep the whole batch visible. Splitting instances into grid chunks allows entire offscreen chunks to be skipped.
## Player-Only Vegetation Streaming
The first distance-streaming pass is intentionally limited to vegetation and crop instances:
- `arbre`
- `sapin`
- `buisson`
- `champdeble`
- `champdesoja`
- `champsdetournesol`
The behavior is configured in:
```txt
src/data/world/fogConfig.ts
```
Current runtime values:
```txt
chunkSize: 35
loadRadius: 45
unloadRadius: 45
updateInterval: 350ms
fog near: 30
fog far: 45
```
The streaming and fog are scoped to the production game scene with the player camera only:
```txt
sceneMode === "game" && cameraMode === "player"
```
This matters for debugging. In debug camera mode there is no fog and no distance streaming, so the developer can inspect the full map freely. In player mode, chunks mount and unmount around the camera to reduce visible triangle count while fog hides vegetation pop-in.
Chunk cleanup is handled through React unmounting. `VegetationSystem` removes chunks from the tree, and `InstancedVegetation` removes its `THREE.InstancedMesh` objects from the group while disposing the locally created merged geometries/material clones in its own cleanup path.
## Runtime Texture Filtering
Loaded GLTF textures are normalized in code through:
```txt
src/utils/three/optimizeGLTFScene.ts
```
The runtime pass applies conservative texture filtering:
1. Cap anisotropy to a small value.
2. Enable mipmap generation for regular PNG/JPG/WebP textures.
3. Use trilinear mipmap filtering for minification.
4. Keep existing opacity/alpha material mapping intact.
This mirrors the intent of the designer upload pipeline without rewriting model files at runtime. The sibling `upload-GLTF` project already has the stronger asset-side path: Blender GLB export with Draco, texture resizing, KTX2 generation with mipmaps, WebP fallback, and GLTF JSON URI/extension rewriting for `KHR_texture_basisu`.
Runtime texture filtering improves distant texture stability and GPU sampling behavior, but it does not reduce mesh triangle count. Triangle reduction still comes from streaming, distance unloading, or optimized source assets.
## Terrain-Snapped Map Placement
Map object heights are corrected at runtime through:
```txt
src/hooks/three/useTerrainHeight.ts
```
The terrain raycast is not done every frame. The terrain mesh list is built from the cached terrain GLTF, then each model or instance computes its snapped `y` when it is mounted or when its instance data changes.
Applied paths:
1. Regular `GameMap` model instances.
2. Generated static map models.
3. Instanced static map assets.
4. Vegetation and crop chunks.
Only the `y` coordinate is replaced. `x`, `z`, and rotation stay from `map.json`. Runtime scale is also normalized when a static map node has a non-uniform scale, which prevents exported values like `[1, 2, 1]` from stretching or shrinking a map model unexpectedly.
## Current Code-Side Optimization
Repeated static assets are configured in:
```txt
src/world/map-instancing/mapInstancingConfig.ts
```
Those names are excluded from the regular `GameMap` clone path, then rendered by `MapInstancingSystem` with merged `THREE.InstancedMesh` batches.
This keeps the existing map authoring format while reducing repeated draw calls for selected assets.
## Generated R3F Model Path
Unique static map assets can use explicit R3F components instead of the generic cloned GLTF path. This follows the same intent as `gltfjsx`: expose the model as a React component, then keep control over mesh/material setup in code.
Current generated map-model entry point:
```txt
src/world/map-generated/GeneratedMapNodeInstance.tsx
```
Current generated model component:
```txt
src/components/three/world/EcoleModel.tsx
src/components/three/world/LafabrikModel.tsx
src/components/three/world/FermeVerticaleModel.tsx
src/components/three/world/GenerateurModel.tsx
```
`ecole`, `lafabrik`, `fermeverticale`, and `generateur` use this path. Their components share the same merged static model renderer, which groups compatible geometry by material before mounting meshes.
This path should be used selectively. It improves control and can remove clone overhead, but it does not reduce source triangle count by itself.
## Asset-Side Follow-Up
Design/export should prioritize:
1. Produce lower-poly `buisson`, `arbre`, `sapin`, and crop assets.
2. Add LOD or billboard variants for far vegetation.
3. Merge `generateur` meshes from 3152 primitives to a small number of material groups.
4. Reduce `lafabrik` texture count and downscale flat/low-detail maps.
5. Merge `ecole` primitives because it uses a single material.
6. Prefer runtime `.glb` or compressed runtime textures when the pipeline supports it.
## Safety Rules
- Do not instance `terrain` for player collision without validating `Octree.fromGraphNode` support.
- Do not replace repair-game models with optimized map models unless repair node names are preserved.
- Dispose only GPU resources created locally. Do not dispose textures or geometries owned by `useGLTF`'s cache.
Binary file not shown.
+35030 -40548
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
-35051
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More