Des surfaces qui n'existent nulle part dans le code
Un blob de metaballs n'est dessiné par personne : aucune forme, aucun cercle, aucun chemin n'est stocké quelque part. Je place seulement quelques boules invisibles qui se déplacent et rebondissent sur les bords. Ce qui apparaît à l'écran — ces gouttes ambre et indigo qui se rejoignent puis se séparent — est une surface implicite : elle est définie par une équation, pas par une géométrie, et je la reconstruis intégralement à chaque image.
Un champ scalaire, somme de contributions
Chaque boule émet un champ d'influence qui décroît avec la distance. En tout
point de l'écran, j'additionne la contribution de toutes les boules selon une loi
en inverse du carré de la distance (r² / d²) : très fort près d'un
centre, faible au loin. Cette somme forme un champ scalaire continu — un
relief invisible dont les sommets sont les boules et dont les vallées se comblent
là où deux boules se rapprochent. C'est cette addition, et rien d'autre, qui fait
fusionner les blobs de façon organique.
Le seuillage définit la surface
Reste à décider où se trouve la « peau » du blob. Je fixe un seuil : tout point où le champ dépasse cette valeur est à l'intérieur, tout point en dessous est à l'extérieur. La surface, c'est exactement la ligne de niveau où le champ vaut ce seuil — l'iso-surface. Quand deux boules s'approchent, leurs champs s'additionnent dans l'espace entre elles, la zone franchit le seuil, et les deux gouttes n'en forment plus qu'une. J'utilise ici deux seuils : un bas pour le halo indigo, un plus haut pour le cœur ambre, ce qui donne aux blobs leur relief.
Marching squares : extraire le contour, cellule par cellule
Évaluer le champ en chaque pixel puis en tracer la frontière serait ruineux. À la place, j'échantillonne le champ sur une grille régulière et j'applique l'algorithme du marching squares. Pour chaque petite cellule, je regarde lesquels de ses quatre coins sont au-dessus du seuil ; sur chaque arête qui relie un coin « dedans » à un coin « dehors », j'interpole linéairement le point de passage exact. Je remplis alors le polygone formé de ces coins et de ces points d'intersection. Mises bout à bout, ces cellules reconstituent un contour lisse — l'interpolation gomme l'effet d'escalier de la grille.
Le vrai sujet : le compromis résolution / performance
Toute la démo tient dans un arbitrage. Une grille fine suit la surface au plus près mais multiplie les points à évaluer à chaque image ; une grille grossière est quasi gratuite mais laisse voir ses facettes. Ici je travaille sur une grille au pas de dix pixels et je laisse l'interpolation faire le reste : le champ n'est calculé que sur quelques milliers de points au lieu de plusieurs centaines de milliers de pixels, et l'animation tient soixante images par seconde jusque sur mobile. C'est exactement le type de décision que j'apporte à un projet : trouver, chiffres en main, le point où la qualité perçue et le coût réel s'équilibrent, pour livrer une application à la fois fluide et tenable dans la durée.