Aide pour After Effect, techniques, expressions.

mardi 30 décembre 2008

chacun son référentiel

Avant de voir la trigonométrie, on va voir quelque chose d'autre avant, rapidement, le changement de référentiel. Ça à l'air horrible comme ça comme phrase, mais en fait, c'est bien, et dans certains cas, on ne peut pas faire sans.
Et quand on peut pas faire ça, bah faut faire avec.
Ça sera pour la fin de semaine, l'année prochaine donc (ça s'est pour pour préparer aux gens qui vont vous dire "hey à l'année prochaine !" demain soir...

mercredi 10 décembre 2008

bientot dans vos salles

Je reviens bientot pour expliquer comment la trigonométrie c'est trop bien.

Et si vous êtes sages, quand vous aurez bien tout appris votre trigo de la classe de 4eme (et un peu aussi de la 2nd je crois...), on verra ensemble comment remédier à un petit manque dans after effect, la gestion de la cinématique inverse ! (je bouge la main, le bras et l'avant bras suivent)

Mais avant, va falloir piger un certain nombre de choses...

jeudi 13 mars 2008

EXPRESSIONS : gestion d'une couleur

Parfois, on peut avoir une composition avec plusieurs calques texte ayant la même couleur.
Si on veut changer la couleur des textes, à priori, il faut modifier la couleur dans chaque calque texte, surtout si les calques sont éparpillés sur la pile des calques de la timeline (empêchant l'utilisation d'un calque de réglage pour modifier l'ensemble des calques textes).

Il existe plusieurs solutions, en voici une très simple utilisant les expressions.
Créez un calque null, avec un effet "paramètre couleur", dans le même menu que le paramètre glissière.
Ouvrez le menu du texte dans la timeline, cliquez sur "animer", et créer un mini menu en cliquant sur "fond du tracé", "RVB". Ainsi, vous pouvez changer la couleur de votre texte de la timeline, et non plus uniquement du panneau "caractère".

Ensuite, il ne vous reste plus qu'à créer une expression pour la couleur en l'accrochant à la couleur de l'effet "paramètre couleur" du Null, et de faire ça avec chaque calque.














Voilà, vous pouvez contrôler la couleur de plusieurs calques avec un seul.

dimanche 9 mars 2008

EXPRESSIONS: selection de calque

Un petit post qui vous donnera un outil puissant dans AE. Une nouvelle façon de selectionner un calque dans une expression.
Pour le moment, nous n'avons vu qu'une seule façon:

thisComp.layer("target").blablabla

On demandait à AE d'aller voir dans cette même composition un calque nommé "target".
Il y a une autre façon de cibler un calque:
"Va cherche la position du calque qui est juste au dessus de moi s'il te plait."

Oui oui, c'est possible, voilà comment:

thisComp.layer(thisLayer, -1)

On demande donc à AE de cibler le calque qui a un index inférieur d'un point à celui dans laquelle est écrite l'expression.

thisComp.layer(thisLayer, +2), et là c'est le calque qui est en dessous de 2 niveaux.

Le chiffre peut également être une variable comme nous le verrons plus tard.
Quel intérêt à tout ça?
L'intérêt est énorme en terme d'automatisation, nous l'utiliserons très souvent, et voilà pourquoi:


Prenons l'exemple tout frais du reflet. Imaginez que vous avez (et ce sera surement le cas) plusieurs calques dont vous voulez le reflet dans le sol. Vous allez donc créer un clone de chaque calque.
Logiquement, vous copiez l'expression de position du votre premier reflet dans la position d'un autre futur reflet. Et pouf, ça ne marche pas comme vous voudriez. Pourquoi ? Car l'expression originale cible le calque "premier mot" alors que ce deuxième reflet devrait faire appel au calque "deuxième mot".
Et là, vous vous rendez compte que vous allez devoir changer plus ou moins à la main toutes les variables "calque machin" pour chaque expression et chaque reflet... Insupportable si tout cela concerne 50 calques.

C'est là que notre nouveau joujou intervient.
Plutôt que d'écrire:
P=thisComp.layer("calque 1").position;

on va donc écrire:
P=thisComp.layer(thisLayer,-1);

Et pareil pour toutes les variables faisant appel au calque reflété. La condition est évidemment de mettre le reflet juste en dessous de son modèle. il ira toujours chercher les variables dans le calque au dessus de lui.

Ainsi, si chacun de vos reflets est en dessous de son modèle, vous pourrez copier/coller toutes les expressions que vous voulez, chaque reflet se comportera parfaitement.

Encore un pas vers l'automatisation!

mercredi 5 mars 2008

EXPRESSIONS: les reflets

Un peu de concret ce coup-ci, la gestion des reflets dans AE. Il s'agit évidemment d'une suite d'astuces, étant donné que les réflections dans AE ne sont pas gérées.

Le sujet est déjà traité ici et là sur internet, mais nous allons intégrer les expressions pour automatiser le tout.

Commençons avec une scène simple, un sol bien grand, et un mot, les deux en 3d.
Evidemment, le sol est horizontal, le mot est vertical.











Déjà, voyons comment créer un reflet. L'astuce est simple, on duplique le calque. Pour qu'il soit un reflet, il faut qu'on le mette en "miroir". Pour cela, plusieurs possibilités. Nous allons en choisir une et s'y tenir, car la suite sera en fonction de ce choix.

On peut par exemple inverser l'échelle sur Y (en décochant l'échelle uniforme), ou bien mettre 180 dans l orientation sur x (et non la rotation). Optons pour l'échelle sur Y à -100. Ensuite, on recoche "échelle uniforme"

Faites descendre votre reflet plus bas, et là, hop, il disparait sous le sol. Logique, puisque sa position sur Y devient plus basse que le sol. Pour régler ce premier problème, une astuce existe.
Créez une calque d'effet juste au dessus du sol. Ainsi, meme si un calque passe sous le sol, il restera entierement visible du moment qu'il reste au dessus du sol dans la pile des calques.

Ca, c'est fait.
Maintenant, automatisons le tout. Nous voulons deja que le reflet s'éloigne du sol vers le bas d'autant que la distance entre le sol et le mot.
On doit donc creer une variable qui définit la distance L entre le sol et le mot, et demander à ce que le reflet ait une position en Y telle que sol+L (et non sol-L, car Y augmente vers le bas):

sol=comp("Composition 1").layer("sol").transform.position[1]; // hauteur du sol
P=thisComp.layer("mot").transform.position; // position du texte
distance=Math.abs(sol-P[1])
// distance entre le sol et le texte

x=P[0]; // meme position sur x que le texte

y=sol+distance;

z=P[2]; // meme position sur la profondeur que le texte
[x , y , z ]


Je ne m'étends pas 4h sur ces quelques lignes simplissimes:
sol est la position du sol sur Y, P la position du mot.
Le reflet doit avoir la meme position que le mot sur X.
Pour la distance, on soustrait la position du sol au mot, ou l'inverse, qu'importe puisqu'on utilise Math.abs qui en ressort la valeur absolue, c'est à dire positive.
Et oui, souvenez vous,
Math.abs(5)=5
Math.abs(-5)=5

Donc Math.abs(10-3) = Math.abs(3-10)=7

Donc, Y=sol+distance

Et pour Z, c'est la meme chose que pour X, mais dans l'autre dimension (la profondeur)

voilà pour la position.
Au final, le reflet devrait suivre le modèle sur x et z, y devant etre inversé puisqu'il correspond à la distance objet-sol

Faites bouger votre mot dans sur les 3 axes, le reflet se comporte parfaitement.

Passons aux rotations.
C'est ici que le choix de la solution miroir influence la suite. On a ici opté pour l'échelle de -100 sur Y.

on a donc ceci:

pour la rotation sur X:
thisComp.layer("mot").transform.xRotation*-1

pour la rotation sur Y:
thisComp.layer("mot").transform.yRotation

pour la rotation sur Z:
thisComp.layer("mot").transform.zRotation*-1

En fait, il n'y a que 2 possibilités. Ou l'angle est le meme, ou bien c'est l'angle inverse ( *-1). Donc si vous optez pour un miroir avec l'orientation sur x de -180, ça sera l'inverse de tout ça.
De toute façon, il suffit de tester, et on se rend vite compte si c'est bon ou pas.

Si on veut aussi automatiser l'échelle, c'est tres simple, surtout avec le miroir fait avec -180 dans l'orientation sur x, il suffit de copier l'échelle du modèle.

Pour le cas où le miroir fait avec l'échelle de -100 sur Y, on écrira ceci:

s=thisComp.layer("mot").transform.scale;
[s[0] , s[1]*-1, s[2] ]

On inverse donc juste Y.

Voilà, toutes les transformations sont faites. Occupons nous de la transparence.











Le reflet doit évidemment etre moins dense que le modèle.
On veut faire en sorte que plus le modèle est loin du sol, plus le reflet est transparent. Nous allons donc utiliser la fonction linear. Bravo à ceux qui ont deviné.

imaginons qu'on veuille que l'opacité aille de 0 à 50:

sol=comp("Composition 1").layer("sol").transform.position[1]; // hauteur du sol
P=thisComp.layer("mot").transform.position; // position du texte
t=transform.opacity; //valeur de l'opacité
distance=Math.abs(sol-P[1]); // distance entre le sol et le texte
linear(distance, 10 , 60 ,t, 0 )

Voilà, c'est pas bien compliqué. Juste une petite précision pour l'utilisation de l'opacité du calque.
Certains pourraient se dire ceci: comment est il possible de creer la variable
t=transform.opacity alors que c'est cette meme variable que toute l'expression modifie ?

C'est tres simple, souvenez vous, AE lit d'abord la valeur, puis l'expression, et utilise la valeur créée par l'expression. De la meme maniere, on peut creer dans la position une expression du type position + [3,5] . Vous pourrez bouger votre calque; une fois votre calque placé, AE rajouter 3 et 5 à la position.

Pour en revenir à nos moutons, il ne vous reste donc plus qu'à entrer 50 dans l'opacité du reflet. Ainsi, 50 sera l'opacité maximum utilisée, jusqu'à ce que le mot soit à plus de 10 pixels du sol. Les valeurs de 10,60,50 et 0 sont ici arbitraire, vous mettez ce que vous voulez selon votre scène.

Affinons le tout avec un flou dans le reflet. Plus le mot est loin du sol, plus le reflet est flou, à la façon d'un sol légèrement dépoli. C'est exactement le meme principe que pour l'opacité. On rajoute un flou gaussien, ou directionnel au reflet et dans le rayon:
sol=comp("Composition 1").layer("sol").transform.position[1]; // hauteur du sol
P=thisComp.layer("mot").transform.position; // position du texte
distance=Math.abs(sol-P[1]); // distance entre le sol et le texte
ease(distance, 10 , 60 , 2 , 20 )














Sans commentaire.

Voilà un exemple simple. Ca a été un peu long, mais quand on regarde le tout, c'est en fait très rapide à mettre en oeuvre.
Si vous avez plusieurs objet à refléter dans votre scène, n'oubliez pas de creer une variable générale pour l'opacité et le flou des réflections, avec par exemple un Null et 4 paramètres glissière du type:

Opmin
Opmax
Floumin
Floumax

et de les intégrer dans vos expressions, ainsi, vous pourrez tout gérer en meme temps, sans avoir à revenir dans chaque calque en cas de modification. On peut aussi rajouter des paramètres de distance du modèle au sol, etc.

voilà voilà, bonne réflection.

vendredi 25 janvier 2008

PARTICULAR : anti-clone

Petite astuce avec Particular, le plugin de Trapcode largement utilisé comme simulateur de particules pour AE.

Particular propose en interne une petite liste de type de particules, comme smoke, sphere, star... Et vous permet également d'utiliser un de vos calques comme particule.

Voilà comment demander à particular d'utiliser plusieurs calques différents, en en choisissant un au hasard à la création de chaque nouvelle particule.

Créez une composition, pas trop grande sinon votre machine va gueuler (200x200 c'est deja pas mal), et placez à la chaine tous les calques que vous voulez utiliser dans particular. Chaque calque ne doit durer qu'une seule image, la composition doit donc durer le temps d'affichage de chaque image (si vous avez 10 calques, votre compo doit avoir une durée de 10 images, et donc finir par 00:09 car 00:00 existe oui oui)

Placez cette compo au début de la compo contenant le calque particular (et masquez la bien évidemment). Comme type de particule, mettez "custom", choisissez la compo créée, et dans "time sampling", utilisez "random - still frame".
Ainsi, particular choisira à chaque fois une image différente, et s'y tiendra pour chaque particule.
Pratique pour avoir des particules toutes différentes, ou bien une légère différence entre chacune pour éviter l'effet clone.

Allez, faites tomber de jolies feuilles mortes de toutes les formes de la vie, faites voler les bonbons...

mercredi 23 janvier 2008

EXPRESSSIONS : Math

j'y viens au fur et à mesure, pas trop vite non plus, mais je vais être obligé d'intégrer au fur et à mesure quelques notions de mathématiques, promis, des simples.

Ici, je vais détailler les différentes façon d'altérer un chiffre avec les fonctions Math.

Il y e en a presque 25, nous allons voir les principales ensemble. J'y consacre un post entier plutot que de faire de longues parenthèses lors des prochains posts où ces fonctions seront très souvent utilisées.

La synthaxe est toujours la meme, à savoir : Math.truc (x)
truc n'a pas de majuscule puisqu'un point le précède.
---------------------------------------------------------------------------
Math.abs (x): donne la valeur absolue du nombre, c'est à dire sa valeur positive.
exemple:
Math.abs (5) = 5
Math.abs (-6) = 6

Imaginons une variable X qui aille de 20 à -10. Math.abs(X) partira à 20, s'arretera à 0, et repartira vers 10.
---------------------------------------------------------------------------
Math.floor (x): donnc la valeur entière inférieure au nombre.
exemple:
Math.floor (5.35) = 5
Math.floor (0.95)= 0

Math.ceil (x): donne la valeur entière supérieure au nombre.
exemple:
Math.ceil (5.35) = 6
Math.ceil (0.95)= 1

Math.round (x): donne la valeur entière la plus proche du nombre
exemple:
Math.round (5.35) = 5
Math.round (0.95)= 1
Math.round (0.5)=1

Ces trois fonctions sont souvent utilisées pour avoir des nombres qui augmentent comme un escalier par exemple.
Math.flour (time) prendra succéssivement les valeurs 0 1 2 3 4 uniquement à chaque nouvelle seconde.

Dans la timeline, à coté du dieze des expressions, il y a un petit graphique. Activez le pour observer ce que crée l'expressions en terme de courbe (quand vous l'activez également dans la timeline en général)
---------------------------------------------------------------------------

Math.min (x,y): donne la plus petite valeur entre x et y. Evidemment, ça ne sert que lorsque x et/ou y varie(nt).

Math.max(x,y): donne la plus grande valeur entre x et y.

par exemple, Math.min(5,time) vaudra de 0 à 5 entre le début de la compo et la 5eme seconde, puis sera toujours égale à 5 ensuite, étant donné que time vaudra plus que 5.

Ces deux fonctions permettent donc de mettre un plancher ou un plafond à une valeur, c'est très utile.

Math.min ( 5 , time ) et Math.min ( time , 5 ) sont strictement identiques.

---------------------------------------------------------------------------

Math.PI : lui ne modifie pas une valeur, mais contient la valeur de PI ( 3.14machin )

---------------------------------------------------------------------------

Math.pow (x,y): crée la valeur x puissance y.
exemples:
Math.pow(5 , 2)=25
Math.pow(2 , time ) augmente à une vitesse considérable !

---------------------------------------------------------------------------

Math.exp (x): donne l'exponentiel du nombre. En gros, cela donne une valeur qui augmente très vite en démarrant lentement (un peu à la manière d'une valeur au carré).
exemples:
Math.exp (.5)=2
Math.exp (3)=20
Math.exp (40)=326901

