Make cargo a child of the parachute, drop the rogue strap meshes

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 <noreply@anthropic.com>
This commit is contained in:
MVA Global Fret 2026-05-05 13:39:58 +02:00
parent 6b0f8d9afb
commit 25ea448abe

View File

@ -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)