# Morphosynthèse 1.0 — Cyclonium

Dessiner un volume. Explorer ses coupes. Écouter ses formes.
Version du 12 octobre 2026. JavaScript sans framework ni dépendance externe.

## Démarrer

Ouvrir la page autonome `morphosynthese.1.html`, ou servir le dossier dist :

    python -m http.server 8000 --directory dist

Puis ouvrir http://localhost:8000/. L’audio temps réel utilise AudioWorklet et
nécessite un contexte sécurisé (HTTPS ou localhost) et un navigateur compatible.
Le rendu 3D nécessite WebGL. L’export WAV utilise le même lecteur en calcul local.

- Glisser dans la scène : rotation du volume avec inertie.
- Molette, pincement à deux doigts ou curseur Profondeur : translation en Z.
- Flèches : rotation ; PageUp / PageDown : profondeur.
- Arrêter le mouvement : annule les vitesses, sans couper le son.
- Recentrer : restaure la pose initiale, sans modifier la forme.
- Dessiner : tracer une silhouette simple ; les extrémités sont reliées.
- Tous les curseurs affinent le réglage en s’éloignant verticalement. Maj ajoute
  un facteur 1/10. Les champs numériques permettent la saisie directe.

L’amortissement de l’inertie est exponentiel ; nul, il conserve la rotation et
la vitesse en profondeur. La translation s’arrête aux limites du domaine.
La caméra et le plan de lecture z=0 restent fixes. Le volume est translucide ;
les contours sont dessinés par-dessus pour rester lisibles. La transparence
est un rendu illustratif à deux passes, pas une simulation de transmission.

## Géométrie

Le principe gestuel s’inspire de Teddy (Igarashi, Matsuoka, Tanaka, SIGGRAPH 1999),
mais ceci n’est pas une réimplémentation de son squelette chordal et de ses arcs.

La silhouette est recentrée et ramenée à une étendue maximale de 1.8 unité.
Sa taille de dessin est conservée par un facteur de taille séparé, réglable.
Une distance signée d(x,y), positive à l’intérieur, définit :

    F(x,y,z) = d(x,y) - z² / épaisseur²

La surface F=0 forme deux nappes jointes sur le contour. L’épaisseur locale
vaut épaisseur * sqrt(d). Ce choix simple arrondit le bord et produit des
formes plus épaisses dans leurs régions larges. Ce n’est pas une pression
physique. Le maillage est extrait par tétraèdres sur une grille de 28 cellules
par axe, avec partage des sommets aux intersections d’arêtes.

Le programme vérifie : une seule composante, deux faces par arête et
caractéristique d’Euler égale à 2. Les croisements francs du dessin sont refusés.
La grille peut perdre des détails trop fins : les volumes séparés ou pincés
par cette discrétisation sont refusés, avec conservation de la dernière forme
valide. Le premier modeleur est limité à une silhouette simple sans trou ;
ce n’est pas une restriction destinée au futur moteur générique de Cyclonium.

La pose est une rotation par quaternion, une taille uniforme et une translation
Z. La coupe est calculée sur le maillage transformé. Les segments sont raccordés
par leurs identifiants d’arêtes, pas par un seuil de proximité arbitraire.
Au passage exact d’un sommet, un très petit décalage symbolique de classification
évite les graphes ambigus. Les fragments non fermés et contours dégénérés ne
sont pas lus. Les tangences sont ainsi régularisées à l’échelle numérique.

## Trajectoires et son

Chaque boucle est rééchantillonnée en 512 points uniformes en longueur d’arc.
Sa taille n’est pas normalisée. X alimente le canal gauche, Y le canal droit.
L’option de centrage soustrait la moyenne de chaque coordonnée pour enlever
la composante continue. Elle ne change pas l’amplitude géométrique.

Deux lois de parcours :
- fréquence de parcours imposée, indépendante du nombre de sommets ;
- vitesse constante, fréquence de parcours = vitesse / longueur de boucle.

