Quand une caisse tombe parce qu’elle doit tomber

Je vais sortir du logiciel d’entreprise parce qu’une caisse qui tombe dans Half-Life 2 me semble soudainement plus intéressante que bien des écrans de gestion. Elle ne joue pas seulement une animation : le moteur met à jour un état physique à petits pas de temps.

Un corps rigide possède au minimum une position, une orientation, une vitesse, une masse et une forme de collision. Les forces changent la vitesse; la vitesse change la position. Avec un pas dt, une intégration très simple donne :

accélération = force / masse
vitesse      = vitesse + accélération × dt
position     = position + vitesse × dt

La gravité ajoute une accélération vers le bas. Une caisse de masse double reçoit une force gravitationnelle double, donc la même accélération. Les impulsions — un choc très court — modifient directement la vitesse. La rotation demande aussi un moment d’inertie et une vitesse angulaire, mais le principe reste : conserver un état et l’avancer.

Le moteur utilise souvent un pas fixe, par exemple 1/60 seconde. Si le rendu ralentit, il peut effectuer plusieurs étapes physiques avant l’image suivante. Un dt qui varie énormément rend les ressorts et collisions instables. Trop d’étapes pour « rattraper » une machine lente peut toutefois créer une spirale où chaque image prend encore plus de retard; il faut limiter et accepter une dégradation.

La collision se fait en deux phases. La broad phase élimine rapidement les paires éloignées avec des boîtes englobantes ou une structure spatiale. La narrow phase teste les formes restantes, trouve les points de contact, la normale et la profondeur de pénétration. Des volumes simples — boîte, sphère, capsule ou enveloppe convexe — coûtent moins cher et se comportent souvent mieux qu’un modèle visuel composé de milliers de triangles.

Pour empêcher une caisse de traverser le plancher, le solveur applique des impulsions qui séparent les corps et empêchent leur vitesse relative d’aller dans le contact. Il ajoute friction et restitution pour le glissement et le rebond. Plusieurs contacts forment des contraintes couplées; le moteur les résout par itérations. Trop peu d’itérations donnent une pile molle ou tremblante, trop en coûtent du CPU.

Le déroulement d’une étape ressemble à :

  1. appliquer gravité, moteurs et forces du jeu;
  2. avancer les vitesses;
  3. trouver les paires potentielles;
  4. calculer les contacts précis;
  5. résoudre contacts, friction et articulations;
  6. avancer positions et orientations;
  7. endormir les objets presque immobiles;
  8. transmettre les transformations au rendu.

L’endormissement est essentiel : une caisse posée depuis dix secondes n’a pas besoin de recalculer chaque contact jusqu’à ce qu’une force la réveille. Le niveau de détail physique peut aussi réduire la précision des objets loin du joueur.

Les approximations produisent des bugs reconnaissables. Un petit objet très rapide peut traverser un mur entre deux pas, le tunneling. Un test de collision continue balaie son trajet au lieu de regarder seulement les positions de départ et d’arrivée. Deux formes qui commencent imbriquées peuvent exploser lorsqu’une correction trop grande s’applique. Une contrainte mal réglée peut injecter de l’énergie et faire vibrer la pile.

En réseau, simuler le même empilement exactement sur deux machines est difficile : arrondis flottants et ordre des contacts divergent. Le serveur devrait conserver l’état autoritaire des objets importants et envoyer des corrections; le client peut interpoler. Il ne faut pas accepter qu’un client annonce la position finale d’un objet lourd sans validation.

Une panne du solveur ne devrait pas contaminer toute la scène. Le moteur peut détecter une position ou une vitesse non numérique, retirer l’objet fautif, inscrire ses paramètres et continuer la partie plutôt que propager des valeurs impossibles à chaque contact.

Pour tester, je construirais une scène laboratoire : dix caisses empilées, une rampe, un objet rapide et un plancher incliné. Je mesure temps physique par étape, énergie qui devrait décroître, pénétrations et comportement à 30/60 images. Après ça seulement, j’ajoute le beau décor.

Le moteur n’a pas besoin de reproduire chaque molécule. Il doit être stable, cohérent et assez prévisible pour que le joueur apprenne ses règles. La pratique applicable est de fixer le pas, simplifier les formes et tester les cas qui injectent de l’énergie. Une caisse crédible vient moins d’une texture parfaite que d’un solveur qui sait rester calme au repos et reprendre quand on la pousse.