Si si, on s'en sert très souvent, par exemple :
Math.min ( Math.exp ( time ) , 5 ) n'ira pas plus haut que 5.

A noter que pour un soucis de clareté, si on a pas créé de variable pour Math.exp(time) genre :
x=Math.exp(time);
Math.min ( x , 5)

On peut aussi écrire ceci:
Math.min (
Math.exp ( time )
,
5 )


Ainsi, chaque élément est sur ligne différente, beaucoup plus lisible.

---------------------------------------------------------------------------

Il en existe d'autre, nous les verrons plus tard.

Je ferai surtout un chapitre bien à part en ce qui concerne:

Math.cos
Math.sin
Math.tan
Math.acos
Math.asin
Math.atan
Math.atan2

Et oui, vous n'allez pas échapper à la trigonométrie, mais quand vous aurez vu ce que l'on peut en faire, vous vous demanderez comment vous avez pu animer quoi que ce soit sans ces outils.

EXPRESSIONS : spot + diapo

Une utilisation concrète des vecteurs.

AE permet la création d' éclairage 3d. Ici, nous allons utiliser le spot 3d, à la façon d'une lampe torche. Nous allons d'ailleurs simuler le dessin lumineux créé par une vraie lampe torche. En effet, le spot n'est pas uniforme, mais hétérogène, à cause des miroirs.














