From 25ea448abe19da158b8cbbf79c88c951a70b2f09 Mon Sep 17 00:00:00 2001 From: MVA Global Fret Date: Tue, 5 May 2026 13:39:58 +0200 Subject: [PATCH] Make cargo a child of the parachute, drop the rogue strap meshes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The black rectangles the user circled in the screenshot were the strap meshes (strapH/strapV, 0.04-thick black boxes) — they were meant to wrap the cardboard box but ended up rendering as detached rectangles in some viewing angles. They're gone. Cargo positioning is now computed from the actual scaled parachute bbox: parachuteBottom = -(size.y · baseScale)/2, cargo center sits just inside that line for a slight overlap so the parachute strings visually terminate on the box top. The cargo is now a child of the parachute mesh (para.add(cargo)), so any transform applied to the parachute — scale, rotation, position — carries the box along with it. To keep the visible box size consistent regardless of the parachute's baseScale, the cargo's local position and scale are divided by baseScale. Co-Authored-By: Claude Opus 4.6 --- js/intro-scene.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/js/intro-scene.js b/js/intro-scene.js index 8991b1f..bad7acc 100644 --- a/js/intro-scene.js +++ b/js/intro-scene.js @@ -98,30 +98,31 @@ parachuteLoader.load( const baseScale = 1.6 / Math.max(size.x, size.y, size.z); para.scale.setScalar(baseScale); - /* Boîte cartonnée brune, dimensionnée pour ressembler à un colis - réaliste, attachée juste au-dessous du harnais (bottom of bbox - ≈ y -0.8 après centrage + scaling à 1.6). */ + /* Position du bas du parachute après centrage + scaling */ + const parachuteBottom = -(size.y * baseScale) / 2; + + /* Boîte cartonnée brune, attachée pile sous le harnais (top de la + boîte = bottom du parachute, donc center.y = bottom - height/2) */ + const cargoH = 0.36; const cargo = new THREE.Mesh( - new THREE.BoxGeometry(0.46, 0.36, 0.46), + new THREE.BoxGeometry(0.46, cargoH, 0.46), new THREE.MeshStandardMaterial({ color: 0xb98859, roughness: 0.85, metalness: 0.05 }) ); - cargo.position.y = -0.96; // pendu juste sous le harnais - - /* Petites « sangles » noires sur la boîte (deux fines bandes - perpendiculaires) → renforce visuellement l'idée d'attachement. */ - const strapMat = new THREE.MeshStandardMaterial({ color: 0x2a2118, roughness: 0.6 }); - const strapH = new THREE.Mesh(new THREE.BoxGeometry(0.48, 0.04, 0.48), strapMat); - strapH.position.copy(cargo.position); - const strapV = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.38, 0.48), strapMat); - strapV.position.copy(cargo.position); + cargo.position.y = parachuteBottom - cargoH / 2 + 0.05; // léger chevauchement + /* Le cargo est ENFANT du parachute para — comme ça le clone et toutes + les transformations (échelle, rotation) restent solidaires : la + boîte ne peut pas se détacher visuellement. + Pour compenser le scale du para, on inverse le baseScale sur la + position et la taille du cargo (cargo doit être dans l'espace + AVANT scaling de para). */ + cargo.position.divideScalar(baseScale); + cargo.scale.setScalar(1 / baseScale); + para.add(cargo); parcelTemplate = new THREE.Group(); parcelTemplate.add(para); - parcelTemplate.add(cargo); - parcelTemplate.add(strapH); - parcelTemplate.add(strapV); }, undefined, (err) => console.error('Failed to load parachute.glb:', err)