Aide pour After Effect, techniques, expressions.

mercredi 4 juin 2014

CIRCLE MAKER V1.11

Petite mise à jour de Circle Maker, il y avait un bug dans la position du cercle quand le controleur était en 3d. Le lien dans le post précédent est mis à jour.

mardi 27 mai 2014

CIRCLE MAKER v1

Bonjour à tous.

Aujourd'hui, petite nouveauté, je ne vais pas décrire comment faire ceci ou cela, mais plutôt vous faire un petit cadeau.
Voici CIRCLE MAKER V1, un petit script concocté par votre serviteur qui vous permettra de créer un cercle avec des calques et d'animer ces derniers avec tout plein de petits paramètres.


Libre à vous d'utiliser ce script comme bon vous semble, il y a beaucoup de possibilités.
Le script fonctionne avec lec versions française et anglaise d'After Effects, testé sous CS6 et CC.
Voici une video qui décrit l'ensemble des paramètres. Les carrés ne sont biensur qu'un exemple, remplaçable par n'importe lesquels de vos calques ou de vos composiitons.


N'hésitez pas à envoyer vos commentaires, questions, ou si vous repérez des bugs ! (en principe il n'y en a pas...)

mardi 25 mars 2014

Laissez-moi là

Bonjour à tous.

Cela fait très longtemps que rien n'a été écrit sur ce blog, non pas par manque d'envie, mais par manque de contenu. En effet, en général un article sort de terre quand un travail demande de trouver une nouvelle astuce. Et cela faisant donc longtemps que je n'avais pas du remettre un peu les mains dans le cambouis.

Je reviens donc avec une petite astuce pour, en quelque sorte, animer un lien de position.
En d'autre terme, c'est comme si on coupait un lien de parent-enfant entre 2 objets, mais uniquement pour la position.


L'idée est la suivante :
-suis la même position qu'un autre calque, plus un décalage spatial si nécessaire.
-Si on te dit de ne plus avoir ce lien, garde la dernière position que tu avais avant qu'on t'ait dit d'arrêter.

Voilà en gros comment faire :

On a 2 carrés, le rouge est le parent, le vert est l'enfant. Attention !! Il ne faut pas créer de lien de parenté !

Tout se passe donc sur le carré vert.
On rajoute à ce dernier un modificateur "Paramètre case", qui permet d'avoir une value intégrale (entière) de 0 (non) ou de 1 (oui). Appelons le "oui non".
Quand la valeur est égale à 0, le carré ne suivra pas, quand la valeur est égale à 1, il le suit.

On ouvre la position du carré vert, et c'est parti :

target=thisComp.layer("Parent");
I=effect("oui non")("Case");

"Case", c'est ainsi que j'ai nommé mon effet "Paramètre case".

Maintenant, on va chercher la clef "case" la plus proche de nous.

N=I.nearestKey(time);
Ni=N.index;

C'est assez simple, on a créé une autre variable Ni qui contient l'index de la clef la plus proche.

if ( N.time>time) { Ni=Ni-1};
Ngood=I.key(Ni);

Grace à ces 2 lignes, on fait en sorte que la clef la plus proche soit forcément celle qui soit derrière nous, c'est à dire dans le passé. Cela nous servira uniquement dans le cas où on souhaite recréer le lien de parent après l'avoir cassé.

Nt=Ngood.time;

Nt vaut donc la position de la clef "non" qui est juste derrière nous.

if ( I==1) { target.position + value }
else {
target.position.valueAtTime(Nt) +value }

Si I=oui, ajoute à ta positon la position du carré rouge.
Si I=non, ajoute à ta position la position du carré au moment où I t'as dit non.

REMARQUE : il faut mettre une clef "oui" ou "non" à l'image 0 de la composition, sinon ça bug.

Et voilà. C'est assez basique et écrit rapidement, je verrai comment cela peut être affiné.

vendredi 24 février 2012

proxy et import final

Rien de bien méchant, juste une petite astuce permettant d'optimiser la production d'animation.
Vous connaissez déjà tous les outils, mais voici l'idée.
Vous avez une compo avec plein d'images importées. Pour le moment, vous bossez avec les images basse résolution, pour éviter que ça rame. Mais à la fin, vous allez utiliser les images en haute définition, qui seront bien plus grandes que les basses définition.

Du coup, en remplaçant vos imports, cela va changer l'échelle de vos images.
On récupère donc la technique utilisée dans "toujours à la hauteur".

On crée un paramètre glissière sur notre calque, que l'on va appeler "taille".
Puis, dans l'échelle :

t=effect("taille")("Curseur");
s=(t/width)*100;
[s,s]

Du coup, c'est la valeur de "taille" qui définira la taille du calque, et rien d'autre. Remplacer votre 400x500 par un 2000x2500, le calque ne change pas de taille dans la compo.
Bien pratique ma foi.

jeudi 17 novembre 2011

répète pour voir ?

