TD 2 : courbes, B-splines, Bézier, subdivision
Résumé du TD
Le but du TD est de tester les différentes formes de courbes vues en cours : B-Splines, Bézier, courbes de subdivision.Ce TD se fait sur deux semaines.
Instructions
Repartez du programme créé pour le TD précédent (mais recopiez-le dans un autre dossier). Il contient déjà une fonction pour entrer des points par la souris (stockés dans le tableau controlPoints).
Dans la fonction drawObject, commencez par afficher tous les points de contrôle (primitive GL_POINTS), avec un rayon large et une couleur bien visible. Tracez également la ligne brisée qui relie tous les points de contrôle dans l'ordre (mais en trait fin). Elle servira à contrôler les calculs.
Ensuite, il vous faut tracer la courbe. Je vous suggè de commencer par les B-splines. Prévoyez la possibilité de passer d'un type de courbe à l'autre par une touche du clavier.
B-Splines
Les B-splines sont définies à partir de 4 points de contrôle, Pi et d'un paramètre t (allant de 0 à 1):
La fonction B(t) est définie par intervalles :
Pour implémenter cette fonction, je vous déconseille les fonctions puissance (pow) ou exponentielle. Elles ont un coût énorme, et vous n'en avez pas besoin pour calculer une puissance 3.
Une fois que vous arrivez à tracer plusieurs segments de B-splines à la suite, vous pouvez soit continuer sur les courbes de Bézier, soit sauter à la partie Déplacement des points de contrôle (et revenir ensuite aux courbes de Bézier).
Courbes de Bézier
Les courbes de Bézier sont définies comme les B-splines, il n'y a que la fonction utilisée pour interpoler qui change:
Je vous déconseille d'utiliser les fonctions puissance ou exposant pour calculer, au pire, une puissance 3. Pour le calcul du coefficient du binome (C_3^i), je vous déconseille fortement d'utiliser des factorielles (sachant que vous n'avez à calculer que 4 valeurs, correspondant toutes à des cas simples...)
Courbes de subdivision
Les courbes de subdivision sont plus difficiles à implémenter, parce qu'elles n'ont pas d'équation précise. Elles sont définies par raffinement successifs : à chaque étape, on remplace les n points par 2n-1 nouveaux points, et on arrête la subdivision quand la courbe est suffisamment lisse.Dans le cadre du TD, comme il n'est pas facile de décider l'arrêt de la subdivision, je vous suggère de faire simplement 4 étapes de raffinement.
Vous pouvez implémenter n'importe quel schéma de subdivision vu en cours. Celui-ci est assez efficace :
- on garde les points calculés à l'étape précédente (qui font tous les points de rang pair, 2i)
- les nouveaux points (2i+1) sont définis par :
Déplacement des points de contrôle
Le plus intéressant avec ces courbes, c'est de voir comment elles se comportent quand on déplace un point de contrôle (tension, flexion, etc).
Il faut définir deux modes différents : un mode où on ajoute des points de contrôle en cliquant à la souris, et un mode où on déplace les points de contrôle. Le passage d'un mode à l'autre se fait en tapant sur une touche (fonction parsekey).
Si on est en mode "déplacement des points de contrôle", le premier travail est de déterminer quel point de contrôle on va déplacer. Lorsque l'utilisateur clique avec le bouton de la souris (fonction mouse), faites une boucle sur les points de contrôle, et sélectionnez celui qui est le plus proche du point cliqué par la souris (une simple distance en 2D dans l'écran). Pensez à mettre en évidence le point sélectionné (par une couleur différente).
Le deuxième travail est de suivre les modifications de façon interactive. Pour celà, il vous faut la fonction glutMotionFunc. Elle s'appelle juste après glutMouseFunc et prend comme argument une fonction à deux paramètres : motion(int x, int y).
La fonction passée en paramètre de glutMotionFunc est appelée en continu lorsque la souris est déplacée avec le bouton enfoncé. Dans cette fonction, vous calculez la nouvelle position du point de contrôle, et vous terminez par glutPostRedisplay(); qui redessine la scène.