Enseignant du Cours:
DJAFER BADDOU (PhD)
Courriel: djafer.baddou@uqo.ca
Programmation 2D/3D
INF 1483
Contenu
Introduction
Mathématiques
de l’infographie
Notions de
Mathématiques
Transformations
Géométriques
Applications OpenGL
Effets Optiques
et Rendu
Effet de lumière
sur les objets
Plaquage des
Textures et
ombrages.
Techniques
d'animation et
simulation 2D/3D
Equations des
mouvements des objets.
Animation:
Temps Réel , a
Frame par Frame.
Applications
OpenGL
Introduction à
l’Infographie
Introduction à
OpenGL
IDE en OpenGL
Programmation 2D/3D: INF 1483
Applications
OpenGL
Applications
OpenGL
The pipeline revisited
Animating the
scene
To keep the image
moving,
our glutIdleFunc call
back continuously
updates the value
we assign to
the fade_factor unifo
rm.
The pipeline revisited
Animating the
scene
GLUT maintains a
millisecond timer
we can access
with glutGet(GLUT
_ELAPSED_TIME);
we just feed this
through the
standard C sinf
function to get a
smooth, periodic
fade from zero to
one and back.
Plaquage des Textures
Simulation et Animation
Programmation 2D/3D:
INF 1483
Conclusion
Compiling and running
the program, again
It's finally time to compile
and run the whole program
with all of our new code.
The command to build the
executable will look much
as it did last time when we
built the dummied-out
version, but this time, you'll
build from the real hello-
gl.c and util.csource files.
Animating the scene
Every time we update the
fade factor, we
call glutPostRedisplay,
which forces
our render callback to get
invoked again, updating
the window.
Animating the scene
static void
update_fade_factor(voi
d) { int milliseconds =
glutGet(GLUT_ELAPSE
D_TIME);
g_resources.fade_facto
r =
sinf((float)milliseconds *
0.001f) * 0.5f + 0.5f;
glutPostRedisplay(); }
The pipeline revisited
Animating the
scene
To keep the image
moving,
our glutIdleFunc call
back continuously
updates the value
we assign to
the fade_factor unifo
rm.
The pipeline revisited
Animating the
scene
GLUT maintains a
millisecond timer
we can access
with glutGet(GLUT
_ELAPSED_TIME);
we just feed this
through the
standard C sinf
function to get a
smooth, periodic
fade from zero to
one and back.
Plaquage des Textures
Simulation et Animation
Programmation 2D/3D:
INF 1483
Conclusion
Compiling and running
the program, again
If you use the Makefiles,
you can build with the
default target:
make -f Makefile.MacOSX
# or Makefile.Unix or
Makefile.Mingw nmake /f
Nmakefile.Windows
Once built, the program
assumes that all its image
and shader resources are
in the current directory, so
Animating the scene
Every time we update the
fade factor, we
call glutPostRedisplay,
which forces
our render callback to get
invoked again, updating
the window.
Animating the scene
static void
update_fade_factor(voi
d) { int milliseconds =
glutGet(GLUT_ELAPSE
D_TIME);
g_resources.fade_facto
r =
sinf((float)milliseconds *
0.001f) * 0.5f + 0.5f;
glutPostRedisplay(); }
// Aiguille des secondes
ctx.save();
ctx.rotate(sec * Math.PI/30);
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30,0);
ctx.lineTo(83,0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,true);
ctx.fill();
ctx.beginPath();
ctx.arc(95,0,10,0,Math.PI*2,true);
ctx.stroke();
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.arc(0,0,3,0,Math.PI*2,true);
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = '#325FA2';
ctx.arc(0,0,142,0,Math.PI*2,true);
ctx.stroke();
ctx.restore();
window.requestAnimationFrame(clock);
}
window.requestAnimationFrame(clock);
ball.vy = -ball.vy;
}
if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
ball.vx = -ball.vx;
}
/////////////////////////////////////////
Voyons voir ce que cela donne. Déplacez votre souris dans le canevas pour commencer l'animation :
AccélérationSection
Afin d'obtenir un mouvement plus réel, vous pouvez jouer sur la vitesse, par exemple :
ball.vy *= .99;
ball.vy += .25;
Ceci ralentit la vitesse verticale à chaque rendu d'image de sorte que la balle va rebondir de moins en moins haut.
Effet de traînéeSection
Jusqu'à maintenant, nous avons utilisé la méthode clearRect pour effacer les images précédentes. En la remplaçant par la méthode fillRect et en
utilisant un remplissage semi-transparent, on obtient un effet de traînée.
ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fillRect(0,0,canvas.width,canvas.height);
Ajout d'un contrôle de sourisSection
Afin d'obtenir quelques contrôles sur la balle, nous pouvons faire suivre notre souris en utilisant l'événement mousemove, par exemple. L'événement
click relâche la balle et la laisse rebondir à nouveau.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var raf;
var running = false;
var ball = {
It's finally time to compile and run the whole program with all of our new code. The command to build the executable will look much as it did last time when we built the dummied
and util.csource files. If you use the Makefiles, you can build with the default target:
Nmakefile.Windows
Once built, the program assumes that all its image and shader resources are in the current directory, so it will work best to run it from the command line from inside the directory
containing the executable, the image files, and the shader source. We can finally bask in the glory of our hard work:
OpenGL version Render the scene
WebGL version Drawing the scene
Une fois que les shaders
sont définis, que les
emplacements sont
retrouvés, et que les
positions des sommets
du carré 2D sont
stockées dans le
tampon, nous pouvons
faire effectivement le
rendu de la scène.
Puisque nous n'animons
rien dans cet exemple,
notre fonction
drawScene() est très
simple. Elle utilise
quelques routines
utilitaires que nous
décrirons sous peu.
La première étape
consiste à effacer le
canevas avec notre
arrière plan ; ensuite,
Le Pipeline Graphique
9
Let's start writing the
code to set up our
rendering job state:
Activating the
shader program and
assigning uniforms
glClearColor sets an
RGBA clear color (in
this case, white),
which glClear then
uses to fill the
framebuffer's color
buffer.
glutSwapBuffers then
brings our cleared
color buffer to the
screen.
We begin by
activating our shader
program by passing
the name of the
linked program
Introduction à OpenGL
Programmation 2D/3D:
INF 1483
function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0); // effacement en
noir, complètement opaque
gl.clearDepth(1.0); // tout effacer
gl.enable(gl.DEPTH_TEST); // activer le test
de profondeur
gl.depthFunc(gl.LEQUAL); // les choses
proches cachent les choses lointaines
// Effacer le canevas avant que nous ne
commencions à dessiner dessus.
gl.clear(gl.COLOR_BUFFER_BIT |
gl.DEPTH_BUFFER_BIT);
Chapitre Transformation:
// Créer une matrice de perspective, une matrice
spéciale qui est utilisée pour
// simuler la distorsion de la perspective dans une
static void render(void){
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(g_resources.program);
glUniform1f(g_resources.uniforms.fa
de_factor, g_resources.fade_factor);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,
g_resources.textures[0]);
glUniform1i(g_resources.uniforms.tex
tures[0], 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,
g_resources.textures[1]);
glUniform1i(g_resources.uniforms.tex
tures[1], 1);
glBindBuffer(GL_ARRAY_BUFFER,
g_resources.vertex_buffer);
glVertexAttribPointer(
g_resources.attributes.position, /*
attribute */ 2, /* size */ GL_FLOAT, /*
type */ GL_FALSE, /* normalized? */
sizeof(GLfloat)*2, /* stride */
(void*)0 /* array buffer offset */ );
glEnableVertexAttribArray(g_resource
s.attributes.position);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER ,
g_resources.element_buffer);
glDrawElements( GL_TRIANGLE_STRIP, /*
mode */ 4, /* count */
GL_UNSIGNED_SHORT, /* type */ (void*)0
/* element array buffer offset */ );
glDisableVertexAttribArray(g_resource
s.attributes.position);
glutSwapBuffers();
}
OpenGL version Render the scene
WebGL version Drawing the scene
Une fois que les shaders
sont définis, que les
emplacements sont
retrouvés, et que les
positions des sommets
du carré 2D sont
stockées dans le
tampon, nous pouvons
faire effectivement le
rendu de la scène.
Puisque nous n'animons
rien dans cet exemple,
notre fonction
drawScene() est très
simple. Elle utilise
quelques routines
utilitaires que nous
décrirons sous peu.
La première étape
consiste à effacer le
canevas avec notre
arrière plan ; ensuite,
Le Pipeline Graphique
10
Let's start writing the
code to set up our
rendering job state:
Activating the
shader program and
assigning uniforms
This for Chapitre
Texture and
Animation
Once the program is
active, we can start
assigning values to
our uniform
variables. If you
recall from looking at
our fragment shader
source, we have the
float fade_factor and
an array of two
sampler2Ds named
Introduction à OpenGL
Programmation 2D/3D:
INF 1483
function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0); // effacement en
noir, complètement opaque
gl.clearDepth(1.0); // tout effacer
gl.enable(gl.DEPTH_TEST); // activer le test
de profondeur
gl.depthFunc(gl.LEQUAL); // les choses
proches cachent les choses lointaines
// Effacer le canevas avant que nous ne
commencions à dessiner dessus.
gl.clear(gl.COLOR_BUFFER_BIT |
gl.DEPTH_BUFFER_BIT);
Chapitre Transformation:
// Créer une matrice de perspective, une matrice
spéciale qui est utilisée pour
// simuler la distorsion de la perspective dans une
static void render(void){
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(g_resources.program);
glUniform1f(g_resources.uniforms.fa
de_factor, g_resources.fade_factor);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,
g_resources.textures[0]);
glUniform1i(g_resources.uniforms.tex
tures[0], 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,
g_resources.textures[1]);
glUniform1i(g_resources.uniforms.tex
tures[1], 1);
glBindBuffer(GL_ARRAY_BUFFER,
g_resources.vertex_buffer);
glVertexAttribPointer(
g_resources.attributes.position, /*
attribute */ 2, /* size */ GL_FLOAT, /*
type */ GL_FALSE, /* normalized? */
sizeof(GLfloat)*2, /* stride */
(void*)0 /* array buffer offset */ );
glEnableVertexAttribArray(g_resource
s.attributes.position);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER ,
g_resources.element_buffer);
glDrawElements( GL_TRIANGLE_STRIP, /*
mode */ 4, /* count */
GL_UNSIGNED_SHORT, /* type */ (void*)0
/* element array buffer offset */ );
glDisableVertexAttribArray(g_resource
s.attributes.position);
glutSwapBuffers();
}
Qu'est-ce que la cinématique?
Équations des Mouvements
Translations: Le mouvement rectiligne uniforme
Un mobile soumis à un mouvement rectiligne
uniforme se déplace à:
Vitesse constante, sa vitesse ne varie pas
avec le temps;
Distance parcourue linéaire donc à
chaque seconde, il parcourt la même
distance.
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
11
Cest une partie de la physique de mécanique.
La cinématique s’occupe à décrire les
mouvements, les changements d'état du système
(ex: de repos à accélération).
La cinématique décrit trois types de mouvements:
1. les translations (une voiture roulant sur la
route, un mobile en chute libre),
2. les rotations (la terre autour du soleil, un seau
attaché à une corde) et
3. les vibrations (le pendule de Foucault).
Équations des Mouvements
Équations des Mouvements
Translations: Le mouvement rectiligne uniforme
Par Exemple:
soit le vecteur de vitesse (3, 0, -4) km / seconde.
Ce vecteur donne:
la direction (3, 0, -4) et
la vitesse dans cette direction est de
5 km / seconde.
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
12
Translations: Mouvement Rectiligne Uniforme
Pour une vitesse constante, on peut spécifier la
position initiale et le vecteur de vitesse pour le
mouvement. Léquation du mouvement est donc:
v et x0 sont des constantes
On dira que , x0 la position initiale (quand
l'objet a commencé son mouvement), c’est la
condition initiale du système.
Équations des Mouvements
Équations des Mouvements
Translations: Mouvement Rectiligne Uniformément
Accéléré
a est l’accélération:
a est positive, le mouvement est accéléré.
a est négative, le mouvement est décéléré ou retar
On dira que le couple constitue les conditions
initiales du système.
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
13
Translations: Mouvement Rectiligne Uniformément
Accéléré
Un mobile soumis à un mouvement rectiligne uniformément
accéléré voit:
sa vitesse varier linéairement au cours du temps et, par
conséquent,
son déplacement s'exprime par une fonction du second
degré décrivant une parabole.
En équations, cela donne :
Équations des Mouvements
Équations des Mouvements
Rotations: Mouvement Circulaire
Repère polaire :
chaque point 𝑶𝑴 du plan est aussi entièrement déterminé
par une distance ρ = 𝑶𝑴 et un angle
q
mesuré par
rapport à l'axe des abscisses
Ԧ
𝒊. Ce couple unique (ρ ;
q
)
s'appelle coordonnées polaires du point M relativement au repère
polaires (O : ρ ,
q
).
Les coordonnées polaires constituent un système de coordonnées
à deux dimensions (O : ρ ,
q
), dans lequel chaque point du plan est
entièrement déterminé par un angle et une distance.
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
14
Rotations: Mouvement Circulaire
Dans le plan, il existe plusieurs façons de repérer un point.
Repère cartésien :
Avec un repère orthonormal sur le plan, à tout point M
de ce plan, correspond un couple unique (x ; y ) réels tels que :
𝑶𝑴 = x
Ԧ
𝒊 + y
Ԧ
𝒋.
Ce couple (x ; y ) s'appelle coordonnées cartésiennes du
point M dans le repère.
Équations des Mouvements
Équations des Mouvements
Rotations: Mouvement Circulaire
Repère polaire :
Le système de coordonnées polaires
peut être étendu à l'espace à trois
dimensions de deux manières,
donnant:
1. le système de coordonnées
cylindriques (O : ρ ,
q ,
z )
Le concept est de rajouter une
coordonnée de distance z, la hauteur.
2. le système de coordonnées
sphériques (O : ρ ,
q,
φ ).
Le concept est de rajouter une autre
coordonnée angulaire φ.
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
15
Rotations: Mouvement Circulaire
Repère polaire :
La coordonnée radiale (ρ) appelée rayon exprime la distance du
point 𝑴 à un point central 𝑶 appelé pôle (équivalent à l’origine
des coordonnées cartésiennes).
La coordonnée angulaire
q
, appelée angle polaire ou azimut,
exprime la mesure, dans le sens trigonométrique (sens positif),
de l’angle entre le point 𝑴 et la demi-droite 𝑶𝑿 d’angle 0°,
appelée axe polaire (équivalente à l’axe des abscisses en
coordonnées cartésiennes).
Contrairement aux coordonnées cartésiennes (x ; y ) , les coordonnées
polaires ne sont pas de même nature. La coordonnée radiale a la
dimension d'une longueur et la coordonnée angulaire s'exprime en radian.
Équations des Mouvements
Équations des Mouvements
Rotations: Mouvement Circulaire
2. Coordonnées sphériques:
Le système de coordonnées polaires peut être
aussi étendu à l'espace tridimensionnel
coordonnées sphériques (O : ρ ,
q,
φ ). La
notation r souvent utilisée pour le rayon, on
préfère ici ρ en accord avec les systèmes polaire
et cylindrique. La coordonnée angulaire
q
, la
longitude (angle mesuré depuis l'axe 𝑶𝑿 et
compris entre 0° et 360°) et φ la latitude, l'angle
depuis le plan équatorial (entre 90° et 90°).
Les trois coordonnées sphériques peuvent être
converties en coordonnées cartésiennes par :
x = ρ sin
f
cos
q
y = ρ sin
f
sin
q
z = ρ cos
f
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
16
Rotations: Mouvement Circulaire
1. Coordonnées cylindriques:
Le système de coordonnées polaires peut être
étendu à l'espace tridimensionnel de coordon-
nées cylindriques (O : ρ ,
q ,
z) en lui ajoutant une
troisième dimension z (aussi notée h ) qui
mesure la hauteur d'un point par rapport au plan
repéré par les coordonnées polaires ,
q
).
de la même manière que l'on étend le système
de coordonnées cartésiennes de deux (O: x , y) à
trois dimensions (O: x , y , z).
Les trois coordonnées cylindriques peuvent être
converties en coordonnées cartésiennes par :
x = ρ cos θ , y = ρ sin θ , z = h .
Équations des Mouvements
Équations des Mouvements
Vibrations: Mouvement Sinusoïdale
Le mouvement sinusoïdal est Un mouvement périodique qui se
reproduit identique à lui-même (1 cycle) pendant des intervalles
de temps T successifs égaux.
T = période (unité: seconde)
f = 1 / T = fréquence (unité : 1 Hertz = 1 cycle / sec)
2 Cas particulier de mouvements périodiques :
1. mouvement rectiligne sinusoïdal défini par l’équation:
x(t ) = xm Cos ( w0 . t + f ) x = A . cos (ω . t + ε)
1. mouvement circulaire sinusoïdal défini par l’équation:
θ (t ) = θm . cos (w0 . t + f )
ou xm et θm des amplitudes , w0 la pulsation et f la phase.
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
17
Rotations: Mouvement Circulaire
Repère polaire :
Ce système polaire est particulièrement utile dans les
situations la relation entre deux points est plus facile à
exprimer en termes d’angle et de distance , par exemple
le pendule.
Dans ce cas, le système des coordonnées cartésiennes, plus
familier, impliquerait dutiliser des formules
trigonométriques pour exprimer une telle relation.
Un point mobile dans un repère polaire est identifié par
une distance (ρ ) et un angle (
q
).
La distance est reportée sur la droite formant l'angle à
l'origine avec l'axe polaire, donnant ainsi le point.
Équations des Mouvements
Équations des Mouvements
Vibrations: Mouvement Sinusoïdale
Le mouvement sinusoïdal est un mouvement périodique
qui se reproduit identique à lui-même pendant des
intervalles de temps T successifs (1 cycle) égaux.
T = période (unité: seconde)
f = 1 / T = fréquence (unité : 1 Hertz = 1 cycle / sec)
2 Cas particuliers de mouvements périodiques
définis par les 2 équations suivantes :
1. mouvement rectiligne sinusoïdal :
x(t ) = xm Cos ( w0 . t + f )
2. mouvement circulaire sinusoïdal :
θ (t ) = θm . cos (w0 . t + f )
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
18
Rotations: Mouvement Circulaire
Repère polaire :
Ce système polaire est particulièrement utile dans
les situations la relation entre deux points est
plus facile à exprimer en termes d’angle et de
distance , par exemple le pendule.
Dans ce cas, le système des coordonnées
cartésiennes, plus familier, impliquerait d’utiliser
des formules trigonométriques pour exprimer
une telle relation.
Un point mobile dans un repère polaire est identif
par une distance (ρ ) et un angle (
q
).
La distance est reportée sur la droite formant
l'angle à l'origine avec l'axe polaire, donnant ainsi
le point.
Où:
x , θ : élongations ( écarts
par rapport à la position
d'équilibre)
xm , θm : amplitudes (
élongation maximum )
ω : pulsation = 2 . π . f
(ω . t + f) : phase
f : constante de phase
On peut aussi utiliser un sinus;
dans ce cas, la constante de
phase ε sera π/2 plus grande.
quelques cas particuliers de
mouvement oscillations:
1. Rectiligne: ressort,
2. circulaire: pendule simple
Équations des Mouvements
Équations des Mouvements
OpenGL: pendule simple
#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
19
Repère polaire : pendule simple
Ce système polaire est particulièrement utile dans
les situations la relation entre deux points est
plus facile à exprimer en termes d’angle et de
distance , par exemple le pendule.
θ (t ) = θm . cos (w0 . t + f )
Dans ce cas, le système des coordonnées
cartésiennes, plus familier, impliquerait d’utiliser
des formules trigonométriques pour exprimer
une telle relation.
x = ρm * sin(w0 . t + f )
y = ρm * cos(w0 . t + f )
Où: x , y : élongations , ρm : amplitudes
ω : pulsation = 2 . π . f ,
q =
(ω . t + f) , f : phase
float rot=0, alpha_degre=135 ,inc=1.0;
void drawSegment(
float x1,float y1,
float x2,float y2){
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glEnd();
}
void drawObjects(float x1,float
y1,double angle) {
double alpha_radian =
alpha_degre*3.14/180;
float m = tan(alpha_radian);
float y2 = 10 * cos( alpha_radian);
float x2 = 10 * sin( alpha_radian);
drawSegment(x1,y1,x2,y2);
}
void pendulum( void ){
if (alpha_degre>225) {
alpha_degre = 225;
inc = -inc;
}
if (alpha_degre<135) {
alpha_degre = 135;
inc = -inc;
}
alpha_degre += inc;
drawObjects(0,0,
alpha_degre);
// myUpdateFunc();
}
Équations des Mouvements
Équations des Mouvements
OpenGL: pendule simple
void display(void) {
glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-10,0,-30);
pendulum( );
glutSwapBuffers();
}
void keyboard(
unsigned char
key, int x, int y){
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
20
Repère polaire : pendule simple
Ce système polaire est particulièrement utile dans
les situations la relation entre deux points
est plus facile à exprimer en termes d’angle et
de distance , par exemple le pendule.
θ (t ) = θm . cos (w0 . t + f )
Dans ce cas, le système des coordonnées
cartésiennes, plus familier, impliquerait
d’utiliser des formules trigonométriques pour
exprimer une telle relation.
x = ρm * sin(w0 . t + f )
y = ρm * cos(w0 . t + f )
Où: x , y : élongations , ρm : amplitudes
ω : pulsation = 2 . π . f ,
q =
(ω . t + f) , f : phase
switch (key) {
case 27:
exit(0);
break;
}
}
void reshape (int w, int h) {
glViewport (0, 0,
(GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION
);
glLoadIdentity ();
gluPerspective (60,
(GLfloat)w / (GLfloat)h, 0.1,
100.0);
}
int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE);
glutInitWindowSize (1200, 800);
glutInitWindowPosition (0, 0);
glutCreateWindow ("A Pendulum");
glutDisplayFunc (display);
glutIdleFunc (display);
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutMainLoop ();
return 0;
}
Équations des Mouvements
Équations des Mouvements
Spécification du mouvement
Le paramètre ω est la fréquence angulaire, et θ
0
est la phase et k
est le coefficient de damping (ralentissement).
Programmation 2D/3D: INF 1483
Simulation et Animation
Cinématique
21
Spécification du mouvement
La méthode la plus directe pour définir une animation est
de spécifier les paramètres des transformations
géométriques (ex. translations, rotations, échelles, etc.),
qui peuvent être appliquées aux objets.
On peut aussi utiliser une fonction approximative
impliquant ces paramètres pour spécifier certains types
de mouvements.
Par exemple, le trajet d’une balle bondissante peut être
donné par:
A est l’amplitude initiale (hauteur de la balle).
kx
exAxy
= )sin()(
0
qw
Lois Physiques
Lois Physiques
Équation Physiques
Le mouvement des objets peut être décrit par des
équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
22
Équation Physiques
Établir un lien mathématique entre les circonstances
d’un mouvement et les causes qui influent sur lui, et
d’exploiter ce lien dans un but de prévision, c’est le rôle
de la dynamique physique.
La description de la dynamique du mouvement exige la
spécification des forces qui induisent la vitesse et
l’accélération des objets.
La description du comportement des objets en termes
d’influence de forces appliquées sur l’objet est appelée la
modélisation basée sur la physique.
Exemples de forces: gravitation, friction,
électromagnétique, etc.
Lois Physiques
Lois de Newton
La forme générale pour la deuxième loi de Newton du
mouvement peut être donnée par:
F est le vecteur de force et v est le vecteur de vitesse.
Comme la masse de l’objet est constante, cette équation
peut être réécrite en terme d’accélération a.
Par ailleurs, connaissant la position initiale et finale d’un
objet, ainsi que le type de mouvement subi, on peut
déduire les forces appliquées sur ce dernier.
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
23
Équation Physiques
Le mouvement des objets peut être décrit par des
équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
amvm
dt
d
F == )(
Lois Physiques
Lois de Newton
Prenons par exemple le cas d’une balle que l’on lâche depuis une
certaine hauteur. On pourrait calculer à l’avance le temps auquel
la balle touchera le sol.
finissons le problème:
la balle, de masse m, est située à une hauteur h0 du sol, et est lâchée
à l’instant t0 = 0.
A chaque instant t, la seule force exercée sur la balle est la force de
pesanteur mg (en négligeant les frottements dans l’air).
On peut donc écrire son poids par la fonction F(t):
F(t) = mg
On en déduit l’accélération de la balle
a(t) = F(t)/m = g (constante).
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
24
Équation Physiques
Le mouvement des objets peut être décrit par
des équations des lois physiques suivantes:
- Lois de newton pour le mouvement.
- Lois de Navier-Stokes pour les fluides.
- Lois de Maxwell pour l’électromagnétisme.
Lois Physiques
Lois de Navier-Stokes
les Fluides
Léquation de Navier et Stokes décrit le comportement de
fluides (liquides, gaz) en fonction de leur viscosité, de la
pression, de la température, du temps, des forces en
présence.
v la vitesse, ρ la densité du fluide, p la pression, and f
représente la force en présence.
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
25
Équation Physiques
Le mouvement des objets peut être décrit par
des équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
Lois Physiques
Lois de Navier-Stokes
les Fluides
Léquation décrit la conservation des moments dans un fluide et
dérive de la deuxième loi de Newton.
Elle peut être donnée:
Le membre à gauche de l’équation décrit l’accélération et il est
temps dépendant.
The membre droit de l’équation est une somme de toutes les forces
exercées ( gravité ou pression … ).
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
26
Équation Physiques
Le mouvement des objets peut être décrit par
des équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
Lois Physiques
Lois de Maxwell
Électromagnétisme
Les équations de Maxwell constituent les lois fondamentales de
l'électromagnétisme, avec l'expression de la force électromagnétique de
Lorentz.
Ces équations traduisent les différents théorèmes (Gauss, Ampère,
Faraday) qui régissaient l'électromagnétisme avant que Maxwell ne les
réunisse sous forme d'équations intégrales.
Ces équations montrent notamment qu'en régime stationnaire, les champs
électrique et magnétique sont indépendants l'un de l'autre, alors qu'ils ne
le sont pas en régime variable.
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
27
Équation Physiques
Le mouvement des objets peut être décrit par
des équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
Lois Physiques
Lois de Maxwell
Électromagnétisme
Le champ électromagnétique possède la propriété, très importante sur le
plan pratique, de pouvoir se propager dans le vide, c'est-à-dire en
l'absence de toute charge ou courant électrique, sous la forme d'ondes
électromagnétiques.
Dans le vide les équations de Maxwell s'écrivent en effet:
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
28
Équation Physiques
Le mouvement des objets peut être décrit par
des équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
Lois Physiques
Lois de Maxwell
Électromagnétisme
Relays and controls are essential to the safety and reliability of power
systems. For instance, they control the tripping of circuit breakers when
400 kilovolt lines are struck by lightning. In order to test this equipment,
we need to simulate in real time the dynamic behavior of the power
system in the presence of fast electromagnetic transients. We can now do
this thanks to the latest parallel architecture computers running the
simulation software. (authors)
Programmation 2D/3D: INF 1483
Simulation et Animation
Dynamique
29
Équation Physiques
Le mouvement des objets peut être décrit par
des équations des lois physiques suivantes:
Lois de newton pour le mouvement.
Lois de Navier-Stokes pour les fluides.
Lois de Maxwell pour l’électromagnétisme.
FIN DU CHAPITRE
FIN DU CHAPITRE
FIN DU CHAPITRE
Programmation 2D/3D: INF 1483
Equations des Mouvements des Objets
FIN DU CHAPITRE
30
FIN DU CHAPITRE
slide 31
Programmation 2D/3D: INF 1483
Contenu
Introduction
Objets et États Géométriques
Notions de Géométrie relies au
cours
Espace et coordonnées 2D/3D.
Géométrie: courbes, surfaces,
polygones, etc.
Transformations géométriques et
projections : translation, rotation,
etc.
Applications OpenGL
État de Rendu
Notions d‘Optique relies au
cours
Effet de lumière sur les objets,
rayons lumineux, camera.
Système de Formation
d’Images
État de Rendu Applications
OpenGL
Techniques d'animation et
simulation 2D/3D
Equations des mouvements
des objets.
Animation :
Temps Réel ,
Frame par Frame.
Applications OpenGL
Introduction à
l’Infographie
Introduction à OpenGL
Introduction
Introduction
En plus des changements de positions d’objets avec des
translations et des rotations, on parle aussi de variations
des tailles, de couleurs, de transparence et de textures
des surfaces d’objets.
On peut aussi générer des animations en changeant les
paramètres de la caméra (ex. position, orientation et la
distance focale).
Beaucoup d’effets réaliste exige des animations.
Il existe deux méthodes pour construire des animations qui
sont
1. l’animation en temps réel (real-time animation) et
2. l’animation frame par frame (frame-by-frame
animation).
Programmation 2D/3D: INF 1483
Simulation et Animation
Introduction
32
L’infographie concerne tous les aspects de
production d’images 2D/3D en utilisant
l’ordinateur.
De nos jours, on peut créer des images en
utilisant les techniques d’infographie, avec un
réalisme qui les rend indiscernables des images
d’objets réel.
L’infographie est surtout utilisée avec succès
dans les production de films au cinéma et les
jeux vidéo.
Lanimation par ordinateur se réfère en général
à une séquence temporelle de changements
dans une scène.
Animation Temps Réel
Animation Temps Réel
Une succession d’image affice à une cadence
suffisante fait croire à un mouvement fluide
24 images par seconde
En animation temps réel, les images sont calculées juste
avant d’être affichées
24 images par seconde => 1/24 = 41 ms maximum
pour calculer une image
En infographie, on essaye d’aller plus vite pour se
synchroniser avec le balayage de l’écran de 60 Hz →
60 images par seconde → 1/60 = 16 ms par image.
Le rendu des données en temps réel s'effectue directement
sur le périphérique d'affichage, contrairement à
l’animation précalculée le rendu est une vidéo.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
33
Dans une animation en temps réel, chaque étape de
l’animation est vue telle qu’elle a été créée. Dans ce cas,
l’animation doit être créée au même taux de
rafraichissement utilisé pour l’affichage.
Chaque image composant l'animation est rendue dans
l'instant qui précède son affichage.
La vitesse de rendu doit permettre une animation fluide.
Le rendu des données de l’animation temps réel est
immédiat.
Le temps de rendu en temps réel est imperceptible, il doit
être inférieur à la persistance rétinienne.
Mouvement en Temps Réel
Mouvement en Temps Réel
finissons le problème comme suit:
la balle: de masse m, est située à une hauteur h0 du sol, et est
lâchée à l’instant t0 = 0.
A chaque instant t, la seule force exercée sur la balle est la force
de pesanteur mg (en négligeant les frottements dans l’air). On
peut donc écrire
F(t) = mg
On en déduit l’accélération de la balle
a(t) = F(t)/m = g (constante).
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
34
Le terme temps réel signifie que le temps qui s’écoule a
une signification dans le programme.
Dans un processus temps réel, le programme continue de
s’exécuter, que l’utilisateur agisse ou non. Ceci permet
d’animer de façon réaliste les éléments du monde que l’on
représente.
On peut construire des animations en utilisant des
descriptions physiques de la cinétique du mouvement.
Prenons par exemple le cas d’une balle que l’on lâche
depuis une certaine hauteur. On pourrait calculer à
l’avance le temps auquel la balle touchera le sol.
Mais dans une simulation physique, on voudrait avoir la
position de la balle à chaque instant pour pouvoir
l’afficher en temps réel.
Mouvement en Temps Réel
Mouvement en Temps Réel
Ce temps est simplement
le temps que l’ordinateur a
mis pour calculer et
afficher la dernière image.
/* Nous sommes maintenant prêts
à effectuer les calculs pour
animer la scène. Supposons
que le problème de notre
ballefasse intervenir les valeurs
suivantes: */
#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
35
F(t) = mg
On en déduit l’accélération de la
balle
a(t) = F(t)/m = g (constante).
a(t + dt) = a( t ) = g
v(t+ dt) = v(t) + ∫a(t)*dt
h(t+dt) = h(t) + ∫v(t)*dt
Lorsque dt est petit on peut se
permettre l’approximation de
l’intégrale par sa version discrète.
On est donc capable de décrire à
chaque instant la nouvelle position
de la balle en fonction de la
précédente et du temps écoulé dt.
// La vitesse augmente de a(t).dt
pendant cette image
v += a * dt ;
// La balle tombe d’une distance v(t).dt
pendant cette image
h -= v * dt ;
// prendre en compte le fait que la
balle a touché le sol
if (0.0 < h) {
// Post re-paint request to activate display()
glutPostRedisplay();
// next timer call milliseconds later
glutTimerFunc( refreshMills ,
myUpdateFunc, 0);
} }
// Demande à glut de redessiner la fenêtre
graphique
glutPostRedisplay();
}
double h = 13.0 ; // m au dessus du sol
double m = 1.0 ; //la masse est 1 kg,
double v = 1.0 ; // Vitesse de la balle en m/s
// accélération de la pesanteur
const double g = 9.81 ;
// refresh interval in millisec
int refreshMills = 150.0;
// timer
/* Called back when timer expired [NEW]
*/
void myUpdateFunc(void) {
// Récupère le temps écoulé depuis la
dernière image
double dt = glutGet( GLUT_ELAPSED_TIME
)/1000000.00 ;// - timeprec;
if (dt >= 0.0 ) {
// Laccélération est uniquement due à g
double a = g ;
Mouvement en Temps Réel
Mouvement en Temps Réel
void reshape(int width , int hight ){
glViewport(0,0,width ,hight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.,1.,-1.,1.,1.5,20.);
}
GLUquadricObj *quadric;
void myinit(void) {
glShadeModel(GL_SMOOTH ) ;
quadric = gluNewQuadric();
gluQuadricTexture(quadric, GL_TRUE);
gluQuadricNormals(quadric,
GLU_SMOOTH);
}
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
36
F(t) = mg
On en déduit l’accélération de la
balle
a(t) = F(t)/m = g (constante).
a(t + dt) = a( t ) = g
v(t+ dt) = v(t) + ∫a(t)*dt
h(t+dt) = h(t) + ∫v(t)*dt
Dans une simulation numérique
non en temps réel, on fixe intervalle
dt à une valeur aussi petite que
possible pour gagner en précision ;
dans le temps réel, c’est la
puissance de la machine qui
détermine dt:
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode(
GLUT_RGBA|GLUT_DEPTH |
GLUT_DOUBLE );
glutInitWindowSize(800,800);
glutInitWindowPosition(150,150);
glutCreateWindow("Simulation");
myinit();
glutReshapeFunc(reshape);
// glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
// First timer call immediately
glutTimerFunc( 0, myUpdateFunc,
0 );
glutMainLoop();
return(0);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// balle
glTranslatef(0.0, h ,-21.53);
glColor4f(0,0,1,1);
gluSphere(quadric, 1.55 , 200, 100);
glFlush();
glutSwapBuffers();
}
Mouvement en Temps Réel
Mouvement en Temps Réel
Pendule:
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
37
plus la scène est complexe à animer et afficher, plus dt sera
grand, et plus la simulation sera approximative et
l’animation sera heurtée.
La raison pour laquelle on ne fixe pas à l’avance l’intervalle
dt est qu’on a priori aucune idée du temps que prendra le
calcul d’une image et, surtout, qu’on n’a aucune garantie
que ce temps restera constant :
plus il y a d’éléments à afficher, plus il augmentera.
On s’en rend bien compte dans certains jeux vidéos:
lorsqu’il y a une explosion, c’est le nombre d’images par
seconde qui diminue et non le temps lui-même qui se dilate.
De façon concrète, dt sera donné par un timer, qui est tout
simplement une fonction C++.
Mouvement en Temps Réel
Mouvement en Temps Réel
Pendule: Solution
θ (t ) = θm . cos (w0 . t + a )
le système des coordonnées
cartésiennes,
x = ρm * sin(w0 . t + a )
y = ρm * cos(w0 . t + a )
w0 = sqrt(g/l)
accl = -( g / length )* sin(alpha);
alpha += (omega + ( accl / 2) *dt ) * dt;
omega += accl * dt;
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
38
Pendule: Énoncé
On écarte de sa position d'équilibre une
masse ponctuelle suspendue à un fil
inextensible de longueur . On repère la
position de la masse par l'angle entre la
verticale et la direction du fil:
Etablir l'équation différentielle du mouvement en
utilisant :
Pendule: Solution
le principe fondamental de la dynamique
Mouvement en Temps Réel
Mouvement en Temps Réel
void pendulum( void ){
double dt = elappsed();
alpha +=(omega+dt*accl/2)*dt;
omega += accl * dt;
if (length * g * (1 - cos(alpha)) >= E) {
alpha = (alpha < 0 ? -1 : 1) * acos(1 - E /
length / g);
omega = 0;
}
accl = -( g / length )* sin(alpha);
double x = 10 * sin(alpha) ;
double y = -10 * cos(alpha);
drawObjects(x,y );
}
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
39
Pendule: Solution
θ (t ) = θm . cos (w0 . t + a )
Le système des coordonnées
cartésiennes,
x = ρm * sin(w0 . t + a )
y = ρm * cos(w0 . t + a )
w0 = sqrt(g/l)
accl =-(g/length)*sin(alpha);
alpha += (omega +
( accl / 2) *dt ) * dt;
omega += accl * dt;
#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
double accl, E;
double alpha, omega =
0;
double x ,y ;
#define length 5
#define g 9.8
glPushMatrix();
glTranslatef(sx, sy , 0.0);
gluSphere(quadric, radius ,200,100);
glPopMatrix();
}
void drawSegment(float x1,float y1,
float x2,float y2){
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glEnd();
}
void drawObjects(float x2,float y2 ){
float radius = 1.0;
drawCircle(radius,x2,y2);
drawSegment(0,0,x2,y2);
}
// timer
struct timeval tv;
double elappsed() {
struct timeval now;
gettimeofday(&now, 0);
int ret = ( now.tv_sec -
tv.tv_sec)*1000.0 +
now.tv_usec
tv.tv_usec;
tv = now;
return ret / 1.e6;
}
// refresh interval in millisec
int refreshMills = 150.0;
GLUquadricObj *quadric;
void drawCircle( float radius, float
sx, float sy)
{
glColor4f(0,0,1,1);
Mouvement en Temps Réel
Mouvement en Temps Réel
myinit();
glutReshapeFunc(reshape);
// glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutIdleFunc(display);
// timer call immediately
glutTimerFunc( 0 , myUpdateFunc, 0 );
glutMainLoop();
return(0);
}
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
40
Pendule: Solution
θ (t ) = θm . cos (w0 . t + a )
Le système des coordonnées
cartésiennes,
x = ρm * sin(w0 . t + a )
y = ρm * cos(w0 . t + a )
w0 = sqrt(g/l)
accl =-(g/length)*sin(alpha);
alpha += (omega +
( accl / 2) *dt ) * dt;
omega += accl * dt;
void myUpdateFunc( void)
{
alpha = 4 * atan2(1, 1) /
2.1;
E = length * g * (1 -
cos(alpha));
accl = -(g / length )*
sin(alpha);
omega = 0;
}
void myinit(){
//set background
color
glClearColor(0,0,0,0);
glShadeModel(GL_SM
OOTH ) ; //GL_FLAT);
void reshape(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (60, (GLfloat)w /
(GLfloat)h, 0.1, 100.0);
// glOrtho(0, w, h, 0, -1, 1);
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode(
GLUT_RGBA|GLUT_DEPTH |
GLUT_DOUBLE );
glutInitWindowSize(800,800);
glutInitWindowPosition(0,0);
glutCreateWindow("Simulation
Pendulum");
//prepare quadric for sphere
quadric = gluNewQuadric();
gluQuadricTexture(quadric,
GL_TRUE);
gluQuadricNormals(quadric,
GLU_SMOOTH);
}
void display(){
glClear(GL_COLOR_BUFFER_B
IT);
glMatrixMode(GL_MODELVIE
W);
glLoadIdentity();
glTranslatef(0,0,-30);
pendulum( );
glFlush();
glutSwapBuffers();
}
Mouvement en Temps Réel
Mouvement en Temps Réel
OpenGL: pendule simple
#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
Programmation 2D/3D: INF 1483
Simulation et Animation
Principes Physiques
41
Repère polaire : pendule simple
Ce système polaire est particulièrement utile dans
les situations la relation entre deux points est
plus facile à exprimer en termes d’angle et de
distance , par exemple le pendule.
θ (t ) = θm . cos (w0 . t + f )
Dans ce cas, le système des coordonnées
cartésiennes, plus familier, impliquerait d’utiliser
des formules trigonométriques pour exprimer
une telle relation.
x = ρm * sin(w0 . t + f )
y = ρm * cos(w0 . t + f )
Où: x , y : élongations , ρm : amplitudes
ω : pulsation = 2 . π . f ,
q =
(ω . t + f) , f : phase
float rot=0, alpha_degre=135 ,inc=1.0;
void drawSegment(
float x1,float y1,
float x2,float y2){
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glEnd();
}
void drawObjects(float x1,float
y1,double angle) {
double alpha_radian =
alpha_degre*3.14/180;
float m = tan(alpha_radian);
float y2 = 10 * cos( alpha_radian);
float x2 = 10 * sin( alpha_radian);
drawSegment(x1,y1,x2,y2);
}
void pendulum( void ){
if (alpha_degre>225) {
alpha_degre = 225;
inc = -inc;
}
if (alpha_degre<135) {
alpha_degre = 135;
inc = -inc;
}
alpha_degre += inc;
drawObjects(0,0,
alpha_degre);
// myUpdateFunc();
}
Cinématique du Mouvement
Cinématique du Mouvement
OpenGL: pendule simple
void display(void) {
glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-10,0,-30);
pendulum( );
glutSwapBuffers();
}
void keyboard(
unsigned char
key, int x, int y){
Programmation 2D/3D: INF 1483
Simulation et Animation
Principes Physiques
42
Repère polaire : pendule simple
Ce système polaire est particulièrement utile dans
les situations la relation entre deux points
est plus facile à exprimer en termes d’angle et
de distance , par exemple le pendule.
θ (t ) = θm . cos (w0 . t + f )
Dans ce cas, le système des coordonnées
cartésiennes, plus familier, impliquerait
d’utiliser des formules trigonométriques pour
exprimer une telle relation.
x = ρm * sin(w0 . t + f )
y = ρm * cos(w0 . t + f )
Où: x , y : élongations , ρm : amplitudes
ω : pulsation = 2 . π . f ,
q =
(ω . t + f) , f : phase
switch (key) {
case 27:
exit(0);
break;
}
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTI
ON);
glLoadIdentity();
gluPerspective (60,
(GLfloat)w / (GLfloat)h, 0.1,
100.0);
//glOrtho(0, w, h, 0, -1, 1);
}
int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE);
glutInitWindowSize (1200, 800);
glutInitWindowPosition (0, 0);
glutCreateWindow ("A Pendulum");
glutDisplayFunc (display);
glutIdleFunc (display);
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutMainLoop ();
return 0;
}
Schéma d’Exécution
Schéma d’Exécution
Deux étapes de la boucle de simulation se répète en
permanence:
1. Calcul et mise à jour: on détermine l’état suivant
du système selon l’état courant et le pas de temps
dt. Cest dans cette phase qu’interviennent les
équations de la simulation vue au dessus.
2. Affichage à l’écran (ou sur tout autre périphérique
de sortie): on envoie les données vers la carte
vidéo (ou un fichier du disque, ...). En théorie
aucun calcul n’est à effectuer dans cette phase.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
43
Globalement, les programmes de simulation fonctionnent
comme suit:
Dans un premier temps, on prépare les variables, on alloue
la mémoire, etc ...
Ensuite on commence la boucle de simulation.
Lois de Navier-Stokes pour les
Fluides
Lois de Maxwell pour
l’Électromagnétisme
La sécurité la reliabilité des lignes électriques de système à hautes
puissances peut être controlée par des tests sur les
équipements. Pour ceci on a besoin d’une simulation en temps
réel des comportment dynamique du systeme en presence de
foudre suite d’une transition d’energie éléctromagnétique.
Le calcule est basé sur les équations de Maxwell:
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
44
Utilisation des équations de Navier et Stokes, qui décrivent le
comportement de fluides (liquides, gaz) en fonction de leur viscosité,
de la pression, de la température, du temps, des forces en présence.
Lespace qui sera rempli par l’eau est discrétisé en un maillage 3D de
sommets. Au cours du temps, des vecteurs vitesse de fluide sont
calculés en chaque sommet du maillage grâce aux équations de
Navier-Stokes:
Des particules de fluide sont placées dans cette matrice 3D.
Leur position est donnée par interpolation des vecteurs vitesse.
Méthodes raster pour les animations
Méthodes raster pour les animations
.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel
45
Si on veut que l’animation soit générée en temps réel, on doit la
produire rapidement pour être affichée sur l’écran.
Dans ce cas, les objets créés en premiers vont être affichés pendant
tout le cycle de rafraichissement d’affichage et les objets générés à
la fin du cycle d’affichage vont disparaitre très rapidement.
Parfois, le temps de production d’un frame est supérieur au temps
de rafraichissement d’affichage, ce qui peut produire des
mouvements erratiques.
Une méthode pour réduire le problème est d’utiliser les double
tampons.
Introduction
Pas de temps réel.
Faire un programme d’animation pour un
film d’un million de frame:
Malheureusement la communication avec
l'écran se fait à intervalle (ou fréquence) fixe
( intervalle de rafraichissement d’écran )
qui est généralement de 60 images par
secondes (Hz), de ce fait il n'est pas possible
d'envoyer chaque image que la GPU à
terminé de calculer en temps réel.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
46
Dans une animation frame par frame, chaque
frame de l’animation est créé puis rangé
séparément. Ensuite, ces frames peuvent être
affichés sur un écran.
le fonctionnement simplifié d'une carte graphique
GPU:
pendant un jeu vidéo GPU, pour afficher une
image, doit faire de très nombreux calculs à
partir des données que le CPU lui envoie.
Lorsque GPU a terminé le calcul sur une image
elle stocke cette dernière sur une mémoire
appelée le frame buffer avant d'être affichée à
l'écran.
Cet mémoire contient par défaut deux images:
1. celle qui est actuellement envoyée à l'écran et
2. celle qui est actuellement en calcul par le GPU.
Dès qu'une nouvelle image est prête
dans le frame buffer le circuit qui
s'occupe de la connexion à l'écran
passe à cette image et libère
l'ancienne image pour que le GPU
puisse démarrer le calcul de la
prochaine,
L'écran peut être à n'importe quel
point de l'image précédente (à la
moitié, au trois quart, à quelques
lignes du début peu importe) lors du
passage à la nouvelle image,
Ainsi l'écran va afficher la nouvelle
image au point où en était la
dernière.
Perte de performance
Perte de performance
Faire un programme d’animation pour un film d’un
million de frame:
Lorsqu'une nouvelle image est prête dans le frame
buffer, on attend la fin de l'envoi de la dernière
image avant d'envoyer la nouvelle ainsi l'écran
n'affichera toujours qu'une seule image à la fois.
Ce qui va engendrer une perte de performance
Le GPU doit attendre que l'emplacement de
l'ancienne image soit libéré (c'est-à-dire qu'elle soit
complètement envoyée à l'écran) avant de pouvoir
commencer à travailler sur la prochaine image.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
47
Si on prend une photo de l'écran, on
verra qu'il y a deux images affichées à
l'écran:
1. un morceau de l'ancienne image avec
2. un morceau de la nouvelle.
Une ligne horizontale aussi appelée
déchirure apparait ce qui n'est vraiment
pas esthétique évidemment.
Ce phénomène peut être amplifié
lorsque le PC est assez rapide pour
calculer plusieurs images dans l'intervalle
d'un rafraichissement d'écran.
Ainsi on peux avoir plusieurs morceaux
d'images à l'écran et donc plusieurs
"déchirures".
Perte de performance
Perte de performance
Solution: Tampon (Buffer ) Double
ou même Triple:
Dans ce cas le frame buffer peut
contenir trois images:
1. celle actuellement affichée à l'écran,
2. la suivante prête à être affichée et
3. celle actuellement en calcul par le GPU.
Ainsi le GPU peut prendre de l'avance
car il n'a pas besoin d'attendre que
l'affichage de l'image en cour soit
terminé pour commencer ces calculs,
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
48
La construction d’une animation peut-
être une tâche complexe, surtout si:
plusieurs objets entrent en jeu,
chacun avec son mouvement.
Les films en général requièrent 24
frames/seconde et
les dispositifs graphiques sont rafraichis
60 fois/seconde.
Par exemple, une animation de 1 minute
va requérir 1440 = 24 x 60 frames.
Il y a d’autres tâches qui peuvent être
requises lors du développement d’une
animation: ex:
réglage des effets sonores,
synchronisation de l’image et du son,
etc.
Faire un programme d’animation pour un film
d’un million de frame:
Tampon (Buffer ) Double
Tampon (Buffer ) Double
une version modifier du programme qui affiche une animation graphique
smooth en utilisant double buffering peut être comme suit:
Cette méthode utilise deux tampons (buffer). Initialement, on crée un
frame dans l’un des tampons. Ensuite, pendant que l’écran est
rafraichi par ce tampon, on construit le prochain frame dans le second
tampon.
Ce processus alternatif continue le long de l’animation.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
49
Tampon (Buffer ) Double ou même Triple:
Dans ce cas le frame buffer peut contenir trois images:
1. celle actuellement affichée à l'écran,
2. la suivante prête à être affichée et
3. celle actuellement en calcul par le GPU.
Ainsi le GPU peut prendre de l'avance car il n'a pas
besoin d'attendre que l'affichage de l'image en cour soit
terminé pour commencer ces calculs,
Ainsi le programme:
Tampon (Buffer ) Double
Tampon (Buffer ) Double
Les librairies graphiques extension OpenGL implantant ce mécanisme
possèdent en général:
1. une fonction pour activer ce dernier et
2. une autre fonction pour échanger les tampons.
glutSwapBuffers()
Ainsi, si le temps de rafraichissement est 1/60 seconde et le temps de
génération d’un frame est 1/50 seconde, alors on doit afficher chaque
frame pendant 2 cycles (1 cycle sur tampon 1 et 1 cycle sur tampon 2 ) de
1/60 seconde chacun.
OpenGL doesn’t have a swap_the_buffers() command because the
feature might not be available on all hardware and, in any case, its
highly dependent on the window system. For example, if you are using
the X Window System and accessing it directly, you might use the
following GLX routine:
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
50
Tampon (Buffer ) Double ou même Triple:
Dans ce cas le frame buffer peut contenir trois images:
1. celle actuellement affichée à l'écran,
2. la suivante prête à être affichée et
3. celle actuellement en calcul par le GPU.
Ainsi le GPU peut prendre de l'avance car il n'a pas
besoin d'attendre que l'affichage de l'image en cour soit
terminé pour commencer ces calculs,
Ainsi le programme:
Animation Frame par Frame
Animation Frame par Frame
/* doubleBuffering: This
is a simple double
buffered program.
Pressing the left mouse
button rotates the
rectangle. Pressing the
middle mouse button
stops the rotation. */
#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdlib.h>
#include <stdio.h>
static GLfloat spin = 0.0;
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
51
Example 1-3 illustrates the use of
glutSwapBuffers() in drawing a
spinning square, as shown in Figure
1-3. This example also shows how to
use GLUT to control an input device
and turn on and off an idle function.
In this example, the mouse buttons
toggle the spinning on and off.
Example 1-3 Double-Buffered
Program: double.c
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(spin, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glRectf(-25.0, -25.0, 25.0, 25.0);
glPopMatrix();
glutSwapBuffers();
}
void spinDisplay(void){
spin = spin + 2.0;
if (spin > 360.0)
spin = spin - 360.0;
glutPostRedisplay();
}
void init(void){
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void reshape(int w, int h){
glViewport(0,0,(GLsizei)w,(GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void mouse(int button, int state, int x, int
y){
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(spinDisplay);
break;
case GLUT_MIDDLE_BUTTON:
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(NULL);
break;
default:
break;
}
}
/*Request double buffer
display mode. Register mouse
input callback functions */
int main(int argc,char** argv){
glutInit(&argc, argv);
glutInitDisplayMode
(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(250, 250);
glutInitWindowPosition(100,
100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
Design d’animations
Design d’animations
Construction d’une maquette (storyboard)
Une maquette est souvent un aperçu d’action qui définit une séquence de mouvement
comme une série d’événements de base.
Définition des objets
Un objet est défini en termes de sa forme (ex. polygones, splines, etc.) et de ses mouvements
potentiels. La définition d’objets est donnée pour chaque acteur de l’action.
Spécifications des frames clés (key-frames):
Un frame clé est un dessin détail de la scène à un certain temps t de la séquence. Dans un
frame clé, chaque objet prend une position correspondant au moment t du frame. Certains
frames clé sont choisis dans des positions extrêmes de l’action.
Génération des frames intermédiaires (in-between).
les autres (intermédiaires) entre deux frames clés sont espacés de sorte que l’intervalle soit
court. Les frames intermédiaires occupent les intervalles entre les frames clés. Le nombre
de frame d’une animation dépend du dispositif d’affichage.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
52
La construction d’une animation peut-
être une tâche complexe, surtout si
on garde l’historique et que
plusieurs objets entrent en jeu,
chacun avec son mouvement.
Une approche de base pour
construire une animation consiste
de 4 étapes suivantes:
1. Construction d’une maquette
(storyboard);
2. Définition des objets;
3. Spécifications des frames clés
(key-frames);
4. Génération des frames
intermédiaires (in-between).
Design d’animations
Design d’animations
Les films en néral requièrent 24 frames/seconde et les dispositifs
graphiques sont rafraichis 60 fois/seconde.
Typiquement, les intervalles de temps sont initialisés de sorte qu’il y a de
3 à 4 frames intermédiaires entre chaque paire de frames clés.
Par exemple, une animation de 1 minute va requérir 1440 = 24 x 60
frames, ce qui va nécessiter 288 = 1440 / 5 frames clés à développer.
Il y a d’autres tâches qui peuvent être requises lors du développement
d’une animation: ex. réglage des effets sonores, synchronisation de
l’image et du son, etc.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
53
La construction d’une animation peut-être
une tâche complexe, surtout si on garde
l’historique et que plusieurs objets entrent
en jeu, chacun avec son mouvement.
Une approche de base pour construire une
animation consiste de 4 étapes suivantes:
1. Construction d’une maquette
(storyboard);
2. Définition des objets;
3. Spécifications des frames clés
(key-frames);
4. Génération des frames
intermédiaires (in-between).
Design d’animations
Techniques traditionnelles d’animations
Système à frames clés pour l’animation
Les animateurs de films utilisent en général une variété de
méthodes pour développer des animations, telles que les
déformations d’objets, l’anticipation du mouvement, le focus sur
des actions, etc.
Une des méthodes importantes pour simuler les effets
d’accélération des objets non-rigides est appelée méthode
squash et stretch.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
54
La construction d’une animation peut-être une tâche
complexe, surtout si on garde l’historique et que
plusieurs objets entrent en jeu, chacun avec son
mouvement.
Une approche de base pour construire une animation
consiste de 4 étapes suivantes:
1. Construction d’une maquette (storyboard);
2. Définition des objets;
3. Spécifications des frames clés (key-frames);
4. Génération des frames intermédiaires (in-
between).
Design d’animations
Techniques traditionnelles d’animations
Système à frames clés pour l’animation
Lobjet s’élonge quand il accélère et il s’aplatit quand il
touche la terre.
Une autre technique pour avoir les effets d’accélération
est le timing qui se fère à l’espacement entre frames.
Un objet lent est représenté par des frames moins
espacés et vice-versa.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
55
La construction d’une animation peut-être une tâche
complexe, surtout si on garde l’historique et que
plusieurs objets entrent en jeu, chacun avec son
mouvement.
Une approche de base pour construire une animation
consiste de 4 étapes suivantes:
1. Construction d’une maquette (storyboard);
2. Définition des objets;
3. Spécifications des frames clés (key-frames);
4. Génération des frames intermédiaires (in-
between).
Design d’animations
Techniques traditionnelles d’animations
Système de frames clés
En général, les trajectoires des objets peuvent être
définies par une description cinétique du
mouvement, et ceci par un ensemble de courbes
spline.
Une courbe spline est une fonction polynomiale
par morceaux définie sur un intervalle [a,b]
divisé en sous intervalles [t , t ] tels que:
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
56
La construction d’une animation peut-être une tâche
complexe, surtout si on garde l’historique et que
plusieurs objets entrent en jeu, chacun avec son
mouvement.
Une approche de base pour construire une animation
consiste de 4 étapes suivantes:
1. Construction d’une maquette (storyboard);
2. Définition des objets;
3. Spécifications des frames clés (key-frames);
4. Génération des frames intermédiaires (in-
between).
Design d’animations
Techniques traditionnelles d’animations
Système de frames clés
La trajectoire peut être spécifiée aussi avec les
forces physiques qui agissent sur l’objet.
Avec des animations complexes, la forme d’un
objet peut changer au cours du temps (ex.
vêtements, caractéristiques faciales, etc.).
Ces changements de forme doivent être pris en
compte dans le développement des frames
intermédiaires d’une animation.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
57
La construction d’une animation peut-être une tâche
complexe, surtout si on garde l’historique et que
plusieurs objets entrent en jeu, chacun avec son
mouvement.
Une approche de base pour construire une
animation consiste de 4 étapes suivantes:
1. Construction d’une maquette (storyboard);
2. Définition des objets;
3. Spécifications des frames clés (key-frames);
4. Génération des frames intermédiaires (in-
between).
Morphing d’objets
Morphing d’objets
On note dans l’exemple précédent qu’une ligne droite
dans le frame clé k est transformée en 2 lignes dans
le frame k+1. On peut utiliser une interpolation
linéaire pour ajouter un sommet dans le frame clé k.
De la même manière, on peut ajouter un sommet
dans les frames intermédiaires.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
58
La transformation de la forme d’un objet d’un état vers
un autre s’appelle le morphing.
Ayant deux frames clés un objet est représenté
avec deux ensembles différents de segments, on
peut, en premier lieu, ajuster la spécification de
l’objet dans l’un des frames pour avoir le même
nombre d’arêtes de polygones.
Morphing d’objets
Morphing d’objets
Légalisation du nombre de segments est faite comme suit:
1. Diviser N
e
segments dans le frame L
min
en N
s
+1 sections.
2. Diviser les segments restant dans le frame L
min
en N
s
sections.
Ex: soit L
k
= 15 segments, et L
k+1
= 11 segments.
Dans ce cas, N
e
= 4 segments et N
s
= 1 groupe de 11 segments dans
L
k
Légalisation du nombre de segments est:
1- on doit diviser N
e
/(N
s
+ 1) = 4 / 2 = 2 segments dans le frame
k+1 en 2.
on doit diviser 4 segments dans le frame k+1 en 2.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
59
On peut définir des règles pour l’ajout de segments et de
sommets lors de la transformation d’objets. En premier, on
doit égaliser le nombre de segments entre les deux frames.
Soit L
k
et L
k+1
le nombre de segments dans les frames clés
k et k+1, respectivement. Le nombre maximal et minimal
qui sont à égaliser sont calculés par:
En deuxième lieu, on doit calculer les quantités suivantes:
),,max(
1max
=
kk
LLL
).,min(
1min
=
kk
LLL
( )
,mod
minmax
LLN
e
=
=
min
max
L
L
intN
s
Morphing d’objets
Morphing d’objets
Dans l’exemple suivant, on a rajouté un point au triangle du
frame clé k pour égaliser le quadrilatéral du frame clé
k+1. Un frame intermédiaire est obtenu par interpolation
linéaire.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
60
On peut aussi utiliser le nombre de sommets, a la place des
segments, pour le même calcul comme suit.
Soit V
k
et V
k+1
le nombre de sommets dans les frames clés k
et k+1. On aura:
Légalisation du nombre de segments est fait comme suit:
1. Ajouter N
p
points à N
ls
segments dans le frame V
min
.
2. Ajouter N
p
-1 points pour les segments restant dans le
frame V
min
.
),,max(
1max
=
kk
VVV
).,min(
1min
=
kk
VVV
=
1
1
min
max
V
V
intN
p
Simulation de l’accélération
Simulation de l’accélération
Lorsque le mouvement d’un objet est sans accélération, on
utilise des intervalles d’espacements égaux entre les
frames intermédiaires.
Par exemple, si nous avons n frame intermédiaires et que
les frames clés sont à t
1
et t
2
, alors l’intervalle entre les
frames clés est divisé en n+1 intervalles et l’espacement
entre frames sera:
Le temps du j-ième frame intermédiaire sera
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
61
Les techniques d’approximation par courbe sont souvent
utilisées pour spécifier les chemins d’une action.
Ayant les positions d’un objet dans les frames clés, on peut
les rassembler par des trajectoires liaires ou non-
linéaires.
1
12
=
n
tt
t
.,,
1
n1,2,3,...jtjttB
j
==
Animation Frame par Frame
Animation Frame par Frame
Préparation:
la succession des sprites composent l'animation.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
62
Dans un jeu 2D, un personnage ou tout autre objet
graphique se déplaçant à l’écran animé ou non est
appelé un sprite.
Un sprite est une image que l'on souhaite afficher
sur l'écran.
Pour animer un sprite on utilise une succession
d'image assez proche qu'on affiche l'une après
l'autre pour donner l’illusion du mouvement.
Une approche de base pour construire une
animation consiste de 4 étapes suivantes:
Construction d’une maquette (storyboard);
Définition des objets;
3. Spécifications des frames clés (key-frames);
4. Génération des frames intermédiaires (in-
between).
1. Construction d’une
maquette (storyboard)
Une telle image est un tableau
de sprites, SpriteSheet.
2. Définition des objets;
En observant ce spritesheet
on remarque que chaque ligne
correspond à une direction.
Animation Frame par Frame
Animation Frame par Frame
la.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
63
Dans un jeu 2D, un personnage ou tout autre objet
graphique se déplaçant à l’écran animé ou non est
appelé un sprite.
Un sprite est une image que l'on souhaite afficher
sur l'écran.
Pour animer un sprite on utilise une succession
d'image assez proche qu'on affiche l'une après
l'autre pour donner l’illusion du mouvement.
Une approche de base pour construire une
animation consiste de 4 étapes suivantes:
Construction d’une maquette (storyboard);
Définition des objets;
Spécifications des frames clés (key-frames);
Génération des frames intermédiaires (in-
between).
3. Spécifications des frames clés (key-
frames);
De ces 4 lignes on va définir les directions
(de 0 à 3).
En ne prenant que la première colonne.
Les images affichent le personnage
immobile.
4. Génération des frames
intermédiaires (in-between).
On utilisera judicieusement les animations
de 0 à 3 pour cela.
Les autres cellules de chaque ligne servent
quand à elles aux animations de
déplacement, numéroter de 4 à 7.
Ainsi si le numéro X correspond à une
image immobile dans une direction,
le numéro X+4 correspondra à l'animation
de marche dans la même direction.
Animation Frame par Frame
Animation Frame par Frame
Initialisation
Commençons par définir les variables représentants notre personnage.
la position de notre personnage avec des coordonnées (x,y)
arbitrairement à (300, 300).
la direction est représenté par un entier dont le domaine de valeur
va de 0 à 3.
un booléen pour indiquer si le personnage se déplace ou non.
nous avons 8 animations, représentées par un tableau (array)
Animation.
Les objets sont crées, il nous faut encore les initialiser, et pour cela
on va compléter la méthode « init() ».
Un tableau de sprite est représenté par la classe SpriteSheet,
il suffit d'instancier cette classe en lui donnant en argument le nom
du fichier et les dimensions des cellules soit 64x64 dans ce cas.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
64
Initialisation
Voici l'exemple du code pour
l'animation :
private float x = 300, y = 300;
private int direction = 0; // 0 à 3
private boolean moving = false;
private Animation[] animations =
new Animation[8];
public void init( ) {
SpriteSheet spriteSheet = new
SpriteSheet((
"sprites/character.png« , 64, 64 );
}
Animation Frame par Frame
Animation Frame par Frame
Initialisation
Ensuite on initialise les animations:
en les composants sprite ( frame)
par sprite à l'aide du tableau de
sprite
en indiquant le temps d'affichage
en milliseconde de chaque
sprite. Soit 100ms.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
65
Initialisation
,
private float x = 300, y = 300;
private int direction = 0;
private boolean moving = false;
private Animation[] animations = new Animation[8];
public void init( ) {
SpriteSheet spriteSheet = new SpriteSheet(( "sprites/character.png", 64, 64);
Animation animation = new Animation();
animation.addFrame(spriteSheet.getSprite(1, 1), 100);
animation.addFrame(spriteSheet.getSprite(2, 1), 100);
animation.addFrame(spriteSheet.getSprite(3, 1), 100);
animation.addFrame(spriteSheet.getSprite(4, 1), 100);
animation.addFrame(spriteSheet.getSprite(5, 1), 100);
animation.addFrame(spriteSheet.getSprite(6, 1), 100);
animation.addFrame(spriteSheet.getSprite(7, 1), 100);
animation.addFrame(spriteSheet.getSprite(8, 1), 100);
this.animations[5] = animation;
Animation Frame par Frame
Animation Frame par Frame
private Animation
loadAnimation(SpriteSheet
spriteSheet, int startX, int
endX, int y) {
Animation animation =
new Animation();
for (int x = startX; x <
endX; x++) {
animation.addFrame(sprite
Sheet.getSprite(x, y), 100);
}
return animation;
}
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
66
,
Initialisation
Ensuite on initialise les
animations:
pour chaque animation.
private float x = 300, y = 300;
private int direction = 0;
private boolean moving = false;
private Animation[] animations = new Animation[8];
public void init() {
SpriteSheet spriteSheet = new SpriteSheet((
"sprites/character.png", 64, 64);
Animation animation = new Animation();
animation.addFrame(spriteSheet.getSprite(1, 1), 100);
animation.addFrame(spriteSheet.getSprite(2, 1), 100);
animation.addFrame(spriteSheet.getSprite(3, 1), 100);
animation.addFrame(spriteSheet.getSprite(4, 1), 100);
animation.addFrame(spriteSheet.getSprite(5, 1), 100);
animation.addFrame(spriteSheet.getSprite(6, 1), 100);
animation.addFrame(spriteSheet.getSprite(7, 1), 100);
animation.addFrame(spriteSheet.getSprite(8, 1), 100);
this.animations[5] = animation;
this.animations[0] =
loadAnimation(spriteSheet, 0, 1, 0);
this.animations[1] =
loadAnimation(spriteSheet, 0, 1, 1);
this.animations[2] =
loadAnimation(spriteSheet, 0, 1, 2);
this.animations[3] =
loadAnimation(spriteSheet, 0, 1, 3);
this.animations[4] =
loadAnimation(spriteSheet, 1, 9, 0);
this.animations[5] =
loadAnimation(spriteSheet, 1, 9, 1);
this.animations[6] =
loadAnimation(spriteSheet, 1, 9, 2);
this.animations[7] =
loadAnimation(spriteSheet, 1, 9, 3);
}
Animation Frame par Frame
Animation Frame par Frame
Affichage
On utilise la méthode drawAnimation() de l'objet _ g_
de la méthode render().
Il faut déterminer l'animation à afficher,
revenons pour cela à la définition du tableau
d'animation:
de 0 à 3 les postures d’arrêts, et de 4 à 7
les animations de déplacement dans le
même ordre que la direction.
Donc il suffit d'ajouter 4 à la direction si le
personnage se déplace.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
67
Affichage
public void render( ) {
g.setColor(new Color(0, 0, 0, .5f));
g.fillOval(x - 16, y - 8, 32, 16);
g.drawAnimation(
animations[direction + (moving ? 4 : 0)],
x-32, y-60);
}
Animation Frame par Frame
Animation Frame par Frame
Déplacement
A l'appui des touches du clavier
[HAUT] [BAS] [GAUCHE] [DROITE]
on va enregistrer la nouvelle direction et indiquer
grâce au booléen que le personnage se déplace.
Pour cela on va redéfinir la méthode keyPressed().
Quand on relâchera une de ces touches
keyReleased() on arrêtera le déplacement en
repassant le booléen à faux.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
68
Déplacement
Il faut ajouter de nouvelle fonction au
clavier pour permettre le
déplacement du personnage.
public void keyPressed(int key, char c) {
switch (key) {
case Input.KEY_UP: this.direction = 0;
this.moving = true;
break;
case Input.KEY_LEFT: this.direction = 1;
this.moving = true;
break;
case Input.KEY_DOWN: this.direction = 2;
this.moving = true;
break;
case Input.KEY_RIGHT: this.direction = 3;
this.moving = true;
break;
}
}
public void keyReleased(int key, char c) {
this.moving = false;
}
Animation Frame par Frame
Animation Frame par Frame
la méthode update( ):
Cette méthode est pour mettre à jour l'état du jeu en
fonction de votre logique de jeux et du temps écoulé.
Il est très important de prendre en compte le temps écoulé
pour adapter votre jeu à la vitesse de l'ordinateur de
l'utilisateur.
Cette information vous est donnée à l'aide de la
variable dt.
Ici on peut fixer arbitrairement la vitesse à v= 0.1f.
Le personnage bouge.
Il reste encore à traiter autres problèmes de déplacement
Le personnage traverse les murs.
il passe dessus les arbres,
il marche sur l'eau etc.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
69
Mettre à jour l'état du jeu
public void update(int dt) {
if (this.moving) {
switch (this.direction) {
case 0:
this.y -= v* dt;
break;
case 1:
this.x -= v* dt;
break;
case 2:
this.y += v* dt;
break;
case 3:
this.x += v* dt;
break;
}
}
}
Simulation de l’accélération
Simulation de l’accélération
On peut obtenir une taille croissante de l’intervalle avec la
fonction suivante:
Entre les n frames intermédiaires, le temps du j-ième
frame sera calculé comme suit:
∆t est l’intervalle entre deux frames clés.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
70
Lorsque l’accélération nest pas nulle (cas des dessin animées,
etc.), il est cessaire de modéliser le début (accélération)
et la fin (décélération) du mouvement par des fonctions
splines ou trigonométriques.
Pour modéliser l’accélération, on voudrait que le temps
d’espacement entre les frames soit croissant pour montrer
le changement de position rapide de l’objet.
2
0),cos(1
qq
nj
n
j
tttB
j
,...,2,1,
)1(2
cos1
1
=
=
Simulation de l’accélération
Simulation de l’accélération
On peut aussi modéliser la décélération par la fonction
sinus. Il s’en suit que le temps d’un frame intermédiaire j
et donné par:
∆t est l’intervalle entre deux frames clés.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
71
La figure suivante montre les courbes d’accélération et de
l’espacement entre frames lorsque n = 5:
nj
n
j
tttB
j
,...,2,1,
)1(2
sin
1
=
=
Animation de Caractères: Animation d’objets
articulés
Animation de Caractères: Animation d’objets
articulés
Par exemple, si une des épaules bouge, elle entraine
avec elle le mouvement de toute la main. Différents
types de mouvements (ex. marcher, courir, sauter) sont
associés à des mouvements des articulations et
membres.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
72
Créer des animations réalistes d’objets simples est assez
facile, contrairement aux objets complexes (ex. humains,
animaux, etc.).
Un technique pour animer des objets complexes (ex.
humains, insectes, etc.) est d’utiliser des modèles
articulés, qui sont des structures hiérarchiques
composées d’un ensemble de liens rigides connectés via
des articulations.
Les points charnières sont placées dans les épaules, la
hanche, les genoux et d’autres point du squelette.
Animation de Caractères: Capture du
mouvement
Animation de Caractères: Capture du mouvement
Cette technique requiert de placer des marqueurs sur des
positions critiques du corps de l’acteur, telles que les
mains, les genoux, etc., (sur le corps directement ou bien
sur une combinaison).
Lacteur est ainsi fil en mouvement, et des techniques
de traitement d’images sont utilisées pour avoir la
position spatiale des marqueurs.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
73
Une autre alternative pour déterminer le mouvement d’un
caractère est d’enregistrer le mouvement d’un acteur
humain et l’utiliser pour animer un caractère.
Cette technique s’appelle capture de mouvement (motion
capture). Le caractère animé effectuera le même
mouvement que l’acteur humain.
Animation de Caractères: Capture du
mouvement
Animation de Caractères: Capture du mouvement
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
74
On peut aussi avoir des marqueurs optiques, et la position de
ces derniers est estimée par la réflexion de la lumière vers
une ou plusieurs caméras.
Mouvements Périodiques
Mouvements Périodiques
Roue tournant à 18 tours /seconde
5 premiers frames à un taux de 24 frames /seconde.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
75
Lorsqu’on construit une animation avec un motif de
mouvement répétitif (ex. roue de voiture, etc.), on doit
échantillonner le mouvement adéquatement pour le
représenter correctement.
Autrement dit, le mouvement doit être synchronisé avec le
taux de génération de frames pour qu’un nombre suffisant
de frames soit affichés par cycle pour montrer le vrai
mouvement.
Un exemple de mouvement sous-échantillonné est illustré
par la roue de wagon qui apparait tourner dans la
mauvaise direction.
Cinéma
Animation
Mouvement = dessin + échange
Tant que la séquence n’est pas terminée
{
1. vider l’écran
2. dessiner la prochaine image
3. échanger les tampons
}
les objets sont toujours affichés
Variations fréquentielles discontinues
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Temps Réel ou Frame par Frame
76
Mouvement = dessin + échange
Tant que la séquence n’est pas terminée
{
1. vider l’écran
2. dessiner la prochaine image
3. attendre 1/24ème de secondes
}
Problèmes si temps de dessin trop
important (objets fantômes)
Variations fréquentielles continues
Fonctions GLUT d’animation
Fonctions GLUT d’animation
Le double tampon (tampon arrière et
tampon devant) est activé par la
fonction:
glutInitDisplayMode(GLUT_DOUBLE);
Alors qu’un des tampon sert au
rafraichissement de l’affichage, l’autre
servira à préparer le prochain frame.
Léchange des deux tampons se fait
par la fonction:
glutSwapBuffers();
Programmation 2D/3D: INF 1483
Simulation et Animation
Simulation OpenGL
77
La gestion de timers avec Glut se fait avec la
fonction:
void glutTimerFunc ( unsigned int msecs,
void (*func)(int value), value);
Le premier argument de la fonction glutTimerFunc est
le nombre de millisecondes avant que la fonction de
rappel soit appelée. Ce nombre de millisecondes est un
minimum, GLUT appelant la fonction de rappel dès
que possible après l'expiration du délai.
Le deuxième argument est un pointeur vers la fonction
de rappel.
Le troisième argument est la valeur du paramètre de la
fonction de rappel.
Animation OpenGL
Une animation continue
implantée dans la fonction
fonctAnimation est mise
en marche par la fonction:
glutIdleFunc(fonctAnimation)
;
Fonctions GLUT d’animation
Fonctions GLUT d’animation
Fonctions de la souris
Le contrôle de la souris est prise en charge par
la fonction:
glutMouseFunc(mouseFunction);
mouseFunction est la fonction de la forme:
mouseFunction(
GLint boutton, GLint action,
GLint xS, GLint ys );
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
78
Fonctions de la souris
Il est souvent intéressant, voire indispensable
parfois, de spécifier les données graphiques de
manière interactive (ex. changement de la
position de la caméra ou d’un objet, etc.).
On peut souhaiter aussi changer les paramètres
d’une animation via une interface graphique ou
un menu permettant la sélection d’actions ou
de changements.
Il y a plusieurs types de données qui peuvent
être utilisées par un programme graphique. Il
existe plusieurs méthodes pour assurer
l’interactivité (ex. les menus, les icones, la souris
etc.).
Fonctions de la souris
Le paramètre bouton prend une des
valeurs suivantes:
GLUT_LEFT_BUTTON,
GLUT_MIDDLE_BUTTON
GLUT_RIGHT_BUTTON,
GLUT_DOWN, GLUT_UP.
Les valeurs de xS et yS donnent la
position de la souris.
Animation OpenGL
Animation OpenGL
Fonctions du clavier
Le contrôle des entrées du clavier se fait
par la fonction suivante:
glutKeyboardFunc(clavierFonction);
la clavierFonction est une fonction
de la forme:
clavierFonction(
GLint touche, GLint xSouris,
GLint ySouris);
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
79
Fonctions de la souris
Il existe aussi la fonction suivante qui invoque
une fonction lorsque la souris subit un
mouvement:
glutMotionFunc(fonctionMotion);
la fonctionMotion est une fonction de la
forme:
fonctionMotion(GLint x, GLint y);
Fonctions du clavier
Le paramètre touche prend la valeur
d’un caractère ou le code ASCII
correspondant.
Les paramètres xSouris et ySouris
prennent les coordonnées de la souris
au moment la touche du clavier est
pressée.
Animation OpenGL
Animation OpenGL
Fonctions du clavier
Le paramètre touche prend la valeur d’un
caractère spécial qui est une constante
OpenGL, telles que:
- GLUT_KEY_F1, , GLUT_KEY_F12 //
pour les fonctions.
GLUT_KEY_RIGHT, GLUT_KEY_UP //
pour les flèches.
etc.
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
80
Fonctions du clavier
Pour les caractères de fonction (les flèches,
contrôles, etc.), on peut utiliser la fonction:
glutSpecialFunc(SpecialKeyFonction);
la SpecialKeyFonction est une fonction de la
forme:
SpecialKeyFonction (
GLint touche,
GLint xSouris, GLint ySouris);
Fonctions de menus d’OpenGL
Animation OpenGL
Animation OpenGL
Création d’un menu GLUT
Une fois que la fonction de menu (qui
sera appelée lorsque l’item du menu est
sélectionné) est définie, on doit
spécifier les options qui seront listées
dans le menu.
On fait cela par une rie dappel qui liste
le nom et la position de chaque item.
Les appels sont de la forme:
glutAddMenuEntry(CharString,
menuItemNombre);
la CharString spécifie la chaine de
caractère à afficher et
menuItemNombre donne la position de
cette entrée dans le menu.
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
81
Fonctions de menus dOpenGL
Création d’un menu GLUT
Un menu GLUT pop-up peut être créé avec la
fonction suivante:
glutCreateMenu(menuFonction);
la menuFonction est le nom d’une fonction à
appeler lorsqu’une entrée du menu est
sélectionnée:
menuFonction(GLint menuNombre);
Le paramètre menuNombre correspond à une
opération (option) du menu qui peut être
sélectionnée.
Lorsqu’un menu est créé, il est associé à la
fenêtre courante d’affichage.
Fonctions de menus d’OpenGL
Exemple d’un menu avec deux options:
glutCreateMenu(menuFonc);
glutAddMenuEntry(Item 1”, 1);
glutAddMenuEntry(Item 2”, 2);
On peut spécifier aussi le bouton de la
souris qui doit être utilisé pour
sélectionner les options du menu. Ceci
est accompli par la fonction:
glutAttachMenu(boutton);
la boutton prend des constante
OpenGL:
- GL_LEFT_BUTTON,
- GL_RIGHT_BUTTON,
- GL_MIDDLE_BUTTON,
Animation OpenGL
Animation OpenGL
Gestion de plusieurs menus GLUT
On détruit un menu par la fonction:
glutDestroyMenu(menuID);
Création de sous-menus GLUT
Un sous-menu peut être associé à un
menu principal en le créant d’abord par
la fonction glutCreateMenu. On doit
ensuite ajouter le sous-menu comme
un option dans la menu principal:
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
82
Fonctions de menus dOpenGL
Gestion de plusieurs menus GLUT
On peut créer plusieurs menus pour une seule
fenêtre d’affichage. Pour un menu créé, on peut
lui assigner un identificateur (ex. 1, 2, , etc.),
comme suit:
menuID = glutCreateMenu(FonctionMenu);
Le menu nouvellement créé devient le menu
courant de la fenêtre. Pour activer le menu pour
la fenêtre courante d’affichage, on utilise la
fonction:
glutSetMenu(menuID);
Création de sous-menus GLUT
Example:
sousMenuID =
glutCreateMenu(
FonctionSousMenu);
glutAddMenuEntry(“Item1”, 1);
menuID =
glutCreateMenu(
FonctionMenu);
glutAddMenuEntry(“Item 1”, 1);
glutAddMenuEntry(Item n”,
sousMenuID);
83
On peut détacher le bouton de souris activant les options d’un menu
par la fonction:
glutDetachMenu(boutton);
boutton prend une des valeurs de boutons de la souris.
Finalement, on peut éliminer une option d’un menu via la fonction
suivante:
glutRemouveMenuItem(ItemNombre);
ItemNombre est le numéro de l’item dans le menu courant.
Autres fonctions
FIN DU CHAPITRE
FIN DU CHAPITRE
FIN DU CHAPITRE
FIN DU CHAPITRE
84
FIN DU CHAPITRE
Simulation et Animation
Programmation 2D/3D: INF 1483
85
Un environnement de réalité virtuelle typique est illustré dans la figure
suivante:
En utilisant des gants tactiles et des lunettes stéréoscopiques, un sujet
peut être en interaction avec l’environnement virtuel et naviguer à
l’intérieur.
Environnements de réalité virtuelle
Les formats de l’animation temps réel comportent des données 3D (géométrie,
texture, animation) et un scénario pré-défini ou interactif (scripts). La 3D temps réel
permet de ce fait un grand degré d'interactivité: possibilités d'immersion, de
contrôle d'animation, d'interactivité avec la scène 3D... La 3D temps réel est au cœur
d'applications telles que la visite virtuelle, la simulation, la visualisation et la...
slide 86
Animation
Animation Temps Réel
Animators usually create a motion by defining a number of "key frames," or well-known positions that determine
the complete motion in their package of choice. For a 50-frame sequence, this might involve setting
keyframes at frame 0, 15, 30, and 45. The character will then loop through the sequence, using keyframes and
interpolation to derive all the remaining frames. This is a timesaver for the artists because they can determine
a complex motion using just a few directions. A two-second cycle (which would total 50 frames) can often be
described within 5 to 10 keyframes.
Taking advantage of this property is the core of keyframe animation. We will only store these keyframes as
specified in the modeling package. This is clearly a memory savings from traditional frame animation. The
animation engine will take care of computing any in-between frame at runtime.
One solution to raise the quality is to make sure your keyframes are not too far apart, thus reducing the
blockiness of the motion. A popular mathematical lemma states that any continuous curve can be reduced to
a straight line if the interval is small enough,
On the other hand, linear interpolation can sometimes yield poor results. Most
animation packages use more powerful interpolators (Bézier, Hermite, and
so on), so when we see the results with just linear interpolation applied,
some motions tend to look robotic and unnatural.
slide 87
Simulation et Animation
Animation Frame par Frame
The coding idea is pretty straightforward: Store the animation at a high sampling rate (such as 25 fps), and then
use an analyzer to find out which frames can be discarded with little or no effect on the results. This can be
achieved in an iterative manner, discarding the least significant frame at each step until we reach a limit error
level. By doing this, we can ensure that our resulting animation is well suited for real-time display, keeping the
best possible quality.
Imagine that you are creating a character for an action title. The character must perform a variety of animations
For example, he must be able to stand still, walk, and run (both forward and backward). He also needs to jump,
crouch, and shoot three different weapons. A first, superficial analysis reveals we will be using 10 different
animation cycles:
Stand still
Walk forward
Walk backward
Run forward
Run backward
Jump
Crouch
Shoot first weapon
Shoot second weapon
Shoot third weapon
slide 88
Simulation et Animation
Animation Frame par Frame
the lead designer comes along and suggests allowing the player to shoot while moving for increased realism.
if you do the math, you will discover you don't need 10 cycles anymore but 28. You have seven "poses" (stand,
walk forward, walk back, run forward, run back, jump, and crouch) and four "actions" (do nothing, and shoot
each of the three different weapons). Notice the combinatorial pattern? That's the root of an annoying problem
with keyframe approaches.
Stand; do nothing
Walk forward; shoot weapon 1
Walk backward; shoot weapon 2
Run forward; shoot weapon 3
Run backward
Jump
Crouch
slide 89
Simulation et Animation
Animation Frame par Frame
Système de frames clés
For Quake III, characters were usually divided into a "head" block, a "torso" block (from the neck to the
belt level), and a "legs" block (from the belt downward). Then, each of these body parts had its own
animation cycles, so combinatorial actions could be achieved by stacking cycles from each body part.
In this case, our head part would remain unanimated. Animation cycles for the torso and the legs are
as follows.
Legs:
Stand still
Walk forward
Walk backward
Run forward
Run backward
Jump
Crouch
Torso:
Stand still
Shoot first weapon
Shoot second weapon
Shoot third weapon
slide 90
Simulation et Animation
Animation Frame par Frame
Système de frames clés
Once the animation cycles have been identified, it is time to link the body pieces together, so the
whole looks like a complete character. To do so,
the designer must manually specify a pivot point in each body part, so each part basically knows
where it should be attached.
These pivots (which are nothing but coordinate systems essentially) are called tags, and hence the
name of the animation system.
In typical Quake III terminology, we have three body parts (head, torso, and legs), and four tags.
The first tag (tag_floor) is used to indicate the ground level, so the character stands well on the terrain.
This tag is usually attached to the legs.
A second tag (tag_legs) specifies the joint between the legs and torso.
A third tag (tag_head) provides the binding between the torso and head.
The fourth tag (tag_weapon) is usually placed inside the right hand, so the character can hold
interchangeable weapons realistically.
You can see a tagged animation character with body parts highlighted in Figure 15.4.
slide 91
Simulation et Animation
Animation Frame par Frame
Système de frames clés
Notice that tags specify where each body part should be placed (both in terms of rotations and
translation).
But how do we ensure continuity between legs and torso (or torso and head)?
Ideally, we should stitch both body parts together to ensure a perfect joint between them by
sewing continuous triangles together.
However, the Quake III animation system chose the easiest solution. No sewing is performed, so
the two body parts are not really integrated: They are just put one beside the other like two
bricks.
To prevent players from noticing this, the body parts interpenetrate each other slightly, so the
whole character always stays together. Artist tricks such as wide belts and clever textures help
convey the sense of continuity.
So clearly, tagged animation is a case for the "too much of a good thing can be bad" discussion.
In the right measure, it can greatly improve upon a keyframe approach, often reducing the memory footprint by half or even
better. But dividing our body into more parts than is strictly required will make things worse:
The control layer will grow out of control.
When programmers fall into this "overdivision" syndrome with a tagged system, it is usually a sign that they really need to get a
skeletal animation system instead.
slide 92
Simulation et Animation
Animation Frame par Frame
Système de frames clés
Implementing a tagged animation system is almost as straightforward as implementing a
regular, single-mesh keyframe interpolator. We only need to store animation pointers for each
body part, so we can keep track of which animation and frame each mesh is playing. Then, we
need to be able to render the whole hierarchy, using the pivot points. To do so, most systems
use a geometric object that hints at the pivot's location and orientation. In most Quake-based
modelers, a triangle is used, so the first point in the triangle is used as the pivot's location, and
then two vectors from that point to the other two define the coordinate axes. By computing the
cross product between these two vectors, an "up" vector is returned.
At runtime, the pivot's position and orientation are usually stored in a quaternion, a
mathematical operator that encapsulates locations and orientations elegantly. A quaternion is
the generalization of a complex number, consisting of four floating-point values. Quaternions
are explained in the next chapter as a way of implementing camera interpolators in games like
Tomb Raider. Generally speaking, they are the way to go whenever you need to smoothly blend
between successive interpolations. Read the next chapter, especially the section referring to the
spherical linear interpolation, for a thorough description on how a quaternion can be used to
compute the pivot point at runtime. Once we have the pivot point in place, all we need to do is
use the transform stacks to apply the right rotations and translations to the vertices.
slide 93
Simulation et Animation
Animation Frame par Frame
Animation Frame par Frame
Animation Frame par Frame
.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
94
The Refresh That Pauses
For some OpenGL implementations, in addition to simply swapping
the viewable and drawable buffers, the swap_the_buffers() routine
waits until the current screen refresh period is over so that the
previous buffer is completely displayed. This routine also allows the
new buffer to be completely displayed, starting from the beginning.
Assuming that your system refreshes the display 60 times per
second, this means that the fastest frame rate you can achieve is 60
frames per second (fps), and if all your frames can be cleared and
drawn in under 1/60 second, your animation will run smoothly at
that rate.
What often happens on such a system is that the frame is too
complicated to draw in 1/60 second, so each frame is displayed more
than once. If, for example, it takes 1/45 second to draw a frame, you
get 30 fps, and the graphics are idle for 1/30 -1/45 = 1/90 second per
frame, or one-third of the time.
Animation Frame par Frame
Animation Frame par Frame
.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
95
The Refresh That Pauses
For some OpenGL implementations,
In addition, the video refresh rate is constant, which can have some
unexpected performance consequences. For example, with the 1/60
second per refresh monitor and a constant frame rate, you can run at
60 fps, 30 fps, 20 fps, 15 fps, 12 fps, and so on (60/1, 60/2, 60/3,
60/4, 60/5,…). This means that if you’re writing an application and
gradually adding features (say its a flight simulator, and you’re
adding ground scenery), at first each feature you add has no effect
on the overall performanceyou still get 60 fps. Then, all of a
sudden, you add one new feature, and the system can’t quite draw
the whole thing in 1/60 of a second, so the animation slows from 60
fps to 30 fps because it misses the first possible buffer-swapping
time.
Animation Frame par Frame
Animation Frame par Frame
.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
96
The Refresh That Pauses
For some OpenGL implementations,
A similar thing happens when the drawing time per frame is more
than 1/30 secondthe animation drops from 30 to 20 fps.
If the scene’s complexity is close to any of the magic times (1/60
second, 2/60 second, 3/60 second, and so on in this example), then,
because of random variation, some frames go slightly over the time
and some slightly under. Then the frame rate is irregular, which can
be visually disturbing.
In this case, if you can’t simplify the scene so that all the frames are
fast enough, it might be better to add an intentional, tiny delay to
make sure they all miss, giving a constant, slower frame rate. If your
frames have drastically different complexities, a more sophisticated
approach might be necessary.
Animation Frame par Frame
Animation Frame par Frame
The Refresh That Pauses
Motion = Redraw + Swap
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
97
The Refresh That Pauses
For some OpenGL implementations, in addition to simply swapping
the viewable and drawable buffers, the swap_the_buffers() routine
waits until the current screen refresh period is over so that the
previous buffer is completely displayed. This routine also allows the
new buffer to be completely displayed, starting from the beginning.
Assuming that your system refreshes the display 60 times per
second, this means that the fastest frame rate you can achieve is 60
frames per second (fps), and if all your frames can be cleared and
drawn in under 1/60 second, your animation will run smoothly at
that rate.
Motion = Redraw + Swap
The structure of real animation programs does not differ very much
from this description. Usually, it is easier to redraw the entire buffer
from scratch for each frame than to figure out which parts require
redrawing. This is especially true with applications such as three-
dimensional flight simulators, where a tiny change in the plane’s
orientation changes the position of everything outside the window.
Animation Frame par Frame
Animation Frame par Frame
If you are using the GLUT library, you’ll want to call this routine:
Example: illustrates the use of glutSwapBuffers() in drawing a
spinning square, as shown in Figure below. This example also
shows how to use GLUT to control an input device and turn on
and off an idle function. In this example, the mouse buttons
toggle the spinning on and off.
Programmation 2D/3D: INF 1483
Simulation et Animation
Animation Frame par Frame
98
Motion = Redraw + Swap
In most animations, the objects in a scene are simply redrawn with
different transformationsthe viewpoint of the viewer moves, or a
car moves down the road a bit, or an object is rotated slightly. If
significant recomputation is required for nondrawing operations, the
attainable frame rate often slows down. Keep in mind, however, that
the idle time after the swap_the_buffers() routine can often be used
for such calculations.
OpenGL doesn’t have a swap_the_buffers() command because the
feature might not be available on all hardware and, in any case, its
highly dependent on the window system. For example, if you are
using the X Window System and accessing it directly, you might use
the following GLX routine:
slide 99
Programmation 2D/3D: INF 1483
Contenu
Introduction
Objets et États Géométriques
Notions de Géométrie relies au
cours
Espace et coordonnées 2D/3D.
Géométrie: courbes, surfaces,
polygones, etc.
Transformations géométriques et
projections : translation, rotation,
etc.
Applications OpenGL
État de Rendu
Notions d‘Optique relies au
cours
Effet de lumière sur les objets,
rayons lumineux, camera.
Système de Formation
d’Images
État de Rendu Applications
OpenGL
Techniques d'animation et
simulation 2D/3D
Equations des mouvements
des objets.
Animation:
Temps Réel ,
Frame par Frame.
Applications OpenGL
Applications OpenGL
Introduction à
l’Infographie
Introduction à OpenGL
slide 100
Programmation 2D/3D: INF 1483
Contenu
Introduction
Objets et États Géométriques
Notions de Géométrie relies au
cours
Espace et coordonnées 2D/3D.
Géométrie: courbes, surfaces,
polygones, etc.
Transformations géométriques et
projections : translation, rotation,
etc.
Applications OpenGL
État de Rendu
Notions d‘Optique relies au
cours
Effet de lumière sur les objets,
rayons lumineux, camera.
Système de Formation
d’Images
État de Rendu Applications
OpenGL
Techniques d'animation et
simulation 2D/3D
Equations des mouvements
des objets.
Animation:
Temps Réel ,
Frame par Frame.
Applications OpenGL
Applications OpenGL
Introduction à
l’Infographie
Introduction à OpenGL
slide 101
Programmation 2D/3D: INF 1483
Contenu
Introduction
Objets et États Géométriques
Notions de Géométrie relies au
cours
Espace et coordonnées 2D/3D.
Géométrie: courbes, surfaces,
polygones, etc.
Transformations géométriques et
projections : translation, rotation,
etc.
Applications OpenGL
État de Rendu
Notions d‘Optique relies au
cours
Effet de lumière sur les objets,
rayons lumineux, camera.
Système de Formation
d’Images
État de Rendu Applications
OpenGL
Techniques d'animation et
simulation 2D/3D
Equations des mouvements
des objets.
Animation:
Temps Réel ,
Frame par Frame.
Applications OpenGL
Applications OpenGL
Introduction à
l’Infographie
Introduction à OpenGL
slide 102
Programmation 2D/3D: INF 1483
Contenu
Introduction
Notions de Géométrie relies au
cours:
Espace et coordonnées
2D/3D. Géométrie:
courbes, surfaces,
polygones, etc.
Transformations
géométriques et
projections : translation,
rotation, etc.
Applications OpenGL
Notions d‘Optique relies au
cours:
Effet de lumière sur les
objets, rayons lumineux,
camera.
Plaquage des Textures
et ombrages.
Rendu de volume.
Applications OpenGL
Techniques d'animation et
simulation 2D/3D
Equations des
mouvements des
objets.
Animation:
Temps Réel ,
Frame par Frame.
Applications OpenGL
Applications OpenGL
Introduction à
l’Infographie
Introduction à OpenGL
103
Programmation 2D/3D: INF 1483
Hiver 2012
Par: Prof. Mohand Saïd Allili
103
Animation & fonctions interactives
104
I- Animations par ordinateur
Mise en application OpenGL
Notons que dans GLUT comme dans beaucoup d’autres
bibliothèques similaires, notre programme est averti qu’il
doit procéder à l’une ou l’autre étape (programmation
événementielle). Enfin, lorsque la condition d’arrêt est
atteinte
(p.ex. délai dépassé ou précision suffisante) on arrête
proprement le programme. Cest ici que l’on doit libérer la
mémoire, fermer les fichiers ouverts, etc ...
slide 105
Simulation et Animation: Applications OpenGL
Animation Temps Réel
Simulation OpenGL
Simulation OpenGL
Définissons formellement le problème:
la balle, de masse m, est située à une hauteur h0
du sol, et est lâchée à l’instant t0 = 0. A chaque
instant t, la seule force exercée sur la balle est la
force de pesanteur mg (en négligeant les
frottements dans l’air).
On peut donc écrire
F(t) = mg
On en déduit l’accélération de la balle:
a(t) = F(t) / m = g (constante).
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
106
Le terme temps réel signifie que le temps qui s’écoule a une
signification dans le programme.
Dans un processus temps réel, le programme continue de
s’exécuter, que l’utilisateur agisse ou non.
Ceci permet d’animer de façon réaliste les éléments du
monde que l’on représente.
Prenons par exemple le cas d’une balle que l’on lâche
depuis une certaine hauteur.
On pourrait, calculer à l’avance le temps auquel la balle
touchera le sol.
Mais dans une simulation physique, on voudrait avoir la
position de la balle à chaque instant pour pouvoir l’afficher
en temps réel.
Simulation OpenGL
Simulation OpenGL
Dans une simulation numérique:
Sans temps réel, on fixe cet intervalle dt à une valeur aussi
petite que possible pour gagner en précision ;
Temps réel, c’est la puissance de la machine qui détermine
dt:
plus la scène est complexe à animer et afficher, plus dt
sera grand, et
plus la simulation sera approximative et l’animation
saccadée.
La raison pour laquelle on ne fixe pas à l’avance l’intervalle dt
est qu’on a priori aucune idée du temps que prendra le calcul
d’une image et, surtout, qu’on n’a aucune garantie que ce
temps restera constant:
plus il y a d’éléments à afficher, plus il augmentera.
De façon concrète, dt nous sera donné par un timer, qui est tout
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
107
Alors :
a(t+dt) = a(t) = g
v(t+dt) = v(t) +
׬
t
t+dt
a(t) dt ≈ v(t) + a(t)*dt
avec v(t0) = 0
h(t+dt) = h(t) +
׬
t
t+dt
v(t) dt ≈ h(t) + v(t)*dt
avec h(t0) = h0 *uy
On est donc capable de décrire à chaque instant la
nouvelle position de la balle en fonction de la précédente
et du temps écoulé dt.
Ce temps est simplement le temps que l’ordinateur a mis
pour calculer et afficher la dernière image.
Simulation OpenGL
Simulation OpenGL
Schéma d’exécution
Globalement, les programmes de simulation fonctionnent selon
le schéma ci-dessous.
Dans un premier temps, on prépare les variables, on alloue la
mémoire, etc.
Ensuite on commence la boucle de simulation. Celle-ci
répète en permanence deux étapes :
1- calcul (ou mise à jour): on détermine l’état suivant du
système selon l’état courant et le pas de temps dt.
C’est dans cette phase qu’interviennent les équations de la
simulation.
2- affichage à l’écran: on envoie les données vers la carte
vidéo (ou un fichier du disque, …).
En théorie aucun calcul n’est à effectuer dans cette phase.
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
108
Alors :
a(t+dt) = a(t) = g
v(t+dt) = v(t) +
׬
t
t+dt
a(t) dt ≈ v(t) + a(t)*dt
avec v(t0) = 0
h(t+dt) = h(t) +
׬
t
t+dt
v(t) dt ≈ h(t) + v(t)*dt
avec h(t0) = h0 *uy
On est donc capable de décrire à chaque instant la
nouvelle position de la balle en fonction de la précédente
et du temps écoulé dt.
Ce temps est simplement le temps que l’ordinateur a mis
pour calculer et afficher la dernière image.
Simulation OpenGL
Simulation OpenGL
#include <windows.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
/* Nous sommes maintenant prêts à effectuer
les calculs pour animer la scène.
Supposons que le problème de notre balle
fasse intervenir les valeurs suivantes: */
double h = 5.0 ; // 5 m au dessus du sol
double m = 1.0 ; //la masse est 1 kg,
double v = 0.0 ; // Vitesse de la balle en m/s
const double g = 9.81 ; // accélération de la
pesanteur
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
109
Mise en application
Ensuite on commence la boucle de
simulation. Celle-ci répète en
permanence deux étapes :
1- calcul (ou mise à jour): on
détermine l’état suivant du
système selon l’état courant et
le pas de temps dt.
C’est dans cette phase
qu’interviennent les
équations de la
simulation.
2- affichage à l’écran: on envoie
les données vers la carte
vidéo (ou un fichier du
disque, …).
On crée un projet SimTempRéel dans
le fichier main.cpp on aura
principalement:
// timer
int refreshMills = 150.0; // refresh interval
in millisec
/* Called back when timer expired [NEW]
*/
Alors nous pouvons écrire dans le corps de
la boucle principale :
void myUpdateFunc() {
// Récupère le temps écoulé depuis la
dernière image
double dt =
glutGet(GLUT_ELAPSED_TIME) /3000;
// L’accélération est uniquement due à g
double a = g ;
// La vitesse augmente de a(t).dt pendant
cette image
v += a * dt ;
Simulation OpenGL
Simulation OpenGL
// La balle tombe d’une distance v(t).dt pendant cette image
h -= v * dt ;
// prendre en compte le fait que la balle a touché le sol
if (0.0 < h) {
// Post re-paint request to activate display()
glutPostRedisplay();
// next timer call milliseconds later
glutTimerFunc(refreshMills, myUpdateFun, 0);
}
// Demande à glut de redessiner la fenêtre graphique
glutPostRedisplay();
}
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
110
Mise en application
Ensuite on commence la boucle de
simulation. Celle-ci répète en
permanence deux étapes :
1- calcul (ou mise à jour): on
détermine l’état suivant du
système selon l’état courant et
le pas de temps dt.
C’est dans cette phase
qu’interviennent les
équations de la
simulation.
2- affichage à l’écran: on envoie
les données vers la carte
vidéo (ou un fichier du
disque, …).
On crée un projet SimTempRéel dans
le fichier main.cpp on aura
principalement:
void reshape(int w, int h) {
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.,1.,-1.,1.,1.5,20.);
}
GLUquadricObj *quadric;
void myinit(void) {
glShadeModel(GL_SMOOTH ) ; //GL_FLAT);
//prepare quadric for sphere
quadric = gluNewQuadric();
gluQuadricTexture(quadric, GL_TRUE);
gluQuadricNormals(quadric, GLU_SMOOTH);
}
Simulation OpenGL
Simulation OpenGL
void display(void) {
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(0.0,0.0,-20.0);
glColor4f(1,1,1,1);
glBegin(GL_POLYGON);
glVertex2f(-100,-100);
glVertex2f(-100,100);
glVertex2f(100,100);
glVertex2f(100,-100);
Programmation 2D/3D: INF 1483
Simulation et Animation
Applications OpenGL
111
Mise en application
Ensuite on commence la boucle de
simulation. Celle-ci répète en
permanence deux étapes :
1- calcul (ou mise à jour): on
détermine l’état suivant du
système selon l’état courant et
le pas de temps dt.
C’est dans cette phase
qu’interviennent les
équations de la
simulation.
2- affichage à l’écran: on envoie
les données vers la carte
vidéo (ou un fichier du
disque, …).
On crée un projet SimTempRéel dans
le fichier main.cpp on aura
principalement:
glEnd();
glPopMatrix();
// balle
glTranslatef(0.0, h ,-21.53);
glColor4f(0,0,1,1);
gluSphere(quadric, 1.55 , 200,
100);
glFlush();
glutSwapBuffers();
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
glutInitDisplayMode(
GLUT_RGBA|GLUT_DEPTH |
GLUT_DOUBLE );
glutInitWindowSize(800,800);
glutInitWindowPosition(150,150);
glutCreateWindow("Simulation");
myinit();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
// First timer call immediately
glutTimerFunc( 0,
myUpdateFun, 0 );
glutMainLoop();
return(0);
}