Resume
Fix architectural du systeme d’animation des vectobj pour supporter les
objets de type « diaporama » (passkey, et potentiellement d’autres) ou chaque
frame n’active qu’une seule part parmi N, donnant l’illusion d’un objet
qui change de face / d’icone en tournant.
Avant ce fix, le converter ne creait QUE les parts visibles a la frame 0,
perdant les autres parts utilisees dans les frames 1+. Le passkey (13 frames,
1 part visible/frame) n’affichait donc QUE la part 0 (le chiffre « 1 ») alors
qu’il aurait du cycler entre les 13 icones (chiffres 1-6, indicateurs de
couleur, symbole (!), rond bleu, etc.).
Cause racine
L’investigation a montre que le passkey.vec a la structure suivante :
- 13 frames, chacune avec un
onOffMaskqui n’active QU’UNE part precise - Frame 0 onOff = 0x001fe001 -> seul bit 0 ON (part 0 visible = chiffre « 1 »)
- Frame 1 onOff = 0x001fe002 -> seul bit 1 ON (part 1 visible = chiffre « 2 »)
- …
- Frame 11 onOff = 0x001fe800 -> seul bit 11 ON (part 11 = symbole
(!)) - Frame 12 onOff = 0x001ff000 -> seul bit 12 ON (part 12 = rond bleu)
(Les bits 13..20 sont du padding, ignores par l’ASM qui s’arrete au sortKey
negatif dans la liste des parts.)
L’ASM rendait l’animation correctement via la boucle putinunsorted dans
objdrawhires.s qui consomme un bit de draw_ObjectOnOff_l par part lue
dans LinesPtr (instruction lsr.l #1, d5; bcs.s .yeson).
Cote Java, le converter testait (onOffMask & (1L << pi)) != 0 UNIQUEMENT
pour la frame 0, et skippait les parts non-visibles a frame 0. D’ou la perte
des 12 autres icones.
Fix
Fichier 1 : VectObjConverter.java
- Calcul de l’union des onOff masks sur toutes les frames
(unionVisibilityMask). - Boucle sur toutes les parts dans cette union (= parts visibles dans au
moins une frame), pas seulement celles visibles a frame 0. - Pour chaque part conservee, calcul d’un
perPartVisibilityMask(bit f = 1
ssi la part est visible a la frame f). - Selection d’une frame de reference appropriee pour les positions :
frame 0 si la part y est visible, sinon premiere frame ou elle est
visible (firstSetBit). - Stockage du
perPartVisibilityMaskdans le j3o via le nouveau UserData
vectobj.visibilityMask(Integer JME, suffisant pour <= 32 frames). - Cas « vis-only » : si la visibilite varie mais que les positions sont
identiques entre frames, on duplique la pose de reference dans
framePositions[f]pour toutes les frames afin que le Control puisse
cycler la visibilite (buildSingleFramePositions). - Pre-application : si la part n’est pas visible a frame 0, on lui met
CullHint.Alwaysinitialement (le Control reactivera le bon hint a la
premiere update).
Fichier 2 : VectObjFrameAnimControl.java
- Nouveau UserData
KEY_VISIBILITY_MASK = "vectobj.visibilityMask". - Nouveau champ
long visibilityMask = -1L(= toujours visible, compat
ascendante). tryAttach()lit le mask depuis les UserData s’il est present.- Surcharge
storeFrames(geo, frames, fps, visibilityMask)qui stocke le
mask si different de -1L. - Nouvelle methode
applyVisibility(frameIdx)qui ajuste leCullHintde
la Geometry (Inherit si bit a 1, Always si bit a 0). Appelee a chaque
update viacontrolUpdateet a chaque manipulation manuelle via
applyCurrentFrameToMesh. cloneForSpatial()propage levisibilityMask.
Compatibilite
- Ascendante : les vectobj sans changement de visibilite (= la majorite,
comme glarebox, mantis, blaster) ne stockent PAS le UserData
vectobj.visibilityMask. Le Control le lit comme-1L= toujours visible
et l’applyVisibilityest un no-op. Aucune regression possible sur ces
objets. - Nouveaux vectobj diaporama : passkey est le premier identifie. Sa
geometry passe de 1 part (« 1 ») a 13 parts dont 12 sont initialement
cachees (CullHint.Always) et seulement reveillees par le Control selon
la frame courante.
Pour tester
Rebuild necessaire : ./gradlew clean buildScenes (les anciens scene_X.j3o
ne contiennent pas les parts 1-12 du passkey).
Logs attendus dans le build pour passkey :
[passkey]
... part[0] anim: 13 frames stockees (vis-only), visMask=0x1
... part[1] anim: 13 frames stockees (vis-only), visMask=0x2
...
... part[12] anim: 13 frames stockees (vis-only), visMask=0x1000
13 triangles dans 13 parts
En jeu (zone 108 de LEVEL_A) : le passkey doit maintenant cycler a 10 FPS
entre 13 icones (chiffres 1-6, couleurs, (!), rond) au lieu d’afficher
statiquement le chiffre « 1 ».