Optimisation - Techniques d'animation par pixels

buzzkaido
Optimisation - Techniques d'animation par pixels

Bonjour,

Voila, j'ai construit une applet (Swing) qui affiche une animation et je me pose 2 questions paske je trouve que ca rame un peu :

**********
La premiere :
**********

Chaque image de l'animation est une image "rendue" par un petit moteur, c'est à dire que je calcule chaque pixel de l'image à partir de plein de parametres...

Donc, j'ai fait un tableau d'int : buffer[hauteur*largeur] qui contient tout les pixels de l'image.

Les pixels sont calculés dans un thread.

J'ai declaré un MemoryImageSource qui prend sa source dans le buffer.

Lors du paintComponent, je fait un bête g.drawImage(source)

Y-a-t-il mieux pour afficher à l'ecran un tableau de pixels ?
Une autre technique que le MemoryImageSource ?

**********
La seconde :
**********

Pour faire evoluer les parametres de mon animation, j'ai essayé avec un thread, qui fait une pause de 40ms entre chaque boucle, et j'ai essayé avec un timer, appelé toutes les 40ms

Donc logiquement, si j'incremente de 1 un parametre de l'animation à chaque mise à jour, je devrais avoir 25 incrementations par seconde (1000/40)

Or, des fois j'ai 15, des fois j'ai 30....

Est-ce le timer ou le thread qui n'est pas stable ?

Ou je m'y prend mal ?

(je precise que à chaque appel de la mise à jour des parametres, il n'y a que quelques additions, rien de lourd qui ferait ralentir tout ca, et c'est dans un thread separé du reste...)

Merci !

fredericmazue

Quote:

Or, des fois j'ai 15, des fois j'ai 30....

Est-ce le timer ou le thread qui n'est pas stable ?

Ou je m'y prend mal ?

Non tu ne t'y prends pas mal.
L'explication c'est qu'il n'a jamais été garanti que le timer se déclenche à intervalles précis et réguliers. L'intervalle est plus un ordre de grandeur qu'autre chose. Ca dépend de ce que le système d'exploitation a à faire.
Dans ton cas (Java) on pourrait même dire que ça dépend de deux systèmes: l'OS et la JVM. Le système déclenche le timer quand il a le temps et la JVM transmet l'événement quand elle à le temps.
Au bout du compte, ça fait comme tu le décris.

buzzkaido

Merci de la réponse !

Euh, du coup y'a-t-il une technique pour avoir des delais stables ?

Dans un thread, j'ai essaé avec sleep(), ça fait pareil....

Et pour MemoryImageSource, comment optimiser ça ?

Merci !

fredericmazue

Quote:

Euh, du coup y'a-t-il une technique pour avoir des delais stables ?

Non, pas à ma connaissance du moins.

Quote:

Et pour MemoryImageSource, comment optimiser ça ?

Je ne sais pas exactement ce que tu fais alors c'est difficile à dire.
Calculer une image pixel par pixel, c'est long évidemment. Tu t'en doutes et si tu fais comme ça c'est, je pense, parce que tu ne peux pas faire autrement.
La solution la plus simple c'est, si possible, de calculer à l'avance toutes les images et après quand tu lances l'animation tu affiche les images précalculées, une à une.

buzzkaido

Alors en fait, j'ai trouvé :

-------------------------------------------------------------------
Pour un timer stable, le plus simple et le plus efficace est :
-------------------------------------------------------------------

* utiliser un timer
* a chaque appel du timer, calculer le delai ecoulé depuis l'appel precedent grace à System.getTimeMillis() (on fait la soustraction avec l'appel precedent)
* comme ca on connait exactement le temps ecoulé depuis l'appel precedent, et on ajuste les calculs en consequence.

-----------------------------
Pour accelerer le rendu :
-----------------------------

Je ne cherchais pas a accelerer le rendu proprement dit (calcul du tableau de pixel) mais la copie de ce tableau de pixel sur l'ecran !

Le plus rapide (difference notoire sur mon PC) :

* declarer un tableau de int[largeur*hauteur] qui va stocker les pixels
* utiliser une BufferedImage monImageSource
* declarer un writableRaster avec monImageSource.getWritableRaster

Dans un thread :
* calculer chaque pixel de l'image
* ecrire dans le raster avec writableRaster.setDataElements(0,0,largeur,hauteur,tableauDePixels)

Dans le paintComponent du composant où l'on veut afficher l'image calculée :

* g.drawImage( (Image) monImageSource,x,y,null)

Bien sur, le mieux est d'utilise le modele ARGB pour la bufferedImage (1 int = Alpha + Rouge + Vert + Bleu), comme ca moins de memoire utilisé, moins de transfert de memoire aussi

Ainsi on profite des accelerations materielles de la carte video, et ca bombe !

Petite precaution : s'assurer que la bufferedImage est compatible avec la carte vidéo, histoire que Java ne perde pas du temps à convertir à chaque fois. Pour faire ca, rechercher "compatible bufferedImage"....