Séance 5: Animation


Scène 3D possible après integration d'une animation

Animation hiérarchique

Code associé à cette partie: scenes_inf443/05_animation/a_hierarchy
Cette partie s'intéresse à la modélisation d'une forme articulée.
Les formes articulées sont généralement modélisées par des primitives reliées entre elles par des relations hiérarchiques: Chaque enfant hérite alors de la transformation du parent, et possède lui-même sa propre transformation.
Lors de la définition d'un objet hierarchique, il est généralement plus simple d'exprimer les transformations à appliquer (translation, rotation) sur un élément comme étant exprimé dans le repère local de son parent. La position et orientation finale d'un élément doit alors être calculé en composant la suite de transformations le long de la hierarchie.

Explication de la structure hiérarchique

Ce code met en oeuvre un modèle articulé modélisé à l'aide d'une structure hierarchy_mesh_drawable.

La structure hierarchy_mesh_drawable modélise une hiérarchie d'éléments. Chaque élément est associé à une transformation (ex. translation, rotation) exprimée localement par rapport au repère de son parent. Avant l'affichage, les transformations exprimées dans le repère global sont mises à jour en suivant la hiérarchie des éléments.

Compilez et exécutez le code et vérifiez que vous obtenez une animation similaire à la video suivante.


Observez la création du modèle hiérarchique dans la fonction initialize(). Chaque élément/noeud de la hierarchie est associé à une structure hierarchy_mesh_drawable_node. Ce noeud contient:
La création/ajout d'un noeud dans la hiérarchie se réalise avec l'opération hierarchy.add(...):
    • La transformation est par défaut l'identitée, et il est possible de modifier cette transformation plus tard.
Au moment de l'affichage:
    • Si vous aviez indiqué une transformation à l'initialization, cela revient à ré-écrire dessus.

Exercice: Ajout d'éléments

> Adaptez le code de manière à modéliser l'animation suivante:
  • Notez que grâce à l'utilisation de la hierarchie, l'ajout d'une transformation sur la racine se propage automatiquement à l'ensemble des éléments enfants.
Aide:
Remarque sur les rotations: Une rotation est une transformation linéaire. Appliquer une rotation revient donc à faire tourner les sommets de l'objet autour de l'origine.
Ainsi visuellement:
  • Rem. Dans le cas d'une hiérarchie, l'"origine" est l'origine du repère parent.
assets/rotation_center.png
Application d'une rotation sur un cylindre dont les coordonnées sont: centrées à gauche, sur l'un des bord à droite.

Exercice: Oiseau

Tentez désormais de créer la forme et l'animation d'une forme animée ressemblant à un oiseau. Exemple de modèle possible

(vous êtes libre de générer un modèle ayant une autre apparence et de l'adapter à votre convenance)
Aide:

Remarques si vous souhaitez utiliser la structure hiérarchique pour des modèles plus avancés.


(Supplément non obligatoire) Interpolation par spline cardinale

Etat actuel de la scène

Considérez le code présent dans le répertoire scenes/inf443/05_animation/b_interpolation_position
Ce code modélise une série de positions clés \(p_i\) affichées par des sphères blanches. Chaque position est associée à un "instant clé" \(t_i\). Les variables key_positions et key_times définies dans la fonction d'initialisation définissent respectivement les suites de positions et temps clés par lequels nous souhaitons réaliser l'interpolation.
Le déplacement de la sphère bleue au cours du temps correspond pour l'instant à l'interpolation linéaire entre ces positions clés. Celle-ci étant donnée par la relation \(\forall t\in[t_i, t_{i+1}]\;,\;\;p(t) = (1-\alpha)\, p_i + \alpha\, p_{i+1} \), avec \(\alpha=\frac{t-t_i}{t_{i+1}-t_i}\).
L'interpolation étant appelée à chaque frame (dans la fonction d'affichage) par la ligne
vec3 p = interpolation(t, keyframe.key_positions, keyframe.key_times);
La structure keyframe permet de stocker les positions et temps clés, et encapsule également les fonctions d'initialisation et d'affichage de ces positions.

Exemple du cas initial obtenu par interpolation linéaire. Notez la possibilité de déplacer les positions clés interactivement.
Notez que le code contient désormais un timer qui varie dans un intervalle défini entre timer.t_min et timer.t_max. L'initialisation de ces bornes est réalisé dans la fonction initialize()).
Notez également qu'il est possible de modifier interactivement les positions clés. Pour cela, appuyez sur shift pendant que vous sélectionnez puis déplacez une sphère d'une des positions de passage.
Le fichier interpolation.cpp contient les fonctions réalisant le calcul de la position interpolée au cours du temps.
Votre objectif est de modifier la fonction de calcul de la position interpolée passant de l'interpolation linéaire appliquée actuellement à une interpolation le long d'une spline cardinale (courbe lisse). Le déplacement résultant devant toujours passer par les points de controles aux instants correspondants.