Voilà l'image que j'ai créé sous photoshop pour l'effet.

Et voilà ce que nous cherchons à faire:












Ici, le cône de lumière a été rajouté par le plugin Lux, et n'est ici que pour une meilleure lecture de l'image.

On voit clairement que la lumière projète l'image.
Installons la scène.

Créez 2 solides 3d que vous mettrez perpendiculaire, et un petit solide 3d, devant, en hauteur (ici en jaune).

Créez un spot (ctrl alt shift L), "concentré" en français, avec un cone d'environ 50 degrés.
Faites en sorte que le spot éclaire les 3 solides, activez les ombres en reception et emission, et activez aussi les ombres pour la lumière. Le petit solide jaune crée donc une ombre sur les deux autres.











Rajoutez votre image de lampe torche. Le but est le suivant, placer cette image devant la spot, puis qu'elle reste toujours devant le spot, et orientée sur l'axe du spot, pour éviter toute déformation.
Nous allons utiliser les outils que nous avons deja utilisé, rien de bien nouveau.

Mettez votre image de lampe torche (ILT) en mode 3d.

Créez une expression pour sa position :

a=thisComp.layer("Lumière 1").transform.position;
b=thisComp.layer("Lumière 1").transform.pointOfInterest;

On a donc crée deux variables, la position de la source du spot, et la position du point ciblé par le spot.