On m'a demandé comment faire pour qu'un son se déclenche automatique à un évènement, et puisse se répéter à chaque fois que cet évènement se produit, sans devoir recopier 200 fois le calque son en question.
C'est une question intéressante, dont la réponse dépend de votre situation.
Je vais donc essayer d'être le plus clair possible. Pour mon exemple, l'évènement en question sera le passage de la ligne de temps sur un marker de composition.
Comme vous le savez, quand vous appuyer sur la touche * et qu'aucun calque n'est sélectionné, cela vous crée un marker de composition. Si un calque était sélectionné, cela crée un marker SUR le calque.

Pour votre fichier son, il faut bien évidemment activer le remappage temporel, et écrire ceci pour l'expression :

T=thisComp.marker.nearestKey(time).time;

time-T

Et si vous placez vos marqueurs sur le calque, ça donne :

T=marker.nearestKey(time).time;

time-T

Oui, c'est tout...
Alors, expliquons un peu le pourquoi du comment.
On demande à T de trouver le marker le plus proche, et d'en enregistrer sa position temporel, ou en d'autres termes, à quel moment il se situe. Par exemple 1s20f, 0s12f, etc.

Tant que le temps est avant le marker, time-T vaut donc moins de 0, la soustraction reste donc bloquée à 0. Et des que time dépasse le marker, il part de 0, donc c'est comme si le calque était lu depuis le début.
Il faut donc que les markers aient au moins un espacement égal à la longueur du son, sinon le son joué en cours sera coupé pour reprendre depuis le début.

J'affinerai ce post plus tard pour illustrer des gestions un peu plus fines.

vendredi 24 juin 2011

Sélecteur graphique

De retour après pas mal de temps, j'ai donc pris le temps d'écrire ce nouveau post, qui ouvre une toute nouvelle dimension à l'animation; nous allons développer un outil assez puissant.

Je souhaite développer une idée très utilisée dans beaucoup de domaine : le sélecteur graphique. De quoi s'agit-il ? C'est très simple, le principe est de traduire une ligne droite en courbe. Tout le truc est évidemment de choisir la courbe que l'on souhaite.

Nous avions déjà vu ce principe sur de nombreux posts, j'en ai déjà parlé en long en large et en travers.
L'idée était d'utiliser une variable qui va de 0 à 1 (et linéaire), et d'altérer cette valeur pour en modifier la progression, selon ce tableau récapitulatif :



Maintenant, imaginons que nous voulons créer notre propre courbe, sans être bloqué par ces courbes mathématiques. Ensuite, nous allons nous en servir pour dispatcher des valeurs différentes à différents calques.
Nous allons utiliser la fonction valueAtTime.
Il y a une infinité d'applications, je vais donc en développer quelques unes.

Mais voyons déjà la structure.

Créez un Null avec un paramètre glissière.
Appelez le "courbe".
Allez dans courbe,, et animez la valeur, en mettant une clef à l'image 0 égale à 0, et une clef à 1 seconde égale à 1. Le choix de faire une courbe sur une seconde est arbitraire, mais pratique car on va de 0 à 1, et cela permet de ne pas se tromper entre chaque projet. "Comment j'ai fait ma courbe ce coup-ci déjà ?".
Passez cette ligne en easeInOut (F9), et dessiner la courbe qui vous plait.

Créez un petit carré, placez le en bas à gauche, et animer le sur X pour qu'il se déplace de gauche à droite.
On va dire qu'il se déplace sur X de 50 à 200 par exemple.

Ouvrer l'expression de la position, et écrivez :

courbe=thisComp.layer("Nul 1").effect("courbe")("Curseur");
hauteur=-200;

Quand le carré sera sur x=50, le cube sera en bas. Quand il sera à x=200, Y montera de 200 (hauteur = -200 car Y=0 est en haut).
Ensuite :

graphTime=linear(value[0],50,200,0,1);

Ici, on définit notre sélecteur, qui va nous permettre de prendre la valeur qui nous intéresse sur la courbe. Le 0 et le 1 de la fin correspondent donc au temps.

graph=courbe.valueAtTime(graphTime);

On a donc créer une valeur graph qui va prendre la courbe à un moment défini par la valeur de X.
La dernière ligne :

[value[0] , graph*hauteur+300]

Le graph va donc jouer son rôle d'interrupteur pour la hauteur, et 300 nous permet juste de mettre le carré vers le bas.
Voyez l'animation. Quand le carré avance, il monte en suivant une trajectoire qui ressemble à votre courbe.

Certains d'entre vous ont peut être une sensation de déjà-vu, puisqu'au final, on aurait pu dans ce cas utiliser simplement un linear(value,a,b,x,y) pour faire varier Y selon X, mais nous n'aurions pas eu la maîtrise des valeurs intermédiaires.

Ca n'a pas l'air comme ça, mais l'outil est surpuissant. Changer la forme de la courbe, et l'animation du carré changera sur Y.
L'outil est particulièrement pratique pour gérer plusieurs calques à la fois.
Un exemple que je ne vais pas développer mais qui parait évident : Faire un coverflow.