Le son n’est pas la vibration physique du volume : c’est une lecture cyclique
de ses contours. La fréquence de parcours ne garantit pas une hauteur perçue
identique. La lecture à vitesse constante est plafonnée à 0.4 fois la fréquence
d’échantillonnage pour les boucles très petites ; cela ne constitue pas un
filtrage anti-repliement. Les tables sont interpolées linéairement et les
harmoniques élevées peuvent se replier. Le moteur est expérimental.

Les voix suivent les boucles par proximité du centre et longueur. Une recherche
de décalage cyclique aligne les tables successives. La phase est conservée
quand une identité est retenue ; les nouvelles formes se fondent sur 25 ms.
Apparitions et disparitions sont également fondues. Lors d’une fusion ou d’une
séparation, cette correspondance est une convention approchée, non une solution
unique. En lecture multiple, les voix sont moyennées : chaque boucle conserve
sa taille, mais le mélange ne grandit pas sans limite avec leur nombre.

Le lecteur sonore fonctionne dans AudioWorklet, indépendamment du dessin de
la scène. Les mobiles visibles parcourent les mêmes tables avec un facteur
commun D de ralentissement ; leur phase visuelle est indépendante de l’audio.
D n’altère pas le son. Arrêter le volume laisse les mobiles et le son continuer.

## Produits et formats

- Instrument JSON `cyclonium.morphosynthese`, version 1 : silhouette, méthode
  de construction, paramètres, pose initiale et pose actuelle, inertie au moment
  de la sauvegarde, contours sélectionnés et provenance. Le rechargement
  restaure volontairement la pose immobile ; il ne relance pas le son seul.
- Contours JSON `cyclonium.contours`, version 1 : toutes les boucles, leur domaine,
  longueurs et coordonnées. Les valeurs exportées correspondent aux tables de
  lecture en flottants 32 bits, pas à un encodage d’image limité à 16 bits.
- OBJ : maillage du volume dans sa pose actuelle, unités du modèle.
- WAV : coupe figée au moment de l’export, stéréo 48 kHz, IEEE float 32 bits,
  quatre secondes. Gain d’écoute et fondus appliqués ; recette dans LIST/INFO/ICMT.
- PNG : image de la scène ; conserver le JSON à côté pour retrouver la recette.

Le format d’instrument est propre à cette première expérience. Les ateliers
anciens ne savent pas encore le charger automatiquement. Le module ci-dessous
permet déjà de lire les contours exportés sans le modeleur ni WebGL.

## Réemploi du lecteur

    import { createInstrumentVoice } from './trajectory-voice.mjs';
    const instrument = JSON.parse(texte);
    const voice = createInstrumentVoice(instrument, { sampleRate: 48000 });
    const pair = [0, 0];
    for (let i = 0; i < gauche.length; i++) {
        voice.next(pair);
        gauche[i] = 0.15 * pair[0];
        droite[i] = 0.15 * pair[1];
    }

`configure({ frequency: 220 })` modifie la fréquence sans réinitialiser la phase.
`update(tables)` est l’interface dynamique, pour des tables déjà validées.
La classe MorphVoice et la fabrique createInstrumentVoice sont exportées.
Un module supplémentaire devra transformer ce contrat en instrument commun
avec les autres ateliers : aucune compatibilité automatique n’est revendiquée.

## Sources et vérification

- geometry.js : gonflement, coupe, quaternions et rééchantillonnage.
- renderer.js : rendu WebGL.
- voice-core.js / trajectory-voice.mjs : même lecteur, versions classique et ES.
- app.js, style.css, index.html : interface et orchestration.
- build.py : génération de la page autonome, du module et du ZIP.
- test-geometry.cjs : tests géométriques et sonores (`node test-geometry.cjs`).

Tests : fermeture et topologie du maillage ; coupe circulaire, coupe vide,
coupes sous 35 orientations ; arche à deux boucles ; refus d’un contour croisé ;
fréquence de lecture, continuité de phase et extinction des voix ; lecteur externe.
Le rendu, les gestes tactiles et l’audio en navigateur n’ont pas pu être vérifiés
ici lors de la livraison. Aucune dépendance navigateur n’a été installée pour
contourner cette limite de vérification.