V=sub(b,a);

On crée le vecteur correspondant.
Voilà la dernière ligne:

a+normalize(V)*50

que je me dois d'expliquer :

On cherche à ce que ILT soit toujours entre la source du spot et le point ciblé.
Tout comme dans le post précédent, on aurait pu écrire ceci:

a+V*0.2

Ainsi, ILT aurait été à 20% de la distance totale entre la source et la cible. Mais ça fonctionnerait mal, car dès que l'on animerait la source ou la cible, la distance entre les deux changerait, la position d'ILT changerait donc aussi par rapport à la source.

Imaginons que la distance entre la source et la cible soit de 1000 pixels.
Avec
a+V*0.2, ILT serait à 200 pixels de la source. Si 1000 se transforme en 1500, l ILT serait plus éloigné de la source, et donc l'ombre créée serait plus grande.

Nous voulons donc que la distance entre la source du spot et l'ILT soit fixe, qu'importe les animations futures. D'où la ligne
a+normalize(V)*50.

Quel est ce normalize(V) ?
C'est une fonction qui transforme un vecteur lamba en un vecteur de distance 1. On garde ainsi l'angle du vecteur, mais ça distance devient donc l'unité. Il suffit donc de multiplier cette valeur par ce que l'on veut, ici 50, et l'ILT sera donc toujours à 50 pixels de la source.

Il faut à présent orienter le calque ILT.
Créez une expression pour son orientation:

a=thisComp.layer("Lumière 1").transform.position;
b=thisComp.layer("Lumière 1").transform.pointOfInterest;
lookAt(a,b);

C'est exactement la meme chose que ce que nous avons vu précédemment. Ajuster les rotations XYZ si besoin est.


Il ne reste plus qu' à modifier un parametre 3d de l ILT, dans les options de surface. Mettez la transmission de lumière à 100%, pour que le calque agisse comme une diapositive (il faut biensur que ILT émette une ombre) .

Ajustez l'échelle du calque pour que sa taille et la taille du cone du spot coïncide. Et voilà.

Cette technique à quelques limites:

Cela interdit l'utilisation des ombres douces, puisque cela rendrait flou la diapositive.
L'autre soucis est que le calque de diapositive est forcément visible s'il entre dans le champs de la composition.

On peut évidemment projeter ce que l'on veut ainsi.

mardi 22 janvier 2008

EXPRESSIONS : les vecteurs

Les vecteurs...

Bouh le vilain mot de mathématiques!
Oui, tout le monde s'en souvient, on a tous eu ça en cours. Nous allons ici en avoir une utilisation extremement simpliste.

Petit rappel, un vecteur, c'est comme une flèche: c'est une direction + une distance.
Exemple : 30 degrés, + 20 pixels. Voilà, c'est pas plus compliqué que ça.

Passons au concret. Crées 2 calques bleu de 50x50, et un troisième, rouge, plus petit. Placez les 2 bleus où voulez dans la compo, plutot en diagonal, et placez le rouge à coté de celui du bas.









Ouvrez la position des 3 solides, et créez une expression pour la position du petit.

a=thisComp.layer("Bleu roi uni 6").transform.position;
b=thisComp.layer("Bleu roi uni 7").transform.position,

Le grand classique, on crée une variable pour chaque position des deux autres solides.
Puis, on rajoute ceci:

V=sub(a,b);

Alors, qu'est ce que c'est... Cette fois ci, V ne sera pas égal à un chiffre, mais sera un vecteur. Il va donc stocker dans sa mémoire un angle, et une distance, en pixel.
Sans rentrer dans les détails, retenez ceci:

sub(A,B) crée un vecteur allant de B à A (et non de A à B).

Finissez l'expression en écrivant ceci:

b+V

On demande donc que le carré rouge ait la position de B, plus le vecteur V. Observez sa position, il est donc logiquement à la meme position que A. C'est logique, si on part de B et qu'on rajoute le chemin pour aller de B à A, on arrive sur A.

Remplacez b+V par position+V , et décalez le carré rouge sur le coté.

A présent, faites bouger le carré A ou B, le carré rouge bouge en meme temps, puisque le fait de bouger A ou B modifie le vecteur V, et donc modifie la position du carré rouge.

Rajoutez un paramètre glissiere au carré rouge, appelez le "coeff", et ecrivez cette expression :

a=thisComp.layer("a").transform.position;
b=thisComp.layer("b").transform.position,

C=effect("coeff")("Curseur");

V=sub(a,b);

b+V*C

Faites variez le paramètre glissière entre 0 et 1. Le carré rouge se déplace entre A et B. Et oui, on peut multiplier ou diviser le vecteur pour faire évoluer la distance, pratique. Une valeur négative fera partir le vecteur dans l'autre sens, une valeur supérieure à 1 fera aller le carré rouge au dela du segment AB.











Ici, j'ai animé la coeff avec un wiggle qui fait vibrer la valeur entre 0 et 1, et j'ai animé les deux carrés bleu.

Une fonction très utile, qui permet beaucoup de chose, nous en verrons un exemple dans le prochain post.

EXPRESSIONS : linear

linear.

Cette fonction crée une variable en fonction d'une autre.
Par exemple, on veut que lorsque X varie de 0 à 50 alors Y varie de 6 à 2. Cela peut servir à plusieurs choses:
-quand la position sur Z d'un calque 3d varie, l'opacité du meme calque varie.
-plus un calque est transparent, plus il est flou.
etc.

Voilà la synthaxe:

Y=linear ( X , a , b , A , B )

Il y a beaucoup de chiffres, mais rien de compliqué :
X est la valeur qui varie.
a et b sont les valeurs entre lesquelles X varie.
A et B sont les valeurs entre lesquelles Y varie.

exemple :

