Aide pour After Effect, techniques, expressions.

mercredi 12 mai 2010

bientôt

Je reviens très bientôt avec 3 nouveaux articles conséquents !

jeudi 6 mai 2010

le cycle de la vie

J'aimerais bien savoir pourquoi il y a un pique de visites tous les mercredis ?
Il y a un centre aéré qui fait un atelier "AE winn3rs, pate-à-sel loos3rs ?"

mardi 27 avril 2010

modèle de début et de fin.

Bonjour à tous, ça faisait longtemps (beaucoup de boulot, et pas de cas d'expression qui vaille le coup)
J'ai eu un commentaire me demandant ceci :
"Comment faire pour caler cette animation de disparition en fonction de la fin du calque (sachant qu'ils n'ont bien sûr pas tous la même durée...)"

Alors oui, ça parait beau comme ça, et vous pensez bien que je m'étais posé la question. Mais malheureusement, c'est plus compliqué que prévu, voilà pourquoi :

Nous avons vu ici comment faire pour qu'une animation se lance quand le début d'un calque se fait sentir. C'était simple, il suffit d'utiliser un valueAtTime pour décaler le temps.

Mais si on veut gérer le début ET la fin, se pose de gros problèmes de logique.
Tout d'abord, cela veut dire qu'il faut définir qui sont les clefs de début, et qui sont les clefs de fin.
C'est une notion très arbitraire, et en rien after effect ne peut le deviner.

L'autre soucis, c'est que pour le début, il suffit de faire un décalage. Là, il faut faire ce décalage, puis arreter la lecture des clefs, puis reprendre la lecture à un moment donné (quand la fin se fait proche).

Ca complique beaucoup les choses, et c'est à se demander si l'energie de la reflexion est rentable comparer à une technique plus manuelle.

Pour un travail, j'ai du trouver une solution, car le fichier after effect était voué à être utiliser par quelqu'un qui ne connait pas du tout after effect, et donc les longueurs de composition allait être variable.
J'ai donc du chercher un moyen de lancer une animation à un moment donné, puis l'arreter, plus la relancer pour l'animation de fermeture.

Je ne donnerai aucune explication, je balance juste l'expression que j'ai utilisé dans un remappage temporel (c'est de toute façon le même principe que pour le remappage de clef).

Je n'ai pas fait le ménage, donc il y a plein de lignes ou de chiffres qui correspondent à ma situation à moi, et ne rentre en aucune façon dans la theorie.

Ce système très très cuisiné vaux le coup quand on a vraiment beaucoup de chose à automatiser...
Donc voilà, pour les plus courageux !

one=comp("prog 1_rush_vendredi").marker.key("fin").time
+
comp("prog 2_rush_vendredi").marker.key("fin").time
+
comp("prog 3_rush_vendredi").marker.key("fin").time
+
comp("prog 4_rush_vendredi").marker.key("fin").time
+
thisComp.layer("prog 1_vendredi").inPoint;


two=comp("source").marker.key("fin").time+one;

ouverture=5;
fermeture=10;
tps=time-inPoint;
x=time;

if (time>ouverture && time
if (time>=one && time
if ( time>one+2 ) { x=fermeture };
if (time>=two) { x=time-two+fermeture};

x


tout le début correspond au fait que ce calque doit démarrer apres 5 calques qui eux mêmes ont exactement la meme chose, c'est à dire un début et une fin totalement aléatoire !
Je vous avais prévenu.

lundi 15 mars 2010

random VS wiggle

J'ai eu un commentaire me demandant comment avoir un random moins violent.
J'en profite donc pour bien expliquer la différence.

Random permet d'avoir une valeur aléatoire comprise entre x et y, et ce à chaque image. La valeur prise à l'image 5 n'est ni fonction de la valeur à l'image 4, ni à la 6. C'est en ça qu'il se différencie de wiggle.
Le wiggle peut être aussi chaotique que désiré (le chanceux), il possède ce qu'on appelle une corrélation.
Prenons une image :
Prenez une feuille, et dessinez des points, où chacun a sa propre abscisse (x), et une valeur en ordonnée aléatoire (y). Vous obtenez le résultat d'un random.
Reliez tous ces points par une ligne passant par chaque point (sans revenir en arrière), et vous obtenez un wiggle.
Aussi grande que puisse être la différence entre l'ordonnée de 2 points, la valeur wiggle passera nécessairement par toutes les valeurs intermédiaires.
Le wiggle a une corrélation de 100%.
Le random à une corrélation de 0%.

Et ça n'est pas parce que vous avez une composition à 25 images/s, et que vous avez écrit wiggle(25,a) qu'il n'y a pas de lien entre les valeurs. Certes, il prendra bien une nouvelle valeur (une nouvelle crête) à chaque image, mais le lien existe bien. Entre les images, le wiggle prend bien les valeurs intermédiaires.
Il y a plusieurs façon d'en avoir la preuve :
-le motion blur
-un remappage temporel grâce à la technique que nous avons vu ici. En effet, si vous appelez la valeur d'une variable au temps 5.36s, vous aurez bien une valeur intermédiaire.

vendredi 19 février 2010

suivi d'objet

Animer un objet dans After Effect est une chose, animer une caméra en est une autre.
C'est parfois compliqué, fourbe, ingrat, ça fait pas ce qu'on veut, bref.




Nous allons en partie régler le problème pour un cas bien particulier, celui du suivi d'un objet dont le mouvement est important et plus ou moins chaotique, comme une mouche par exemple.

Nous allons essayer d'imiter le comportement d'un vrai caméraman.
Que fait le caméraman ? Il essaye tant bien que mal de suivre la trajectoire de l'objet pour le garder dans son cadre, en étant parfois en retard sur l'objet en question ou parfois un peu en avance s'il a anticipé.

Dans l'exemple, il s'agit d'un gros wiggle 3d bien large (le cercle fait 100 de large, le wiggle se déplace en tout sur 2000). Les particules sont là pour avoir un élément fixe pour que vous puissiez différencier le mouvement de la caméra et celui de l'objet.

Nous allons donc créer une expression sur le point ciblé de la caméra. La caméra en elle-même restera fixe.
Pour créer le caméraman parfait, il suffit logiquement de coller la position de l'objet au point ciblé par la caméra, et l'objet restera donc toujours au centre de l'image. Mais ça n'est pas ce que nous voulons faire.

Créez votre petite scène, et rajoutez un Null objet que nous appellerons "target cam". C'est à lui que nous allons appliquer l'expression et non à la caméra. Vous verrez un peu plus tard pourquoi.

Ajoutez 3 paramètres glissière à ce Null, et nommez les "amplitude", "tendance" et decalage".

amplitude définira le nombre d'images maximum de décalage dans le temps. (mettez 20 par exemple)
tendance nous permettra de définir si la camera sera plus souvent en retard ou en avance. (mettez -1 pour le moment)
decalage contiendra la valeur de décalage temporel à chaque image.

Écrivons l'expression dans "decalage" :

amp=effect("amplitude")("Curseur");
tendance=effect("tendance")("Curseur");

Expliquons un peut le processus avant de se lancer dans l'écriture de l'expression.
"decalage" va contenir un wiggle qui va faire varier le décalage temporel, selon l'amplitude.
Pour le moment, si on écrit juste "wiggle(0.2,amp), on va avoir une valeur qui va varier de -20 à 20, c'est à dire que la caméra sera (statistiquement parlant) autant en retard qu'en avance.
Nous allons donc utiliser la valeur "tendance" pour faire varier ça.
Ca va pas mal ressembler à la façon dont on a gérer le néon.
Quand tendance=1, la caméra sera toujours en avance.
Quand tendance=-1, la caméra sera toujours en retard.

si on le traduit pour le wiggle, ça donne ça :
tendance=-1 : le wiggle ira de -20 à 0 (avec un milieu à 10 donc)
tendance=0 : le wiggle ira de -20 à 20 (avec un milieu à 0 donc)
tendance=1 : le wiggle ira de 0 à 20 (avec un milieu à -10 donc)

Ecrivons donc cette amplitude qui peut aller de 20 à 40 selon les cas :


ampF=linear(Math.abs(tendance),0,1,amp,amp/2);

Voilà, on a bien ce qu'on voulait.
Maintenant, on doit créer la valeur final en décalant le centre du wiggle entre -10 et 10:

W=tendance*(amp/2)+wiggle(.2,ampF);

Ainsi, on transforme tendance pour qu'il varie de -10 à 10.
La dernière ligne, on transforme le nombre d'image en seconde :

d=thisComp.frameDuration*W;

Voilà, on a créé notre décalage en seconde.
Maintenant, écrivons l'expression pour la position de ce même calque (on est toujours dans "target cam" je vous rappelle):
p=thisComp.layer("target").transform.position;
d=effect("decalage")("Curseur");
p.valueAtTime(time+d);

J'explique même pas, vous connaissez par cœur tout ça. Juste une petite précision quand même.
Là j'ai écrit
time+d car c'est la valeur de tendance (de -1 à 1) qui va définir le retard ou l'avance.
-1, et le calque sera toujours en retard. 1, et le calque sera toujours en avance. Vous pouvez aussi mettre -10 ou 456, ça ne change rien, la fonction linear écrête les résultats.

Bref, on a bien notre calque "target cam" qui suit la même trajectoire que la cible, parfois en avance, parfois en retard (ça dépend de la valeur de tendance).

Occupons de la caméra à présent.
Nous allons comprendre pourquoi nous n'avons pas écrit cette expression directement dans la caméra.
Certes notre caméraman va être en avance ou en retard, mais il paraît fortement improbable que sa caméra suive exactement le trajet de l'objet.
Nous allons donc utiliser une fonction pour altérer cette trajectoire, et plus exactement, l'adoucir.

Nous allons utiliser la fonction smooth(a,b).
a est la durée sur laquelle un adoucissement va être effectué. Plus la durée sera longue, plus les creux et les bosses seront mélangés.
b Correspond à la puissance du smooth. Gardez comme règle de toujours utiliser une valeur impaire (C'est comme ça, discutez pas).

Sauf qu'il y a un petit problème...
On pourrait se dire qu'écrire ceci fonctionnerait :

P=thisComp.layer("target cam").transform.position;
P.smooth(1,5)

Et bien non, ça ne marchera pas !
Je vous explique pourquoi.
Les expressions dans After Effect ont leurs limites, et notamment une très importante:
Elles n'ont aucune mémoire. Vous ne pouvez pas enregistrer dans la mémoire d'AE une valeur qu'on va venir chercher à chaque image, ou bien faire que cette valeur augmente de n à chaque image (il y a en fait une technique pour faire ça, mais c'est un systeme D où AE recalcule tout depuis le début à chaque image).
Le problème est que se le smooth va faire une moyenne des valeurs, par exemple sur 1 seconde, il va aller voir les valeurs sur 1/2 seconde avant, et 1/2 seconde après. Sauf que voilà, il ne peut pas connaître les valeurs du futur puisqu'elles n'ont pas encore été calculée.

Nous devons donc passer par une étape supplémentaire.
Ecrivons donc juste ceci :
P=thisComp.layer("target cam").transform.position;

La caméra a donc exactement le même mouvement que "target cam"
A présent, en ayant la variable "point ciblé" sélectionnée, allez dans Animation, assistant d'image clé, convertir l'expression en image clés.

After va créer une clef par image calculées par l'expression, et désactiver cette dernière.

A présent, effacez l'expression et remplacez là par

smooth(1,5)

Et voilà !
Donc à chaque fois que vous faite une modification dans l'objet "target cam", vous devez reconnecter la caméra en remettant :
P=thisComp.layer("target cam").transform.position;

Refaire le coup de "Animation machin bidule), et remettre smooth(a,b).

Ne vous plaignez pas, ça prend 5 secondes.

Voilà c'est fini, vous avez votre belle caméra qui fait un beau mouvement.
Encore une article bien long, mais au final, il y a très peu de ligne à écrire.



Ce système est largement améliorable.
Par exemple, on peut imaginer que le caméraman dézoome quand la cible est trop loin de sa caméra.
Autre finesse, si l'objet se déplace essentiellement horizontalement, on voudra gérer de manière séparer X et Y.

Peut être pour un prochain article.

précision sur le néon

Certains se sont peut être demandé pourquoi j'ai créé un interrupteur qui va de 0 à 1 si c'est pour derrière l'utiliser uniquement en le transformant de 0,25 à 0,75.

C'est certes arbitraire, mais il y a plusieurs raisons:

Tout d'abord, une raison "logique". Étant donné qu'il s'agit d'un interrupteur, il est légitime qu'il aille de 0 à 1.
Ensuite, nous pourrions imaginer que cet interrupteur va agir sur d'autres éléments de l'animation, pour que ces derniers soient synchrones avec l'allumage du néon. Des valeurs allant de 0,25 à 0,75 seraient donc inappropriées d'un point de vue démocratique.

Enfin, et de manière plus générale, c'est un bon réflexe de créer ou de transformer les variables de 0 à 1 dans le cas où elles servent de potentiomètre ou d'échelle.
Nous avons déjà vu cela à plusieurs reprises:
Quand nous voulions avoir plusieurs calques qui se positionnent entre 2 calques et créent une chaine, nous avons utilisé leur index pour créer une variable allant de 0 à 1, et multiplier cette valeur par le vecteur allant d'un bout à l'autre pour les positionner. Plus génériquement, cela permet d'aller de 0 à la valeur finale d'une variable.

Les exemples sont nombreux, et souvent édifiants, car mathématiquement, c'est pratique :

-Pour la trigonométrie, on reste dans les valeurs du cosinus et du sinus.
-pour les vecteurs, on reste également à l'intérieur du vecteur sans le dépasser ni partir dans l'autre sens.
-Cela nous permet également de monter cette valeur à la puissance X, tout en restant entre 0 et 1, et ça, c'est extrêmement pratique.
Nous l'avons déjà vu par exemple pour l'amélioration des flares ou des lumières volumétriques. Au lieu d'avoir une droite qui va de 0 à 1, une courbe qui reste plus longtemps autour de 0 (avec une puissance supérieure à 1), ou au contraire on peut avoir une courbe qui va plus vite vers 1 (avec une puissance comprise entre 0 et 1 (non inclus). Pour rappel, la racine carrée correspond à une puissance de 0,5)

Nous verrons d'autres applications de l'utilisation de ce type de courbe pour casser la linéarité d'une valeur allant de 0 à 1.

jeudi 18 février 2010

animation modèle

Aujourd'hui, un petit truc tout simple, mais dont vous ne pourrez pas vous passer tant il peut vous faire gagner un temps précieux.




Imaginez que vous ayez créé une animation d'apparition pour un calque, qui mélange opacité, échelle, rotation, etc.
Vous êtes très content de votre mixture, ça fonctionne bien.
Sauf que cette apparition de luxe doit vous servir à faire apparaître 50 calques.
Alors oui, vous pourriez copier/coller toutes les clefs de chaque variable sur chaque calque, en faisant attention que les clefs soient bien synchro avec le début de chaque calque....
Et si vous changez votre animation, il faut tout refaire.
Bref, c'est tout pourri.

Nous allons donc dire à chaque calque de copier un calque modèle, chacun quand il le désire.

Imaginons comme dans l'exemple que vous ayez des clefs d'échelle et de rotation.
Ouvrez ces 2 propriétés dans votre 2ème calque, et écrivez ceci pour l'échelle par exemple :

target=thisComp.layer("modele");
e=target.scale;
e.valueAtTime(time-inPoint+target.inPoint)

C'est tout. Pas grand chose à expliquer.
Le valueAtTime nous permet donc de corriger le tir, et de faire en sorte que l'animation commence au bon moment, c'est à dire quand le calque apparait dans la composition.
Le +target.inPoint corrige également le tir si le calque modèle ne commence pas au début de la composition.

Il vous suffit de faire une expression équivalente pour chaque variable qui en a besoin, et tout sera automatisé.