Navigation: back up next notes exercises
The user specifies two keyframes describing the initial and final x position of the triangle alongwith the timing requirements. The program generates the inbetween frames by linear interpolation. Users controls the time by pressing 'f' and 'b'. 'f' advances the time and 'b' reverses it.
#include <stdio.h> #include <GL/glut.h> #include <math.h> /* the triangle is a 1DOF (degrees of freedom) system, as we are only controlling the translation along the x-axis. */ // keyframe 1. the triangle should be at x=0 at time t=0 float start_x = 0.0; float start_time = 0.0; // keyframe 2. the triangle should be at x=10 at time t=60 float end_x = 10.0; float end_time = 60.0; // 1 minute float x = 0.0; // the current position of the object float time = 0.0; // the current time (for interpolation purposes) float time_step = 0.01; // time advance per keystroke int main(int argc,char **argv) { /* initialize GLUT, OpenGL */ glutInit(&argc,argv); /* set the window pos---let the windowing system determine */ glutInitWindowPosition(-1,-1); /* set the window size */ glutInitWindowSize(250,250); /* set the window display modes (hopefully supported) GLUT_DOUBLE: double-buffered GLUT_RGBA: rgba colors (no colormap) GLUT_DEPTH: z-buffering */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); /* setting background */ glutCreateWindow("my first animation"); /* setting up a black background */ glClearColor(0.0,0.0,0.0,0.0); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glutDisplayFunc(draw_scene); glutReshapeFunc(resize_window); /* let it go! */ glutMainLoop(); } /* linear interpolation is used to compute the current value of x given the two keyframes (start_x, start_time) and (end_x, end_time) */ float linear_interpolate(float t, float t0, float t1, float x0, float x1) { return (t-t0)*(x1-x0)/(t1-t0)+x1; } /* called when the window is resized */ void resize_window(int w, int h) { glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0,(GLfloat)w/(GLfloat)h,1.0,30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-3.6); } /* drawing scene */ void draw_scene(void) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslate(x,0,-3.6) /* clear back buffer */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBegin(GL_POLYGON); glColor3f(1,0,0); glVertex3f(0,0,0); glColor3f(0,1,0); glVertex3f(10,0,0); glColor3f(0,0,1); glVertex3f(10,10,0); glEnd(); glFlush(); /* double buffering. swap buffers */ glutSwapBuffers(); } /* handling input */ void keyboard(unsigned char key, int x, int y) { switch(key) { case 'q': case 27: // esc key exit(0); break; case 'f': time += time_step; time = min(end_time,max(start_time,time)); // ensuring that time is within [start_time,end_time] x = linear_interpolate(time,start_time,end_time,start_x,end_x); glutPostRedisplay(); break; case 'b': time -= time_step; time = min(end_time,max(start_time,time)); // ensuring that time is within [start_time,end_time] x = linear_interpolate(time,start_time,end_time,start_x,end_x); glutPostRedisplay(); break; default: break; } }
Animation has historically been produced in two ways. The first is by artists creating a succession of cartoon frames, which are then combined into a film. A second method is by using physical models, e.g. King Kong, which are positioned, the image recorded, then the model is moved, the next image is recorded, and this process is continued.
Computer animation can be produced by using a rendering machine to produce successive frames wherein some aspect of the image is varied. For a simple animation this might be just moving the camera or the relative motion of rigid bodies in the scene. This is analogous to the second technique described above, i.e., using physical models. More sophisticated computer animation can move the camera and/or the objects in more interesting ways, e.g. along computed curved paths, and can even use the laws of Physics to determine the behavior of objects.
Many of the principles of traditional animation were developed in the 1930's at the Walt Disney studios. These principles were developed to make animation, especially character animation, more realistic and entertaining. These principles can and should be applied to 3D computer animation. These principles are devised to capture the "personality" of the character.
Reference: John Lasseter, "Principles of Traditional Animation Applied to 3D Computer Animation", Computer Graphics, pp. 35-44, 21:4, July 1987 (SIGGRAPH 87).
The idea came from the traditional (hand-drawn) animation, where the artists draws the basic poses of the scenes first, drawing poses of the entire character so the timing and acting can be worked out with a minimum of drawings created. These basic poses are called keyframes. Once the poses are finalized, then the inbetween drawings are created by hand to complete the action.
In computer animation, the artist define the key-frames and the computer uses interpolation to generate the inbetween frames automatically.
to be written
See Curves.
Using the laws of Physics to determine the behavior of a objects. For certain scenes/objects it is difficult to generate the keyframes and use interpolation to generate the animation, e.g., an ocean wave. For some other objects it is just more intuitive to model their behavior using physical models, e.g., a ball bouncing of a table, a flag fluttering in the wind, and a car speading along a corner.
Some definitions:
First Law: In the absence of a force, a body maintains its state, i.e., in the absence of a force, a body at rest will remain at rest and a body in motion will keep moving with the constant velocity.
Second Law: Rate of change of momentum = Force OR Force = Mass x Acceleration
Third Law: Every action has an equal and opposite reaction
Using these laws we can create dynamic simulations of objects: compute the future states of an object given the forces acting upon it.
Let's take the 1-dimensional case. The position of the body at time t is x_t and the total force acting on the body is f_t. Let m be the mass of the body. We want to find out the position of the body at time t+1. Using finite differences approximations for acceleration, we write,
Acceleration: x_t'' =
(x_(t+1) - 2*x_t + x_(t-1))/dt^2
Here, x_(t-1) and x_(t+1) is the position of the body at the previous and the next timesteps respectively and dt is the simulation time step.
Using Newton's second law: F=MA, we write,
f_t = m * (x_(t+1) - 2*x_t + x_(t-1))/dt^2 (1)
Rearranging (1),
x_(t+1) = f_t * dt^2 + 2*x_t - x_(t-1)
Spring mass systems are heavily used in graphics (physically-based animation) to madel the dynamics properties of deformable objects, such as clothes and hair.
Equations of Motion:
F = force acting on the mass M
l = rest length of the spring
d = deformation in the spring (in the positive x direction)
k = spring's constant
Then from Hook's Law, F=-k d (2). Also, from Newtons second law, F=Ma (3).
Equating (2) and (3) we get,
Ma=-kd (3)
a=-k d/M
Subsituting the value of a from (1),
x_(t+1) = (-k d / M) dt^2 + 2*x_t - x_(t-1)
Forward Kinematics: Given the joint angles (th1 and th2),
what's the position (x0,y0) of the end-effector.
Inverse Kinematics: Given the position (x0,y0) of the end-effector, what
are the joint angles (th1 and th2).
Inverse kinematics is harder to solve, but is useful for animating articulated bodies. E.g., the animator can specify the position of the feet, head, and tail of a dinosaur and let the inverse kinematics to find out the joing angles.
Inverse kinematics can yeild mutliple joint configurations for a given input.
How to avoid flicker?
Show every frame only when the drawing is complete; never show a partially drawn frame.
Allocate A Allocate B back_buffer = B /* scene is always rendered into the back buffer */ display_buffer = A /* user always sees the display buffer */ while (drawing) { Draw in back_buffer Switch back_buffer and draw_buffer
}
User does not see any flicker since swapping two operation is much faster than the actual rendering operation.
(to be written)