Car toute la question du coverflow est : de quelle façon mes calques s'avancent, reculent, grandissent. Vous pouvez ainsi tout contrôler facilement. Les calques ont une variable qui définisse leur distance par rapport au centre du coverflow, et la courbe vous permet de les faire commencer à grandir tout doucement au début, quand ils sont encore loin, puis de les faire grandir d'un coup, pour que celui du centre ait une taille bien plus grande que ceux d'à côté.

Ces applications pourraient être définies comme directes. En effet, l'utilisation de la courbe se retrouve plus ou moins visuellement dans l'animation, ici en trajectoire.

Mais on peut aller bien plus loin que cela, en créant par exemple des populations différentes. Soyons chiants 2 secondes, cela est comparable aux courbes que vous pouvez voir dans des magazines économiques par exemple. On vous montre une courbe des revenus moyens, et de la population qui est dans cette tranche. Résultat, la courbe est au plus haut sur le salaire médian, et très basse aux 2 extrémités.

Nous allons voir un exemple où l'on fait un peu la même chose, mais en moins chiant, pour ceux qui sont restés, merci à eux.

Nous allons reprendre l'animation des mouches que nous avons vu ici.
Les mouches suivent donc en retard, nous allons dessiner ce retard.

Voici ce que j'ai écrit pour chaque mouche :

target=thisComp.layer("Orange uni 1").transform.position;
courbe=thisComp.layer("Nul 1").effect("courbe")("Curseur");
retard=thisComp.layer("Nul 1").effect("retard")("Curseur");

seedRandom(index,true);
R=random(0,1);
graph=courbe.valueAtTime(R);

W=wiggle(2,10);

target.valueAtTime(time-graph*retard)+W-value

On comprend donc grace au random que chaque mouche va se voir attribuer une valeur aléatoire sur la courbe entre T0 et T1.

1er exemple :





Avec cette courbe, étant donné que la distribution des randoms est homogène entre 0 et 1, on comprend que les mouches auront plus de chance d'avoit une valeur proche de 1 que de 0.

On obtient donc cette animation :



La plupart des mouches ont un retard important.

2ème courbe :





Ici c'est l'inverse, la plupart des mouches auront un retard proche de 0, sauf certaines qui auront une valeur aléatoire attribuée dans la partie droite de la courbe.




En gros, nous avons créé un linear(value,a,b,x,y) beaucoup plus puissant, car nous contrôlons les valeurs intermédiaires.

Voilà, à vous de trouver comment cela peut vous servir. Le dernier exemple est assez parlant, car la simple utilisation du random aurait donné une distribution très homogène. Ici, on a pu créer un vilain petit canard très en retard.
Il vous suffit de changer la forme de la courbe pour voir toutes les mouches changer de position en prendre en compte la nouvelle distribution des retards.

Les applications sont infinies, et permettent de grandes finesses d'animation.

vendredi 18 février 2011

composition 2d en 3d

Oui je sais, une éternité sans post... C'est ainsi.
Petite astuce du jour. Vous avez une photographie, vous avez découpé différentes parties (1er plan, 2ème plan...), et voulez bouger votre caméra pour que l'on s'aperçoive que les différents éléments de la photo sont sur des plans différents.

Comme ça, ça n'a pas l'air bien compliqué, le truc, c'est que si on place les plans sur différentes valeurs de Z, ils n'auront plus le bon rapport de taille entre eux. Nous allons remédier à cela.

Comme tous ces calques seront en 3d, et que cette impression de 3d ne va apparaître que lorsque la caméra va se déplacer, il faut commencer par orienter nos calques dans le cas où la caméra ne serait pas face aux calques :

Donc dans l'orientation des calques :

a=thisComp.layer("Caméra 1").transform.position.valueAtTime(0);
lookAt(position,a)

Maintenant, pour pouvoir déplacer les calques sur l'axe Z de la caméra :
Créer un paramètre glissière sur le calque que vous nommerez "distance camera"

Puis, dans la position :

cam=thisComp.layer("Caméra 1").transform.position.valueAtTime(0);
V=sub(position,cam);
dist=effect("distance camera")("Curseur")/100;
value+V*dist

J'ai déjà expliqué tout ça, donc je ne m'attarde pas. Juste au sujet de "dist", j'ai divisé la valeur par 100 car notre vecteur doit être multiplié par 1 ou -1 pour que le calque soit collé à la caméra ou 2 fois plus loin. Le paramètre glissière sera ainsi plus simple à utiliser, et ça va nous aider pour l'échelle.

Voilà, vous pouvez tester, votre calque se déplace bien sur l'axe de la profondeur de la caméra quand vous modifiez le paramètre glissière.

Passons à l'échelle :
Quand le paramètre glissière est à 0, notre objet est à la bonne taille, son échelle est donc bien de 100. Si notre calque est collé à la caméra, il doit théoriquement avoir une échelle de 0. Si le paramètre glissière vaut 100, le calque sera donc 2 fois plus loin, il doit donc être 2 fois plus gros, etc.

On a donc :

dist=effect("distance camera")("Curseur");

s=dist+100;
[s,s,s]

Et voilà, c'est tout.