Move cargo up into the canopy base, not below the strings

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 <noreply@anthropic.com>
This commit is contained in:
MVA Global Fret 2026-05-05 13:46:38 +02:00
parent 25ea448abe
commit 71d2f06920

View File

@ -90,39 +90,41 @@ parachuteLoader.load(
(gltf) => { (gltf) => {
const para = gltf.scene; const para = gltf.scene;
/* Centrer + normaliser le parachute à ~1.6 unités max */ /* Calcule la bbox originale du parachute (avant tout transform) */
const box = new THREE.Box3().setFromObject(para); const box1 = new THREE.Box3().setFromObject(para);
const size = box.getSize(new THREE.Vector3()); const size = box1.getSize(new THREE.Vector3());
const center = box.getCenter(new THREE.Vector3());
para.position.sub(center);
const baseScale = 1.6 / Math.max(size.x, size.y, size.z); 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 */ /* Wrapper qui scale, puis qui se re-centre proprement après scaling.
const parachuteBottom = -(size.y * baseScale) / 2; (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 /* Bbox monde du parachute centré à l'origine, max extent = 1.6 */
boîte = bottom du parachute, donc center.y = bottom - height/2) */ const parachuteHeight = size.y * baseScale;
const cargoH = 0.36; 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( const cargo = new THREE.Mesh(
new THREE.BoxGeometry(0.46, cargoH, 0.46), new THREE.BoxGeometry(0.36, cargoH, 0.36),
new THREE.MeshStandardMaterial({ new THREE.MeshStandardMaterial({
color: 0xb98859, roughness: 0.85, metalness: 0.05 color: 0xb98859, roughness: 0.85, metalness: 0.05
}) })
); );
cargo.position.y = parachuteBottom - cargoH / 2 + 0.05; // léger chevauchement /* Hauteur ≈ 55% depuis le bas → juste sous la canopée */
/* Le cargo est ENFANT du parachute para comme ça le clone et toutes cargo.position.y = parachuteBottom + parachuteHeight * 0.55;
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 = new THREE.Group();
parcelTemplate.add(para); parcelTemplate.add(paraWrapper);
parcelTemplate.add(cargo);
}, },
undefined, undefined,
(err) => console.error('Failed to load parachute.glb:', err) (err) => console.error('Failed to load parachute.glb:', err)