C++ 2D and 3D Animation

Cover Photo
Animated sequence of planets resembling the scene from Star Wars Episode VI.

Background

As part of a final assignment in my Introduction to C++ Class in my senior year of high school, we were supposed to write a program to generate a simple 2D animation. After the class, I decided to expand on my animation and build a more complicated 2D model.
After developing all of this, I thought I was finished with the project until early October of 2016, when I attended a Pixar tech talk at UC Berkeley. I was inspired to continue my work, and decided to develop a very simple model of 3D spheres in space. While I wanted to start working with OpenGL and other libraries for graphics, I decided to first pursue understanding the basics of graphics by implementing some small things in my own way. I calculated and created the algorithms for the 3D effects on the circles myself. I'm sure they've been used before, and they definitely are not industry standard at all, but I pushed myself to imagine how to make circles appear 3D from various light source points, and I succeeded as displayed in the animation.

Animation Description

The animation I developed is a miniature model of scenes from Star Wars. It starts with a Sun near the middle of the screen at a user specified point, a blue planet revolving around the Sun, a moon revolving around the planet, and a moon revolving around the first moon. There is also a second planet revolving around the sun, but this planet is a magenta color and it has a few rings around it, making it seem like a gas giant planet in our solar system. There are randomly generated stars that cover the background as well. In the top right corner, there is a Death Star shape, which later fires a green laser towards Alderan, the planet in the top left of the screen. The green laser destroys the planet Alderan. While all this is happening, a spaceship squadron left the magenta planet at the beginning of the animation, and travels in an elliptical orbit, reaching the same x-position as the Death Star. Then, the squadron travels in a straight line to reach the Death Star. Once they reach, two spaceships exit the Death Star, while one stays behind. This symbolizes Luke Skywalker staying behind in the Death Star in Episode 6 to finish up some family business. The moon of the planet is continuously shooting shots at the Death Star every time it approaches the top of the orbit. 3/4 of the way through the animation, the third space ship leaves the Death Star and it begins to shrink into its destruction. It flashes red and grey while shrinking until it disappears. The planets and moons remain in motion throughout and stop shooting at the Death Star because it no longer exists..

Algorithms

To draw the circles, I used the distance formula to find the pixels surrounding the center point that should be colored, and then went on to color them. In the beginning, I was scanning through the entirety of the frame to find the pixels to shade. However, I found that it would be more efficient to define the possible area first, and then scan that area only. To do this, I calculated the minimum and maximum X values, and the maximum Y value. The minimum Y could not be used because a segmentation fault was returned when defining the array location with a variable, so I ended up using 0. I called this the "Predictive Pixel Method". Even so, my program went from generating 1 frame every 3.3 seconds, to 1 frame every 0.136 seconds, or the equivalent of 7.3 frames per second. With it, I measured the time to draw the stars, the time to draw the whole frame, and the time to draw all the frames. The massive change in efficiency in generating the frames showed me the power of using algorithms to make the production of graphics far more efficient. The minute long animation that once took nearly 2 hours now could be finished in just 4 minutes. With improved efficiency, this program could even be used to render animations in real-time. I implemented this Predictive Pixel Method to all the shapes I drew, including the rectangles and spaceships. The rectangle class uses a simplified distance formula to draw the pixels in the specified length and width. It is essentially what the Predictive Pixel Method uses to define the possible locations of the shape's pixels. To draw the spaceship in the TShip class, I implemented one circle as the body and two rectangles for the wings. To model the circular and elliptical paths, I used the parametric equations of a circle and ellipse with the independent variable as the angle. (Circle: x=rcos(theta), y=rsin(theta)) (Ellipse: x=Acos(theta), y=Bsin(theta)). To determine the time to shoot the lasers, I divided the 360 degrees by the angular speed to determine at which frequency to fire the laser from the moon to the Death Star. Majority of the locations except the Sun are all relative to the given parameters set by the user. The user sets the Sun's location and the frame size. For example, the Death Star is a certain distance away from the top right of the screen. The planets are a variable distance away from the Sun, and so on. I used a random number generator to determine the position and the intensity of the stars.

Extra Info

Made between January 10th, 2016 and October 26th, 2016. Written in C++ with the use of no C++ libraries. ImageMagick was used in the command line to convert bmp images to jpeg files, and to combine the image files into an animated mp4.

Shivam
Shivam Parikh Software Engineer at Flexport. UC Berkeley Class of 2020 - Computer Science, Data Science, Environmental Economics and Policy. Avid photographer, engineer, and community member.

Related Posts