Exemple de trajectoire obtenue lors de l'utilisation d'une spline cardinale.

Spline cardinale

On rappelle si nécessaire dans la suite le principe et les relations associées à l'interpolation par spline cardinale (rappel du cours).

Expression en cubique de Hermite

Considérons deux positions \(p_0\) et \(p_{1}\), associées à deux vecteurs dérivées \(d_0\) et \(d_{1}\). Supposons dans un premier temps que \(p_0\) est associé à l'instant \(0\), et \(p_1\) est associé à l'instant \(1\).

assets/interpolation_01.svg

La courbe \(p(t)\) interpolant ces positions et dérivées entre \(t=0\) et \(t=1\) doit satisfaire les contraintes suivantes

\(\left\{ \begin{array}{l} p(0) = p_0 \\ p(1) = p_1 \\ p ' (0) = d_0 \\ p ' (1) = d_1 \end{array} \right.\)

En supposant que la fonction \(p:t\to p(t)\) soit exprimée sous la forme d'un polynome cubique \(p(t)=a t^3 + b t^2 + c t + d\), l'ensemble des contraintes se traduit par un système linéaire à 4 inconnus

\(\left\{ \begin{array}{r} d = p_0 \\ a+b+c+d = p_1 \\ c = d_0 \\ 3 a + 2 b + c = d_1 \end{array} \right.\)

La résolution de ce système abouti au polynome solution

\(p(t)=(2 p_0 - 2 p_1 + d_0 + d_1) t ^ 3 + (-3 p_0 + 3 p_1 - 2 d_0 - d_1) t ^ 2 + d_0 t + p_0 \)

Ou encore, reformulé suivant la représentation dite de Hermite, en regroupant les termes suivants \((p_0,p_1,d_0,d_1)\)

\(p(t) = (2 t^3 - 3 t^2 + 1)\, p_0 + (t ^ 3 - 2 t ^ 2 + t)\, d_0 + (-2 t ^ 3 + 3 t ^ 2)\, p_1 + (t ^ 3 - t^2)\, d_1 \)

Prise en compte de la plage de valeur du paramètre temporelle

D'une manière plus générale lorsque l'on cherche à interpoler un ensemble de positions clés, les sommets \((p_0, p_1)\) vont correspondre aux positions \((p_i,p_{i+1})\) qui sont elles même associés à des instants \((t_i,t_{i+1})\) quelconques. On supposera similairement que les dérivées sont données par \((d_{i}, d_{i+1})\)

assets/interpolation_02.svg

Afin de prendre en compte la plage de variation du paramètre \(t\), on applique un changement de variable transformant l'intervalle \([t_i,t_{i+1}]\) vers \([0,1]\).

Le polynome de Hermite interpolant des deux positions et dérivées peut alors s'exprimer sous la forme

Expression en position: Spline Cardinale

La dernière étape consiste à exprimer le polynome en utilisant uniquement des données de positions à la place des deux dérivées. La "spline cardinale" consiste à exprimer ces dérivées sous la forme de différences finies par rapport aux positions voisines.

On pourra considérer

Avec \(K\in[0,1]\) un paramètre relié à la notion de "tension" de la spline.

Notez qu'il s'agit d'une version un peu plus générale que celle vue en cours en prenant en compte des intervalles de temps quelconques. Vous retrouverez la formulation du cours en supposant \(\forall i\;,\;t_{i+1}-t_i = constante = 1\).

Synthèse

La Spline Cardinale interpolant les positions \(p_i\) aux instants \(t_i\) peut s'exprimer sous la forme suivante

\(\forall i\in[\![1,N-2]\!], \forall t\in[t_i,t_{i+1}]\)

  • \(p(t) = (2 s ^ 3 - 3 s ^ 2 + 1)\, p_i + (s ^ 3 - 2 s ^ 2 + s)\, d_i + (-2 s ^ 3 + 3 s ^ 2)\, p_{i+1} + (s ^ 3 - s^2)\, d_{i+1}\)

  • \(\displaystyle s=\frac{t-t_i}{t_{i+1}-t_i}\)
  • \(\displaystyle d_i=2 K \, \left(\frac{p_{i+1}-p_{i-1}}{t_{i+1}-t_{i-1}}\right)\)
  • \(\displaystyle d_{i+1}=2 K\,\left(\frac{p_{i+2}-p_{i}}{t_{i+2}-t_{i}}\right)\)

Exercice: Interpolation

En suivant et adaptant le schéma utilisé pour l'interpolation linéaire, implémentez l'interpolation par spline cardinale. Pour cela

Scène finale

Si jamais vous êtes en avance, vous pouvez tenter d'incorporer votre élément animé dans votre scène de terrain.

Rem. Les extensions, ainsi que l'incorporation de l'interface de manipulation des points de contrôle dans votre scène demande un travail conséquent. Ne passez pas trop de temps dessus si vous n'êtes pas en avance.