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.
vendredi 19 février 2010
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é.
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é.
vendredi 12 février 2010
faux contact
Un petit truc tout simple aujourd'hui, nous allons créer un interrupteur qui galère un peu à se stabiliser, à la manière d'un néon.
Il y a 1000 façons de voir les choses, en voici une.
Voilà commet nous pourrions décrire l'allumage d'un néon :
A partir du moment où l'on appuie sur l'interrupteur, plus le temps passe, plus le néon a une forte probabilité d'être allumé, jusqu'à ce qu'il le reste allumé sans probabilité de revenir à une position éteinte.
Nous devons donc créer une courbe qui restitue cette définition.
Nous allons utiliser une variable qui ira de 0 à 1.
A 0, le néon n'aura aucune chance d'être allumé, et à 1, le néon sera forcément allumé. Nous allons donc utiliser 2 outils : le wiggle, et Math.round. Vous pouvez cliquer sur un des 2 mots pour avoir un rappel de leur fonction.
Pour le moment, occupons nous du wiggle. Voilà la 1ere courbe que nous voulons :
Rappelez-vous qu'ensuite, nous allons utiliser Math.round pour que la valeur de sortie ne puisse faire que 0 ou 1. Donc tout ce qui sera sous 0.5 vaudra 0, et tout ce qui vaudra 0.5 et plus faudra 1.
Donc quand la variable vaut 0, notre wiggle ne doit rien produire au delà de 0.4999. Le wiggle faisant varier la valeur aussi bien vers le haut que le bas, nous avons donc besoin d'un départ à 0.25, et que l'amplitude du wiggle soit égale à 0.25, pour qu'on aille bien de 0 à 0.5.
Dans la théorie, je suis bien d'accord, cela donne une possibilité d'atteindre 0.5, mais dans la pratique, ça n'est pas le cas, le wiggle atteint très rarement sa valeur max.
Quand la variable vaudra 1, c'est tout pareil, mais entre 0.5 et 1.
Le wiggle va donc garder son amplitude de 0.25 de chaque coté, mais avec une valeur moyenne de 0.75.
Voilà ce que ça donne :
I=thisComp.layer("controle").effect("switch")("Curseur");
.25+ I/2+ wiggle(20,.25)
N'oubliez pas que le wiggle contient la valeur initiale de la variable ! N'oubliez donc pas de bien mettre 0 dans la valeur qui contient l'expression pour que le wiggle tremble bien autour de 0.
.25+ I/2 varie bien de 0.25 à 0.75. La fréquence de 20 est arbitraire, mais fonctionne bien.
Il ne reste plus qu'à utiliser le Math.round:
I=thisComp.layer("controle").effect("switch")("Curseur");
Math.round(
.25+ I/2+ wiggle(20,.25)
)
Regardez votre graphique. Plus on s'approche de 1, moins le néon a une chance de s'éteindre.
Une fois que la variable vaut 1, plus aucune chance que ça s'éteigne.
La morale d'aujourd'hui ? (oui j'ose)
Même si c'est intuitivement très simple, on se doute bien qu'il s'agit d'une histoire de Wiggle & Cie, il faut bien réfléchir en amont pour avoir l'effet escompté.
Il y a 1000 façons de voir les choses, en voici une.
Voilà commet nous pourrions décrire l'allumage d'un néon :
A partir du moment où l'on appuie sur l'interrupteur, plus le temps passe, plus le néon a une forte probabilité d'être allumé, jusqu'à ce qu'il le reste allumé sans probabilité de revenir à une position éteinte.
Nous devons donc créer une courbe qui restitue cette définition.
Nous allons utiliser une variable qui ira de 0 à 1.
A 0, le néon n'aura aucune chance d'être allumé, et à 1, le néon sera forcément allumé. Nous allons donc utiliser 2 outils : le wiggle, et Math.round. Vous pouvez cliquer sur un des 2 mots pour avoir un rappel de leur fonction.
Pour le moment, occupons nous du wiggle. Voilà la 1ere courbe que nous voulons :
Rappelez-vous qu'ensuite, nous allons utiliser Math.round pour que la valeur de sortie ne puisse faire que 0 ou 1. Donc tout ce qui sera sous 0.5 vaudra 0, et tout ce qui vaudra 0.5 et plus faudra 1.
Donc quand la variable vaut 0, notre wiggle ne doit rien produire au delà de 0.4999. Le wiggle faisant varier la valeur aussi bien vers le haut que le bas, nous avons donc besoin d'un départ à 0.25, et que l'amplitude du wiggle soit égale à 0.25, pour qu'on aille bien de 0 à 0.5.
Dans la théorie, je suis bien d'accord, cela donne une possibilité d'atteindre 0.5, mais dans la pratique, ça n'est pas le cas, le wiggle atteint très rarement sa valeur max.
Quand la variable vaudra 1, c'est tout pareil, mais entre 0.5 et 1.
Le wiggle va donc garder son amplitude de 0.25 de chaque coté, mais avec une valeur moyenne de 0.75.
Voilà ce que ça donne :
I=thisComp.layer("controle").effect("switch")("Curseur");
.25+ I/2+ wiggle(20,.25)
N'oubliez pas que le wiggle contient la valeur initiale de la variable ! N'oubliez donc pas de bien mettre 0 dans la valeur qui contient l'expression pour que le wiggle tremble bien autour de 0.
.25+ I/2 varie bien de 0.25 à 0.75. La fréquence de 20 est arbitraire, mais fonctionne bien.
Il ne reste plus qu'à utiliser le Math.round:
I=thisComp.layer("controle").effect("switch")("Curseur");
Math.round(
.25+ I/2+ wiggle(20,.25)
)
Regardez votre graphique. Plus on s'approche de 1, moins le néon a une chance de s'éteindre.
Une fois que la variable vaut 1, plus aucune chance que ça s'éteigne.
La morale d'aujourd'hui ? (oui j'ose)
Même si c'est intuitivement très simple, on se doute bien qu'il s'agit d'une histoire de Wiggle & Cie, il faut bien réfléchir en amont pour avoir l'effet escompté.
dimanche 31 janvier 2010
lampe anisotropique et son flare
Derrière cette recette délicieuse se cache simplement le même principe que la luminosité de Lux, mais appliqué à un flare.
Quelle est la différence à observer ?
Si la lumière volumétrique est bel et bien un phénomène lumineux qui varie selon l'angle avec la caméra, il reste en principe visible dans toutes les directions, même si la lampe est dos à la caméra.
Pour les flares, ça n'est pas le cas. Ils ne sont visibles que lorsque la lampe est en face de la caméra. C'est même dans la nature profonde des flares d'avoir des changements importants au moindre changement d'angle de la lumière.
On peut donc considérer qu'un flare ne commence à apparaître que lorsque la lampe est AU MOINS de profile par rapport à la caméra.
Souvenez vous du petit diagramme avec l'angle de la lampe qui tourne.
La valeur de profil correspond donc à la situation ou les 2 segments sont perpendiculaires.
Les segments valant chacun 1, le vecteur bleu mesure donc racine carré de 2, donc environ 1.4
Il nous suffit donc de modifier la dernière ligne pour que la valeur ne commence non pas à 0, mais à ...hmm ?
Alors alors, souvenez vous, le vecteur bleu va de 2 à 0.
Et on avait transformer ça en valeur qui va de 0 à 1.
C'était donc 1-x/2 pour arriver à ça.
1-1.4/2=0.3
Donc la dernière ligne est :
ease(courbe,0.3,1,min,max)
Et voilà. Votre flare n'apparaîtra qu'à partir du moment où la lampe est dirigée vers la caméra.
Et vous pouvez toujours jouer avec la variable "falloff" pour contraster son apparition
mardi 26 janvier 2010
remappage temporel de clef 2
Certains l'auront peut-être compris, cette technique de remappage de clefs peut également servir à la gestion de plusieurs valeur à la fois.
Par exemple, si vous avez une animation sur une position et sur une rotation, et que vous voulez changer la vitesse d'animation tout en gardant le même rapport entre la position et la rotation.
Imaginez par exemple un homme qui saute d'un plongeoir en faisant des figures. La rotation de son corps sera à priori toujours la même à une position donnée. Autre façon de le dire, la rotation est fonction de la position.
En gros, c'est exactement la même chose, sauf que bien entendu, on va créer la variable dans un calque à part, puisqu'il peut être destiné à plusieurs calques.
On appliquera donc l'expression
target=thisComp.layer("controle vitesse").effect("temps")("Curseur");
valueAtTime(target)
à toutes les valeurs dont on veut contrôler le déroulement.
Mais si vous vous souvenez de l'autre post (ou si vous relisez), nous avions relié la valeur du curseur (celui qui va de 0 à 100) à la valeur à modifier.
Vous pouvez toujours faire ça, mais à quelques conditions:
-la variable qui gère le curseur (la position dans le post précédent) doit avoir sa 1ère clef avant les 1eres clefs de toutes les autres variables (ou au même moment) et sa dernière clef doit être après les dernières clefs des autres variables.
C'est logique, puisque la valeur ne va varier le temps qu'entre les clefs de cette variable.
Ceux qui commence à avoir un peu de bouteille auront sans doute l'intuition qu'il y a d'autres façon de générer cette valeur de temps remappé.
En effet, on peut le voir de plein de façons différentes.
En voici une autre, que vous allez surement préférer dans le cas où il faut gérer plusieurs variables en même temps :
T=thisComp.duration;
linear(value,0,100,0,T)
Voilà, c'est vraiment tout bête.
T vaut la longueur de la composition (en seconde). Quand le curseur vaut 0, le temps vaut 0, et quand le curseur vaut 100, ça renvoie au code temporel de la dernière image de la compo.
Cette expression est plus valable dans le cas où on gère un ensemble de calques/variables, car il n'y a pas de raison pour qu'une variable rentre dans l'équation qui gère un ensemble de variables qui sont au même niveau hiérarchique que cette dernière.
Voilà, il vous suffit donc de bien copier l'expression dans toutes les variables animées que vous voulez.
Vous pourrez ainsi gérer l'ensemble de vos clefs d'une même composition !
Si c'est pas chouette quand même....
Par exemple, si vous avez une animation sur une position et sur une rotation, et que vous voulez changer la vitesse d'animation tout en gardant le même rapport entre la position et la rotation.
Imaginez par exemple un homme qui saute d'un plongeoir en faisant des figures. La rotation de son corps sera à priori toujours la même à une position donnée. Autre façon de le dire, la rotation est fonction de la position.
En gros, c'est exactement la même chose, sauf que bien entendu, on va créer la variable dans un calque à part, puisqu'il peut être destiné à plusieurs calques.
On appliquera donc l'expression
target=thisComp.layer("controle vitesse").effect("temps")("Curseur");
valueAtTime(target)
à toutes les valeurs dont on veut contrôler le déroulement.
Mais si vous vous souvenez de l'autre post (ou si vous relisez), nous avions relié la valeur du curseur (celui qui va de 0 à 100) à la valeur à modifier.
Vous pouvez toujours faire ça, mais à quelques conditions:
-la variable qui gère le curseur (la position dans le post précédent) doit avoir sa 1ère clef avant les 1eres clefs de toutes les autres variables (ou au même moment) et sa dernière clef doit être après les dernières clefs des autres variables.
C'est logique, puisque la valeur ne va varier le temps qu'entre les clefs de cette variable.
Ceux qui commence à avoir un peu de bouteille auront sans doute l'intuition qu'il y a d'autres façon de générer cette valeur de temps remappé.
En effet, on peut le voir de plein de façons différentes.
En voici une autre, que vous allez surement préférer dans le cas où il faut gérer plusieurs variables en même temps :
T=thisComp.duration;
linear(value,0,100,0,T)
Voilà, c'est vraiment tout bête.
T vaut la longueur de la composition (en seconde). Quand le curseur vaut 0, le temps vaut 0, et quand le curseur vaut 100, ça renvoie au code temporel de la dernière image de la compo.
Cette expression est plus valable dans le cas où on gère un ensemble de calques/variables, car il n'y a pas de raison pour qu'une variable rentre dans l'équation qui gère un ensemble de variables qui sont au même niveau hiérarchique que cette dernière.
Voilà, il vous suffit donc de bien copier l'expression dans toutes les variables animées que vous voulez.
Vous pourrez ainsi gérer l'ensemble de vos clefs d'une même composition !
Si c'est pas chouette quand même....
recherche
N'hésitez pas à utiliser le champ de recherche pour trouver un article qui traite d'un sujet particulier ou d'une fonction.
jeudi 21 janvier 2010
remappage temporel de clef
Bonsoir à tous.
Ce soir, un petit outil très pratique qui va vous permettre de gérer la vitesse d'animation d'une valeur sans toucher à cette dernière.
Petit exemple:
Comme vous le savez, quand un objet va d'un point A à un point B, vous pouvez gérer la courbe de vitesse pour faire en sorte que l'objet accélère tout du long, ou freine juste à la fin, etc.
Mais c'est un peu plus compliqué quand l'objet décrit une trajectoire faite de 5 ou 256 points. On peut toujours mettre les points en mode "déplacement dans le temps", mais on ne gère que la vitesse globale et non local (à chaque instant).
Nous allons donc installer un système de remappage temporel, mais pour les clefs.
Vous allez voir, c'est assez simple.
J'explique d'abord ce que l'on va faire:
On va créer une valeur qui va de 0 à 100. Quan la valeur vaudra 0, on chargera la position qui est sur la 1er clef. Quand la valeur vaudra 100, on chargera la valeur qui est sur la dernière clef.
Créez votre objet, faites lui faire une petite trajectoire faite avec 4-5 clefs, qu'importe.
Ensuite, rajoutez lui un paramètre glissière et écrivez ceci :
n=position.numKeys;
On demande que n valle le nombre de clefs dans la valeur "position".
start=position.key(1).time;
end=position.key(n).time;
On crée 2 variables qui nous indiquent à quel code temporel se trouve la 1ere clef et la dernière clef (et oui, la clef "n" sera toujours la dernière. Vous pouvez rajouter des clefs, ça se mettra à jour tout seul).
linear(value,0,100,start,end);
Et voilà !
Il ne vous reste plus qu'à animer ce paramètre glissière en l'animant de 0 à 100.
Cela vous permet de gérer l'accélération/décélération de l'objet, ou vous pouvez aussi faire varier la valeur dans tous les sens pour faire une yoyo, ou même utiliser un wiggle pour aller de 0 à 100.
A présent, écrivez ceci dans la position de l'objet :
p=effect("Paramètre glissière")("Curseur");
valueAtTime(p)
La position va donc charger la position à un moment différent, celle qui est dans le paramètre glissière.
Ça fonctionne évidemment pour toutes les propriétés.
Inscription à :
Articles (Atom)





