Project 4: Animation
Bogdan Gevko - gevkob@oregonstate.edu
Project Details
As in prior projects, I started with a sketch in Blender. I read somewhere that a classic exercise for all beginner animators is to start with a bouncing ball, so that’s what I did! I tried to incorporate a few animation principles such as squash, stretch, and even a bit of anticipation. Here’s how the animation sketch turned out:

The next challenge was figuring out how to get the same effect with the Keytimes helper function. I ran into a few problems:
- My initial animation was only 1.233 seconds, but I needed to make it into 10 seconds
Actually, that was the main problem. There’s 12 keyframes in each cycle, and I needed to figure out how to fit that neatly into 10 seconds. I ended up slowing down the animation quite a lot (to 2 seconds). The above version is that 2 second version. I also realized that perhaps it was a bit too fast anyways, so the result turned out okay.
Then, it was just a matter of creating a single 2 second cycle in C++, and then copying it over 5 times to fit the 10 second window. I did this by looking at each frame in Blender, and then dividing the current frame by 30 (the FPS value I used), which gave me the exact time value for each keyframe.
I used the same technique for the platform to make it seem as if it’s reacting to the weight of the ball.
After that, I added a few more elements inside C++ to meet the rest of the assignment requirements, and here’s the final result:

Timetables
// Animate ball
Ypos1.Init();
Ypos1.AddTimeValue( 0.000, 0.0 );
Ypos1.AddTimeValue( 0.133, -0.05 );
Ypos1.AddTimeValue( 0.500, -0.08 );
Ypos1.AddTimeValue( 0.700, -0.07 );
Ypos1.AddTimeValue( 0.833, 0.0 );
Ypos1.AddTimeValue( 1.000, 1.0 );
Ypos1.AddTimeValue( 1.200, 2.0 );
Ypos1.AddTimeValue( 1.433, 2.1 );
Ypos1.AddTimeValue( 1.633, 2.2 );
Ypos1.AddTimeValue( 1.733, 2.1 );
Ypos1.AddTimeValue( 1.933, 1.0 );
Ypos1.AddTimeValue( 2.000, 0.0 );
Ypos1.AddTimeValue( 2.000, 0.0 );
Ypos1.AddTimeValue( 2.133, -0.05 );
Ypos1.AddTimeValue( 2.500, -0.08 );
Ypos1.AddTimeValue( 2.700, -0.07 );
Ypos1.AddTimeValue( 2.833, 0.0 );
Ypos1.AddTimeValue( 3.000, 1.0 );
Ypos1.AddTimeValue( 3.200, 2.0 );
Ypos1.AddTimeValue( 3.433, 2.1 );
Ypos1.AddTimeValue( 3.633, 2.2 );
Ypos1.AddTimeValue( 3.733, 2.1 );
Ypos1.AddTimeValue( 3.933, 1.0 );
Ypos1.AddTimeValue( 4.000, 0.0 );
Ypos1.AddTimeValue( 4.000, 0.0 );
Ypos1.AddTimeValue( 4.133, -0.05 );
Ypos1.AddTimeValue( 4.500, -0.08 );
Ypos1.AddTimeValue( 4.700, -0.07 );
Ypos1.AddTimeValue( 4.833, 0.0 );
Ypos1.AddTimeValue( 5.000, 1.0 );
Ypos1.AddTimeValue( 5.200, 2.0 );
Ypos1.AddTimeValue( 5.433, 2.1 );
Ypos1.AddTimeValue( 5.633, 2.2 );
Ypos1.AddTimeValue( 5.733, 2.1 );
Ypos1.AddTimeValue( 5.933, 1.0 );
Ypos1.AddTimeValue( 6.000, 0.0 );
Ypos1.AddTimeValue( 6.000, 0.0 );
Ypos1.AddTimeValue( 6.133, -0.05 );
Ypos1.AddTimeValue( 6.500, -0.08 );
Ypos1.AddTimeValue( 6.700, -0.07 );
Ypos1.AddTimeValue( 6.833, 0.0 );
Ypos1.AddTimeValue( 7.000, 1.0 );
Ypos1.AddTimeValue( 7.200, 2.0 );
Ypos1.AddTimeValue( 7.433, 2.1 );
Ypos1.AddTimeValue( 7.633, 2.2 );
Ypos1.AddTimeValue( 7.733, 2.1 );
Ypos1.AddTimeValue( 7.933, 1.0 );
Ypos1.AddTimeValue( 8.000, 0.0 );
Ypos1.AddTimeValue( 8.000, 0.0 );
Ypos1.AddTimeValue( 8.133, -0.05 );
Ypos1.AddTimeValue( 8.500, -0.08 );
Ypos1.AddTimeValue( 8.700, -0.07 );
Ypos1.AddTimeValue( 8.833, 0.0 );
Ypos1.AddTimeValue( 9.000, 1.0 );
Ypos1.AddTimeValue( 9.200, 2.0 );
Ypos1.AddTimeValue( 9.433, 2.1 );
Ypos1.AddTimeValue( 9.633, 2.2 );
Ypos1.AddTimeValue( 9.733, 2.1 );
Ypos1.AddTimeValue( 9.933, 1.0 );
Ypos1.AddTimeValue( 10.000, 0.0 );
ScaleXZ.Init();
ScaleXZ.AddTimeValue( 0.000, 0.409 );
ScaleXZ.AddTimeValue( 0.133, 0.479 );
ScaleXZ.AddTimeValue( 0.500, 0.641 );
ScaleXZ.AddTimeValue( 0.700, 0.479 );
ScaleXZ.AddTimeValue( 0.833, 0.409 );
ScaleXZ.AddTimeValue( 1.000, 0.130 );
ScaleXZ.AddTimeValue( 1.200, 0.409 );
ScaleXZ.AddTimeValue( 1.433, 0.409 );
ScaleXZ.AddTimeValue( 1.633, 0.409 );
ScaleXZ.AddTimeValue( 1.733, 0.409 );
ScaleXZ.AddTimeValue( 1.933, 0.130 );
ScaleXZ.AddTimeValue( 2.000, 0.409 );
ScaleXZ.AddTimeValue( 2.000, 0.409 );
ScaleXZ.AddTimeValue( 2.133, 0.479 );
ScaleXZ.AddTimeValue( 2.500, 0.641 );
ScaleXZ.AddTimeValue( 2.700, 0.479 );
ScaleXZ.AddTimeValue( 2.833, 0.409 );
ScaleXZ.AddTimeValue( 3.000, 0.130 );
ScaleXZ.AddTimeValue( 3.200, 0.409 );
ScaleXZ.AddTimeValue( 3.433, 0.409 );
ScaleXZ.AddTimeValue( 3.633, 0.409 );
ScaleXZ.AddTimeValue( 3.733, 0.409 );
ScaleXZ.AddTimeValue( 3.933, 0.130 );
ScaleXZ.AddTimeValue( 4.000, 0.409 );
ScaleXZ.AddTimeValue( 4.000, 0.409 );
ScaleXZ.AddTimeValue( 4.133, 0.479 );
ScaleXZ.AddTimeValue( 4.500, 0.641 );
ScaleXZ.AddTimeValue( 4.700, 0.479 );
ScaleXZ.AddTimeValue( 4.833, 0.409 );
ScaleXZ.AddTimeValue( 5.000, 0.130 );
ScaleXZ.AddTimeValue( 5.200, 0.409 );
ScaleXZ.AddTimeValue( 5.433, 0.409 );
ScaleXZ.AddTimeValue( 5.633, 0.409 );
ScaleXZ.AddTimeValue( 5.733, 0.409 );
ScaleXZ.AddTimeValue( 5.933, 0.130 );
ScaleXZ.AddTimeValue( 6.000, 0.409 );
ScaleXZ.AddTimeValue( 6.000, 0.409 );
ScaleXZ.AddTimeValue( 6.133, 0.479 );
ScaleXZ.AddTimeValue( 6.500, 0.641 );
ScaleXZ.AddTimeValue( 6.700, 0.479 );
ScaleXZ.AddTimeValue( 6.833, 0.409 );
ScaleXZ.AddTimeValue( 7.000, 0.130 );
ScaleXZ.AddTimeValue( 7.200, 0.409 );
ScaleXZ.AddTimeValue( 7.433, 0.409 );
ScaleXZ.AddTimeValue( 7.633, 0.409 );
ScaleXZ.AddTimeValue( 7.733, 0.409 );
ScaleXZ.AddTimeValue( 7.933, 0.130 );
ScaleXZ.AddTimeValue( 8.000, 0.409 );
ScaleXZ.AddTimeValue( 8.000, 0.409 );
ScaleXZ.AddTimeValue( 8.133, 0.479 );
ScaleXZ.AddTimeValue( 8.500, 0.641 );
ScaleXZ.AddTimeValue( 8.700, 0.479 );
ScaleXZ.AddTimeValue( 8.833, 0.409 );
ScaleXZ.AddTimeValue( 9.000, 0.130 );
ScaleXZ.AddTimeValue( 9.200, 0.409 );
ScaleXZ.AddTimeValue( 9.433, 0.409 );
ScaleXZ.AddTimeValue( 9.633, 0.409 );
ScaleXZ.AddTimeValue( 9.733, 0.409 );
ScaleXZ.AddTimeValue( 9.933, 0.130 );
ScaleXZ.AddTimeValue( 10.00, 0.409 );
ScaleY.Init();
ScaleY.AddTimeValue( 0.000, 0.409 );
ScaleY.AddTimeValue( 0.133, 0.206 );
ScaleY.AddTimeValue( 0.500, 0.121 );
ScaleY.AddTimeValue( 0.700, 0.206 );
ScaleY.AddTimeValue( 0.833, 0.409 );
ScaleY.AddTimeValue( 1.000, 0.459 );
ScaleY.AddTimeValue( 1.200, 0.409 );
ScaleY.AddTimeValue( 1.433, 0.409 );
ScaleY.AddTimeValue( 1.633, 0.409 );
ScaleY.AddTimeValue( 1.733, 0.409 );
ScaleY.AddTimeValue( 1.933, 0.459 );
ScaleY.AddTimeValue( 2.000, 0.409 );
ScaleY.AddTimeValue( 2.000, 0.409 );
ScaleY.AddTimeValue( 2.133, 0.206 );
ScaleY.AddTimeValue( 2.500, 0.121 );
ScaleY.AddTimeValue( 2.700, 0.206 );
ScaleY.AddTimeValue( 2.833, 0.409 );
ScaleY.AddTimeValue( 3.000, 0.459 );
ScaleY.AddTimeValue( 3.200, 0.409 );
ScaleY.AddTimeValue( 3.433, 0.409 );
ScaleY.AddTimeValue( 3.633, 0.409 );
ScaleY.AddTimeValue( 3.733, 0.409 );
ScaleY.AddTimeValue( 3.933, 0.459 );
ScaleY.AddTimeValue( 4.000, 0.409 );
ScaleY.AddTimeValue( 4.000, 0.409 );
ScaleY.AddTimeValue( 4.133, 0.206 );
ScaleY.AddTimeValue( 4.500, 0.121 );
ScaleY.AddTimeValue( 4.700, 0.206 );
ScaleY.AddTimeValue( 4.833, 0.409 );
ScaleY.AddTimeValue( 5.000, 0.459 );
ScaleY.AddTimeValue( 5.200, 0.409 );
ScaleY.AddTimeValue( 5.433, 0.409 );
ScaleY.AddTimeValue( 5.633, 0.409 );
ScaleY.AddTimeValue( 5.733, 0.409 );
ScaleY.AddTimeValue( 5.933, 0.459 );
ScaleY.AddTimeValue( 6.000, 0.409 );
ScaleY.AddTimeValue( 6.000, 0.409 );
ScaleY.AddTimeValue( 6.133, 0.206 );
ScaleY.AddTimeValue( 6.500, 0.121 );
ScaleY.AddTimeValue( 6.700, 0.206 );
ScaleY.AddTimeValue( 6.833, 0.409 );
ScaleY.AddTimeValue( 7.000, 0.459 );
ScaleY.AddTimeValue( 7.200, 0.409 );
ScaleY.AddTimeValue( 7.433, 0.409 );
ScaleY.AddTimeValue( 7.633, 0.409 );
ScaleY.AddTimeValue( 7.733, 0.409 );
ScaleY.AddTimeValue( 7.933, 0.459 );
ScaleY.AddTimeValue( 8.000, 0.409 );
ScaleY.AddTimeValue( 8.000, 0.409 );
ScaleY.AddTimeValue( 8.133, 0.206 );
ScaleY.AddTimeValue( 8.500, 0.121 );
ScaleY.AddTimeValue( 8.700, 0.206 );
ScaleY.AddTimeValue( 8.833, 0.409 );
ScaleY.AddTimeValue( 9.000, 0.459 );
ScaleY.AddTimeValue( 9.200, 0.409 );
ScaleY.AddTimeValue( 9.433, 0.409 );
ScaleY.AddTimeValue( 9.633, 0.409 );
ScaleY.AddTimeValue( 9.733, 0.409 );
ScaleY.AddTimeValue( 9.933, 0.459 );
ScaleY.AddTimeValue( 10.00, 0.409 );
// Animate platform
PlatformY.Init();
PlatformY.AddTimeValue( 0.000, 0.0 );
PlatformY.AddTimeValue( 0.133, -0.05 );
PlatformY.AddTimeValue( 0.500, -0.08 );
PlatformY.AddTimeValue( 0.700, -0.07 );
PlatformY.AddTimeValue( 0.833, -0.1 );
PlatformY.AddTimeValue( 1.000, 0.0 );
PlatformY.AddTimeValue( 1.200, -0.02 );
PlatformY.AddTimeValue( 1.333, 0.0 );
PlatformY.AddTimeValue( 1.433, -0.01 );
PlatformY.AddTimeValue( 1.566, 0.0 );
PlatformY.AddTimeValue( 2.000, 0.0 );
PlatformY.AddTimeValue( 2.000, 0.0 );
PlatformY.AddTimeValue( 2.133, -0.05 );
PlatformY.AddTimeValue( 2.500, -0.08 );
PlatformY.AddTimeValue( 2.700, -0.07 );
PlatformY.AddTimeValue( 2.833, -0.1 );
PlatformY.AddTimeValue( 3.000, 0.0 );
PlatformY.AddTimeValue( 3.200, -0.02 );
PlatformY.AddTimeValue( 3.333, 0.0 );
PlatformY.AddTimeValue( 3.433, -0.01 );
PlatformY.AddTimeValue( 3.566, 0.0 );
PlatformY.AddTimeValue( 4.000, 0.0 );
PlatformY.AddTimeValue( 4.000, 0.0 );
PlatformY.AddTimeValue( 4.133, -0.05 );
PlatformY.AddTimeValue( 4.500, -0.08 );
PlatformY.AddTimeValue( 4.700, -0.07 );
PlatformY.AddTimeValue( 4.833, -0.1 );
PlatformY.AddTimeValue( 5.000, 0.0 );
PlatformY.AddTimeValue( 5.200, -0.02 );
PlatformY.AddTimeValue( 5.333, 0.0 );
PlatformY.AddTimeValue( 5.433, -0.01 );
PlatformY.AddTimeValue( 5.566, 0.0 );
PlatformY.AddTimeValue( 6.000, 0.0 );
PlatformY.AddTimeValue( 6.000, 0.0 );
PlatformY.AddTimeValue( 6.133, -0.05 );
PlatformY.AddTimeValue( 6.500, -0.08 );
PlatformY.AddTimeValue( 6.700, -0.07 );
PlatformY.AddTimeValue( 6.833, -0.1 );
PlatformY.AddTimeValue( 7.000, 0.0 );
PlatformY.AddTimeValue( 7.200, -0.02 );
PlatformY.AddTimeValue( 7.333, 0.0 );
PlatformY.AddTimeValue( 7.433, -0.01 );
PlatformY.AddTimeValue( 7.566, 0.0 );
PlatformY.AddTimeValue( 8.000, 0.0 );
PlatformY.AddTimeValue( 8.000, 0.0 );
PlatformY.AddTimeValue( 8.133, -0.05 );
PlatformY.AddTimeValue( 8.500, -0.08 );
PlatformY.AddTimeValue( 8.700, -0.07 );
PlatformY.AddTimeValue( 8.833, -0.1 );
PlatformY.AddTimeValue( 9.000, 0.0 );
PlatformY.AddTimeValue( 9.200, -0.02 );
PlatformY.AddTimeValue( 9.333, 0.0 );
PlatformY.AddTimeValue( 9.433, -0.01 );
PlatformY.AddTimeValue( 9.566, 0.0 );
PlatformY.AddTimeValue( 10.00, 0.0 );
Ypos1.AddTimeValue( 0.000, 0.0 );
Ypos1.AddTimeValue( 0.133, -0.05 );
Ypos1.AddTimeValue( 0.500, -0.08 );
Ypos1.AddTimeValue( 0.700, -0.07 );
Ypos1.AddTimeValue( 0.833, 0.0 );
Ypos1.AddTimeValue( 1.000, 1.0 );
Ypos1.AddTimeValue( 1.200, 2.0 );
Ypos1.AddTimeValue( 1.433, 2.1 );
Ypos1.AddTimeValue( 1.633, 2.2 );
Ypos1.AddTimeValue( 1.733, 2.1 );
Ypos1.AddTimeValue( 1.933, 1.0 );
Ypos1.AddTimeValue( 2.000, 0.0 );
// Animate cam
Cam.Init();
Cam.AddTimeValue( 0.00, 0.0 );
Cam.AddTimeValue( 1.200, 0.1 );
Cam.AddTimeValue( 2.000, 0.0 );
Cam.AddTimeValue( 2.00, 0.0 );
Cam.AddTimeValue( 3.200, 0.1 );
Cam.AddTimeValue( 4.000, 0.0 );
Cam.AddTimeValue( 4.00, 0.0 );
Cam.AddTimeValue( 5.200, 0.1 );
Cam.AddTimeValue( 6.000, 0.0 );
Cam.AddTimeValue( 6.00, 0.0 );
Cam.AddTimeValue( 7.200, 0.1 );
Cam.AddTimeValue( 8.000, 0.0 );
Cam.AddTimeValue( 8.00, 0.0 );
Cam.AddTimeValue( 9.200, 0.1 );
Cam.AddTimeValue( 10.0, 0.0 );
Red.Init();
Red.AddTimeValue( 0.00, 1.0 );
Red.AddTimeValue( 1.00, 0.64 );
Red.AddTimeValue( 2.00, 0.1 );
Red.AddTimeValue( 2.50, 0.0 );
Red.AddTimeValue( 3.00, 0.1 );
Red.AddTimeValue( 4.00, 0.64 );
Red.AddTimeValue( 5.00, 1.0 );
Red.AddTimeValue( 6.00, 0.64 );
Red.AddTimeValue( 7.00, 0.1 );
Red.AddTimeValue( 7.50, 0.0 );
Red.AddTimeValue( 8.00, 0.1 );
Red.AddTimeValue( 9.00, 0.64 );
Red.AddTimeValue( 10.0, 1.0 );
Green.Init();
Green.AddTimeValue( 0.00, 0.0 );
Green.AddTimeValue( 0.00, 0.1 );
Green.AddTimeValue( 2.00, 0.64 );
Green.AddTimeValue( 2.50, 1.0 );
Green.AddTimeValue( 3.00, 0.64 );
Green.AddTimeValue( 4.00, 0.1 );
Green.AddTimeValue( 5.00, 0.0 );
Green.AddTimeValue( 6.00, 0.1 );
Green.AddTimeValue( 7.00, 0.64 );
Green.AddTimeValue( 7.50, 1.0 );
Green.AddTimeValue( 8.00, 0.64 );
Green.AddTimeValue( 9.00, 0.1 );
Green.AddTimeValue( 10.00, 0.0 );
Blue.Init();
Blue.AddTimeValue( 0.00, 0.0 );
Blue.AddTimeValue( 1.00, 1.0 );
Blue.AddTimeValue( 2.00, 0.0 );
Blue.AddTimeValue( 3.00, 1.0 );
Blue.AddTimeValue( 4.00, 0.0 );
Blue.AddTimeValue( 5.00, 1.0 );
Blue.AddTimeValue( 6.00, 0.0 );
Blue.AddTimeValue( 7.00, 1.0 );
Blue.AddTimeValue( 8.00, 0.0 );
Blue.AddTimeValue( 9.00, 1.0 );
Blue.AddTimeValue( 10.00, 0.0 );
```That’s it! Thanks for reading!