X=time;
Y=linear (X , 0 , 50 , 6 , 2 )

je mets volontairement des espaces autour de chaque chiffre et virgule, car on a vite une ligne riche en information. Quand on écrira des lignes du type
linear (x,incr-1,incr*(index+2),math.abs(math.sin(time*360)),100)

L'exemple est extrème, mais il montre bien que se faire une ligne lisible est important pour modifier quoi que ce soit par la suite, ou meme eviter d'oublier une virgule ou une parenthèse.

Lorsque X vaut 0, Y vaut 6 et quand X vaut 50, Y vaut 2. Quand X prend les valeurs intermédiaire, Y prend ses propres valeurs intermédiaire. Par exemple, quand X vaut 25, Y vaut 4.
Que se passe-t-il quand X vaut plus de 50 ? Et bien Y est "bloqué" à 2. Et quand V vaut moins de 0, Y est "bloqué" à 6.

a,b, A et B peuvent évidemment aussi etre des variables comme nous le verrons plus tard.

L'utilisation de linear est tres large, on s'en sert dans de nombreux cas.
linear peut etre remplacé par un autre mot : ease.
La synthaxe est la meme, mais l'effet diffère très légèrement:
Avec ease, la valeur Y aura une accélération au début et une décélération à la fin, à la façon d'une clef "lissage de vitesse", "ease" en anglais.
easeIn permet une accélération au début, et une fin linéaire.
easeOut permet une décélération à la fin, et un début linéaire.

























J'appliquerai cette fonction très souvent, vous en découvrirez donc plein d'utilités.

EXPRESSIONS : moyenne

Ici, pas de nouvelle fonction, juste un tout petit calcul de rien du tout.
Nous cherchons à ce qu'un objet soit toujours entre deux autres, plus précisement au milieu de ces derniers.











Rien de plus simple, certains s'en souviennent peut etre, ils sagit de la somme des postions des deux objets, divisée par 2.

Créez 2 solides bleus et un solide rouge. Ouvrez les positions des 3, et créez une expression pour le rouge.

a=thisComp.layer("Bleu roi uni 3").transform.position;
b=thisComp.layer("Bleu roi uni 2").transform.position;

(a+b)/2

Voilà, meme pas la peine d'expliquer les 3 lignes, ça tombe sous le sens, et ça s'écrit en 5 sec.

Nous pouvons également rajouter un lookAt, pour que le carré rouge soit toujours dans l'axe des deux autres. Passez le calque en 3d, créez une expression pour son orientation, et recopiez les deux 1ere ligne de l'expression de position:

a=thisComp.layer("Bleu roi uni 3").transform.position;
b=thisComp.layer("Bleu roi uni 2").transform.position;

et rajoutez

lookAt ( a , b )

Vous aurez surement à reajuster la rotation Y de 90 degrés, et voilà.



EXPRESSIONS : lookAt

LookAt, ça va être simple à expliquer:












Cette fonction simplissime sert à donc à ce qu'un objet soit aligné avec un ou deux objets. Très pratique. Voilà comment on s'en sert.
Tout d'abord, votre calque doit être un calque 3d, car l'expression est faite pour "orientation" et non la rotation.
Créez deux calques, l'un carré l'autre en forme de barre, passez la barre en mode 3d, ouvrez son orientation, et écrivez ceci:

