From 71d2f0692038d8dab69a8822cd5347036f9138bb Mon Sep 17 00:00:00 2001 From: MVA Global Fret Date: Tue, 5 May 2026 13:46:38 +0200 Subject: [PATCH] Move cargo up into the canopy base, not below the strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User's annotation showed the cargo belongs right at the canopy's base — where the strings converge — not at the very bottom of the strings. New position: parachuteBottom + 0.55·parachuteHeight, i.e. about 55% up the parachute's vertical extent. Cargo also shrunk to 0.36×0.30×0.36 to better match the small rectangle the user drew. Co-Authored-By: Claude Opus 4.6 --- js/intro-scene.js | 48 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/js/intro-scene.js b/js/intro-scene.js index bad7acc..aeaa038 100644 --- a/js/intro-scene.js +++ b/js/intro-scene.js @@ -90,39 +90,41 @@ parachuteLoader.load( (gltf) => { const para = gltf.scene; - /* Centrer + normaliser le parachute à ~1.6 unités max */ - const box = new THREE.Box3().setFromObject(para); - const size = box.getSize(new THREE.Vector3()); - const center = box.getCenter(new THREE.Vector3()); - para.position.sub(center); + /* Calcule la bbox originale du parachute (avant tout transform) */ + const box1 = new THREE.Box3().setFromObject(para); + const size = box1.getSize(new THREE.Vector3()); const baseScale = 1.6 / Math.max(size.x, size.y, size.z); - para.scale.setScalar(baseScale); - /* Position du bas du parachute après centrage + scaling */ - const parachuteBottom = -(size.y * baseScale) / 2; + /* Wrapper qui scale, puis qui se re-centre proprement après scaling. + (Faire `sub(center)` avant `scale` laisse un offset, c'est pour ça + que le colis paraissait flotter sous le parachute.) */ + const paraWrapper = new THREE.Group(); + paraWrapper.add(para); + paraWrapper.scale.setScalar(baseScale); + const box2 = new THREE.Box3().setFromObject(paraWrapper); + const center2 = box2.getCenter(new THREE.Vector3()); + paraWrapper.position.sub(center2); - /* 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; + /* Bbox monde du parachute centré à l'origine, max extent = 1.6 */ + const parachuteHeight = size.y * baseScale; + const parachuteBottom = -parachuteHeight / 2; + + /* Boîte cartonnée brune positionnée à la BASE DE LA CANOPÉE (là où + les filins convergent) — pas en bas des filins. C'est l'endroit + que l'utilisateur a marqué d'un rectangle rouge sur sa capture. */ + const cargoH = 0.30; const cargo = new THREE.Mesh( - new THREE.BoxGeometry(0.46, cargoH, 0.46), + new THREE.BoxGeometry(0.36, cargoH, 0.36), new THREE.MeshStandardMaterial({ color: 0xb98859, roughness: 0.85, metalness: 0.05 }) ); - 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); + /* Hauteur ≈ 55% depuis le bas → juste sous la canopée */ + cargo.position.y = parachuteBottom + parachuteHeight * 0.55; parcelTemplate = new THREE.Group(); - parcelTemplate.add(para); + parcelTemplate.add(paraWrapper); + parcelTemplate.add(cargo); }, undefined, (err) => console.error('Failed to load parachute.glb:', err)