lookAt (

Comme d'habitude, le deuxieme mot des fonctions commence par une majuscule. La synthaxe est la suivante : lookAt ( A, B ) , ou A et B sont les positions respectives de deux objets. Si l'une des deux positions est celle de l'objet "barre", alors l'objet tournera sur son axe. Si les deux positions sont celles de deux autres objets, la barre s'orientera sur l'axe parallele à l'axe des deux objets.

Reprenons notre expressions
lookAt ( . Placez le curseur apres la parenthese, prenez la corde, attachez la à la position de l autre objet, mettez une virgule, et écrivez position.

On se retrouve donc avec quelque chose qui ressemble à ça:

lookAt( thisComp.layer("Rouge uni 2").transform.position , position )

C'est finalement très simple, il suffit juste de donner les deux positions qu'on souhaite pointer. Il ne vous reste plus qu'à modifier le point d'ancrage de la barre si besoin est. Sur mon exemple, le point d'ancrage est à l'extrémité de l'objet et non en son centre comme initialement.

A noter que l'objet s'alignera, mais pas forcément dans l'axe que vous désiriez. Pour réajuster l'axe, utilisez les rotations X Y Z. (qui sont tjs animables si besoin est).

Il peut arriver qu'on ne veuille pas que le calque soit en 3d. Par exemple, si une camera est présente dans votre scene, le passage en 3d du calque change sa position dans la composition.
Nous verrons plus tard comment orienter un objet sans qu'il soit en 3d, c'est un peu plus compliqué.

samedi 19 janvier 2008

EXPRESSIONS : les mouches

Première application concrète des expressions dans AE ! (ici en tout cas).
Car oui, le but des expressions n'est pas juste de faire joujou avec les chiffres, mais bien de les intégrer dans vos animations.

voilà ce que nous allons faire:












Oui, ce post est long, mais ça n'est pas parce qu'il est compliqué.
Je ne vais pas balancer les lignes magiques directement, mais plutot expliquer la démarche qui consiste à partir d'une volonté d'animation, et trouver le meilleur moyen de la gerer dans AE.

Créez tout d'abord votre cible, que vous appelerez d'ailleurs "cible".
Créez une mouche (un petit solide) qui vous appelerez "mouche01".

Réfléchissons à ce que nous voulons faire. Nous voulons qu'un essaim de mouche suive un objet, avec donc un mouvement général de l'essaim (large), plus un mouvement propre à chaque mouche(frénétique). Chaque mouche suit l'objet avec plus ou moins de retard.

Créez tout d'abord un null objet (ctrl alt shift Y), qui va nous permettre de stocker toutes les valeurs que l'on veut faire varier. Nous voulons que les mouches aient un retard compris entre 5 images et 30 images sur l'objet cible.

Créez donc deux paramètres glissière au null, appelez la 1ere "max" et la 2eme "min"; dans "min", tapez donc 5, et 30 dans "max".

Chaque mouche aura également sa propre frénésie. La frénésie sera bien évidemment un futur wiggle. Nous ne ferons varier que l'amplitude pour la raison suivante: Nous voulons qu'il y ait des mouches plus ou moins frénétiques. Donc si nous faisons varier uniquement l'amplitude avec une fréquence fixe, chaque mouche va faire varier sa position avec la meme fréquence, donc plus l'amplitude sera forte, plus la mouche sera frénétique. C'est suffisant pour visualiser des mouches toutes différentes.

Créez donc deux autres parametres glissiere sur le null, un "amp max" et un "amp min".
amp max =60 , amp min = 10

Voilà pour les variables de réglage.

Ouvrez la position de la mouche, et c'est parti pour la création des variables:
(comme vous pouvez le voir, " //" permet de rajouter du texte dans les expressions qui ne sera pas lu par AE, pratique pour rajouter des annotations personnelles.

p=thisComp.layer("cible").transform.position; // position de la cible
min=thisComp.frameDuration*thisComp.layer("Nul 1").effect("min")("Curseur");
max=thisComp.frameDuration*thisComp.layer("Nul 1").effect("max")("Curseur");
amin=thisComp.layer("Nul 1").effect("amp min")("Curseur");
amax=thisComp.layer("Nul 1").effect("amp max")("Curseur");


Pour min et max, nous avons multiplié la valeur de la variable du null par la durée d'une image dans la composition (
thisComp.frameDuration). min vaut 5 et max vaut 30. Donc le retard sera compris entre 5 images et 30 images.

Si nous avions juste écrit ceci:

min=thisComp.layer("Nul 1").effect("min")("Curseur");
max=thisComp.layer("Nul 1").effect("max")("Curseur");

le retard aurait été compris entre 5 et 30 secondes comme nous le verrons apres.

Ca, c'est fait.
Nous voulons donc que chaque mouche ait sont propre retard.
Définissons ce retard:

seedRandom(index,true); //
permet donc d'avoir par la suite une valeur au hasard fixe. R=random(min,max); // crée donc une variable R égale à une valeur fixe au hasard entre min et max, 5 et 30 images donc pour nous. Si votre compo est à 25 im/s, R varie donc entre 5*(1/25) et 30*(1/25), donc entre 0.2 sec et 1.2 sec.

Maintenant, la frénésie propre à chaque mouche:

A=random(amin,amax); //crée une variable A égale à une valeur fixe au hasard entre amin et amax, donc entre 10 et 60 (le seedRandom est toujours actif)
w=wiggle(5,A);// notre wiggle sera différent pour chaque mouche, entre (5,10) et (5,60)

Récapitulons, pour le moment nous avons ceci:

p=thisComp.layer("cible").transform.position;
min=thisComp.frameDuration*thisComp.layer("Nul 1").effect("min")("Curseur");
max=thisComp.frameDuration*thisComp.layer("Nul 1").effect("max")("Curseur");
amin=thisComp.layer("Nul 1").effect("amp min")("Curseur");
amax=thisComp.layer("Nul 1").effect("amp max")("Curseur");

seedRandom(index,true);

R=random(min,max);

A=random(amin,amax);

w=wiggle(5,A);

Rien de bien particulier, nous avons créé 5 variables: la position de la cible, et 4 variables venant des paramètres glissière du null.
Ensuite, R définie le retard en seconde, A la frénésie de la mouche.

Passons à la dernière ligne, celle qui va définir la position avec toutes ces variables. Soyons méthodiques :

p.valueAtTime(time-R)

voilà le début de la ligne. On demande donc que la mouche ait la meme position que la cible, avec un retard dans le temps vallant R. Rappelez vous, time est en seconde, donc il faut que R soit également en seconde pour une bonne compréhension de la ligne. Voilà pourquoi nous avons créé des variables min et max avec thisComp.frameduration*5 et *30. Nous aurions aussi pu avec des valeurs comme min=0.1 et max =1.2 pour avoir directement des valeurs en seconde. Ici, c'est un choix personnel qui nous permet de connaitre tres precisement le retard en nombre d'images. en général, la fréquence étant 25images/sec, il est facile de calculer ce que l'on veut.

Animez votre cible, et dupliquez plusieurs fois votre mouche. Deja, les mouches suivent avec plus ou moins de retard la cible.










Effacez toutes les mouches, sauf une. Réouvrez sa position, et reprenons la suite de

p.valueAtTime(time-R)

Rajoutons la frénésie:

p.valueAtTime(time-R)+W

Et là, vous observez un petit souci, la mouche se décale dans l'espace. Et oui, souvenez vous, le wiggle a cette particularité qu'il contient déja la position de l'objet, pour des raisons très logique que j'ai déja expliqué. Donc nous devons écrire ceci:

p.valueAtTime(time-R)+W - position

L'effet est le suivant: on rajoute la frénésie du wiggle, mais en enlevant la position contenu en lui en la retirant derriere (position faisant évidemment référence à la position de l'objet).

Redupliquez votre mouche plusieurs fois, animez. hop, ça marche pas trop mal tout ça, chaque mouche a son propre retard et sa propre frénésie. Tout ceci est largement suffisant pour observer des mouches qui ont toutes un comportement tres différent.

Rajoutons le mouvement général de l'essaim. Pour ceci, ouvrez la position du null qui contient toutes les variables, et écrivez ceci:

wiggle(.5,20)

c'est à dire un leger mouvement tres lent ( 0.5 est une fréquence très lente). Ensuite, placez le null à la position [0,0]. Ainsi, sa position va varier entre [-10,10] et [10,10]

Effacez toutes les mouches sauf une, et ajoutez à la dernière ligne ceci:

p.valueAtTime(time-R)+W + thisComp.layer("Nul 1").transform.position

Ainsi, toutes les mouches auront en plus de leur frénésie un mouvement commun, celui du null. Sinon nous n'avions pas replacer le null sur [0,0], le null serait resté au milieu de la composition avec une position du type [200,200] + son wiggle, les mouches auraient donc récupéré toute cette postion en plus.
A noter également qu'au début de l'expression on aurait pu créer une variable :

P=
thisComp.layer("Nul 1").transform.position;

Et ensuite rajoutez ceci à la fin:

p.valueAtTime(time-R)+W+P-position

Et voilà, dupliquez votre mouche une dizaine de fois par exemple, activez le motion blur pour tout le monde et activez le aussi dans la composition (le mouvement des mouches sera moins saccadé en raison de leur rapidité) et lancez l'animation.

Au final, il ne suffira que de modifier l'animation de la cible, et /ou des 4 variables, et toute l'animation suivra.

Avec un peu d'habitude, cette expression ne prendra pas plus d'une minute à mettre en place, pour ensuite avoir un outil d'animation pratique et rapide à modifier. Impossible d'étre aussi maleable et reactif avec des clefs.

Cette animation simpliste est une base qui peut etre affinée à volonté, en voici quelques exemples:

Puisque les mouches vont vers la cible, il peut également etre interessant de jouer sur la distance qui les sépare grace à la fonction "length".
Par ex, plus les mouches sont proches de la cible, plus la cible devient rouge et tremble.

On peut aussi rajouter un leger wiggle tres lent sur leur échelle, pour simuler un déplacement sur l'axe de la profondeur.

Evidemment, tous mes exemples se font avec des carrés, il va de soi que l'uilisation de "vrais" calques changent tout.

voilà voilà.

vendredi 11 janvier 2008

EXPRESSIONS : valueAtTime

ValueAtTime.

Derrière ce nouveau barbarisme se cache encore une fois un nouvel ami pour vous. Et encore une fois, impossible de le remplacer correctement avec les clefs.
Sa fonction est très simple; tout comme son nom l'indique, ValueAtTime permet de creer une variable qui a la meme valeur qu'une autre, mais à un moment différent.

Imaginons ceci: deux solides, avec l'un des deux qui a comme position celle de l'autre solide. Animez ce dernier, l'autre calque se déplace aux memes endroits, au meme moment. Les deux calques seront logiquement superposés.

A présent, effaçons la ligne dans l'expression de position, et écrivons ceci:

p=thisComp.layer("Rouge uni 1").transform.position; (mon "rouge uni 1" ne regarde évidemment que moi ici)
p.valueAtTime(time-1);

Animez le premier solide (l'autre donc) sur plusieurs seconde, et lancez l'animation: le second solide fait exactement la meme chose que son voisin, mais avec une seconde de retard.










C'est finalement assez simple, mais décortiquons quand meme tout ça.
La 1ere ligne ne fait peur à personne, on demande à ce que p soit égale à la position [x,y] de l'autre calque.
Si l'on écrivait p à la ligne suivante, nous aurions deux solides qui feraient exactement la meme chose. Mais p.valueAtTime(time-1); demande à ce que la position de ce calque soit égale à p non pas à l'instant présent, mais à time - 1 c'est à dire à une seconde de retard, time ayant la seconde comme unité. Par exemple, à la seconde 3, AE ira cherche la position que le calque avait à la seconde 2. time - .5 creera un retard d'une demi-seconde, time+3 creera une anticipation de 3 seconde, bouleversant ainsi la causalité universelle.
Comme vous vous en doutez, on peut également avoir time - x, où x varie. On peut également écrire valueAtTime(x) , nous verrons des cas où cela peut etre utile.

Encore une fois, faites bien attention à ce que vous écrivez, et rappelez vous de cette règle:

Pour toutes les fonctions composées de plusieurs mots, tous les mots sont attachés, et chaque nouveau mot commence par une majuscule, sauf pour le 1er mot. valueAtTime. Si vous faites la moindre faute à ce niveau, AE ne reconnaitra pas le mot.

Nous allons à présent creer une expression avec non pas une mais DEUX fonctions. Oui oui, vous allez voir. Nous allons donc utiliser la fonction valueAtTime, et index.

Souvenez vous, index crée une valeur qui correspond à la position du calque dans la timeline.

Créez un solide rouge de 30 par 30, et nommez le "chef".
Créez un solide bleu (ou autre, je m'en fous) de 15 par 15, et nommez le "mouton01", et plaçez le au dessus de chef.
Ouvrons sa position, p= , et hop la corde:
p=thisComp.layer("chef").transform.position;
dec=thisComp.frameDuration;
p.valueAtTime(time - dec*index)

Alors alors, qu'a-t-on fait... La 1ere ligne, facile. Ensuite, nous avons demandé que dec soit égal à la durée d'une image. Et oui, c'est le rôle de
thisComp.frameDuration. Voyons ce doux mot composé. thisComp fait évidemment référence à un paramètre de la composition. Il y en a évidemment plusieurs : sa largeur, sa hauteur, son nombre d'image à la seconde... C'est cette dernière qui nous interesse ici. La durée d'une image. Si votre composition est à 25 image/sec, vous auriez pu écrire dec=1/25.

Notez également le " . " entre chaque mot. le " . " est présent dans tous les mots composés, c'est une sorte de séparateur de hierarchie, tout comme dans p.valueAtTime : on fait les choses dans l'ordre. D'abord on parle de p, ensuite on dit que l'on veut la valeur à un temps différent.
C'est pareil ici: on parle de la composition, et on en demande un sous-paramètre.

Bref, nous avons à présent une variable qui égale au temps d'une image, en seconde. Si votre composition est à 25 images/seconde, votre dec vaut donc 0.04.

p.valueAtTime(time - dec*index)
Ici, on peut facilement déduire ce qu'il se passe. On demande à mouton qu'il suive chef avec un retard dans le temps égale à dec*index, soit ici 0.04 sec puisque son index vaut 1 (c'est pour cela que nous l'avons placé au dessus de chef tout à l heure).

A présent, dupliquez le calque mouton ( crtl D ou pomme D) plusieurs fois.
Lancez l'animation, miracle, les moutons se suivent à la queue leu-leu, avec un décalage d'une image entre chacun. C'est tout à fait logique, le second calque accuse un retard de 0.08 étant donné que son index vaut 2, etc.










Ce retard d'une image est trop faible, augmentons le proprement.
Effacez tous les moutons sauf un. Qu'importe lequel, puisqu'il sont tous des copies conformes.
Nous allons creer une variable qui determinera le retard de chaque calque.

Selectionnez le calque chef, et rajoutez lui le filtre "parametre glissière", dans "option pour expression" dans "filtre". Nommez cette glissière "coeff". Donnez la valeur de 10 à la glissière.
Revenez à votre mouton, et rajoutez cette ligne:
R=thisComp.layer("chef").effect("coeff")("Curseur"); grace à la code bien entendu, sauf pour les inconditionnels du clavier.
Nous allons donc à présent rajouter cette variable à la dernière ligne:
p.valueAtTime(time - dec*index*R)
A present, le retard sera donc égal à une image, multiplié par la position du calque dans la timeline, multiplié par notre coefficient. Ici nous avons 10, donc chaque mouton aura un retard de 10 images par rapport au mouton précédent.










Nous aurions aussi pu taper ceci:
p.valueAtTime(time - dec*index*10)
Le résultat aurait été le meme, sauf qu'ici, si on veut changer la valeur de retard, il faut le faire sur tous les moutons, un par un... Imaginez vouloir changer le retard sur 200 moutons, impossible.
C'est ici un point extrèmement important :
Prévoir les valeurs qu'on voudra peut etre faire varier et régler dans le futur, et creer les variables en conséquence, indépendantes des calques concernés. Aidez vous, ne vous tirez pas une balle dans le pied. C'est également pour cela que nous avons creer la glissère "coeff" sur le chef, et non sur le mouton. Si le "coeff" etait sur le mouton, chaque mouton serait allé chercher son propre coeff, et la glissièere aurait donc été parfaitement inutile. Oui, certains me diront qu'écrire *10 prend une demi-seconde, creer une filtre glissère, creer la variable et taper *R prend 10 sec... Certes, mais vous gagnerez non seulement un grand nombre d'heures, mais votre travail sera meilleur: Plus un réglage est accessible et rapide, plus vous vous permetterez d'affiner votre travail.


Voilà pour valueAtTime, c'est une fonction très important, et infaisable avec des clefs (amusez vous à copier des clefs et les déplacer dans le temps, c'est vite lassant, et surtout, c'est n'importe quoi).
Bien évidemment, et comme d'habitude, cette fonction peut s'appliquer à n'importe quelle valeur dans AE, nous la retrouverons extremement souvent, et notamment dans le prochain post, qui sera ENFIN le premier exemple concret de l'utilisation des expressions.

à vos solides.

vendredi 4 janvier 2008

EXPRESSIONS : random

RANDOM. En anglais, cela signifie hasard. Cette fonction va nous permettre de creer un ou plusieurs chiffres complètement au hasard. Plongeons nous dans le concret:

On crée une composition de 600 x 400, on fait un solide de 50 x 50, on ouvre sa position, et ecrit ça:
X=random ( 0 , 600 );
Y=random ( 0 , 400 );
[ X , Y ]

Lançons l'animation; a chaque image le calque se place à une position différente.
X=random ( 0 , 600 ); cette ligne demande donc à ce que X varie entre 0 et 600.

Voilà les autres possibilités:
random ( [0,0,0 ] , [0,3,5 ] ) : cela va donc creer une variable à 3 dimensions fluctuant entre les deux valeurs. A noter que lorsqu'une des "extrémités" est égale à 0, on peut ne pas la noter:
random ( [0,3,5] ) correspond à la meme ligne que la précédente.

random ( ) : la valeur fluctue de 0 à 1.

Un point important: dupliquez ce calque, et lancez l'animation. Le clone n'a pas la meme position que l'original:
random creer une valeur différente pour chaque calque.

A présent, imaginons qu'on veuille une valeur au hasard, mais fixe; on ne veut pas que la valeur change à chaque image. Nous devons rajouter une ligne:

seedRandom ( 5,true );

Oula, qu'est ce que c'est que ce truc immonde qui ressemble à de la programmation !!!
On se calme, et on regarde. La fonction seedRandom est à intégrer avant la fonction random, car c'est elle qui demande à ce que le random soit fixe ou pas.

( 5 , true ) :
le chiffre 5 a été bien evidemment choisi au hasard ici. Imaginez que la fonction random possède une liste infinie de suites de chiffres. Le chiffre 5 appel donc la liste numero 5.
En gros, ça veut dire que si vous remplacez 5 par 8, la fonction random crachera d'autres chiffres aux hasard. Remettez 5, vous retrouvez les memes chiffres qu'auparavant.
true : il demande à ce que la prochaine ligne "random" soit une valeur fixe.

donc si vous écrivez ceci:
seedRandom ( 5,true );
X=random (0,600);
Y=random (0,400);
[X,Y]

Notre calque prend bien une position au hasard, mais s'y tient. Dupliquez le calque, la copie est ailleurs.

Dans le cas d'un random non fixe, il faut bien comprendre la différence avec wiggle: random crée une valeur différente pour chaque image sans aucun lien avec la valeur sur l'image précédente, alors que wiggle crée 'une courbe" de valeur aléatoire.

EXPRESSIONS : index

INDEX : un mot très important, oui, je sais, je dis ça à chaque fois.

Ce mot bien particulier donne une valeur précise: la position du calque dans la timeline. Et oui... Mais à quoi ça sert ? A tout, nous le verrons au fur et à mesure, c'est une fonction essentielle.
Par exemple, le calque tout en haut de votre composition aura un index égale à 1, etc. Cela nous amène donc à une possibilité extremement importante, celle d'avoir un comportement différent pour plusieurs calques qui sont pourtant de parfaits clones.
Voyons quelques exemples:

Créez un calque de 20x20, ouvrez sa position, et écrivez ceci:
[ index*40 , 100 ]

Votre calque se place naturellement à la position [40 , 100 ]
A present, dupliquez ce calque plusieurs fois ( ctrl D ou pomme D ). A chaque duplication, le nouveau calque se place à la droite du précédent. On le comprend bien, le second calque se place donc à la position [ 2 x 40 , 100 ], donc [ 80 , 100 ], etc.

Nous utiliserons index extremement souvent: pour placer des objets sur une grille, sur un cercle, en ligne, ou pour que chaque calque possède une variable aléatoire propre.