OpenGL Physics Engine

by Michael Brandon Williams


About:

    This project has been written in C++, using OpenGL for the graphics, and compiled in Microsoft Visual Studio C++ 6.0. The physics engine is object oriented, contains 14 mathematics and physics related classes, and over 10,000 lines of code. Some classes have been written despite the fact they exist (in some form) in the Standard Template Library. This was not my attempt at being a nonconformist; the purpose of the project is for me to utilize object oriented programming to the best of my knowledge, and creating my own classes was a major part of that.
     The purpose of this project was to create an interface in which the programmer could use physical elements (rigid bodies, springs, particles) to create simulations in an easy and controlled manner. The engine is not meant to be used on large games or applications because it is not fast or accurate enough. But, it was meant to be used to test physics simulations to approximate the outcome, use on small games, and just have fun with.
    The engine is entirely 2D but the program is run in a 3D environment in order for the user to see things from every angle. The viewing system is controlled with my Camera class; once again I am not dismissing the inherent functions of OpenGL but simply learning how to write my own before I choose to use the obviously better method.
Features:

- Point masses are simulated with a particle class by specifying its mass
- You can add forces to act on the particles
- 2D rigid bodies are simulated with a rigid body class by specifying a density and a   position for the body's vertices
- Surface area, mass, center of mass, and moment of inertia of rigid bodies are   calculated dynamically depending on where you place the body's vertices
- Convex and concave shapes can be used for the rigid bodies
- You can add forces to act on the rigid bodies by specifying the point on the body   the force is being applied to and the force vector itself
- Forces acting on the rigid bodies can be held in different coordinate systems   depending on how you want it to affect the body
- Collisions between rigid bodies and particles are all simulated
- Collision detection between any two arbitrary shapes
- Both particles and rigid bodies have different "states" they can be in depending on   if you want them to be static or kinetic
- Springs can be added to a system to act on rigid bodies or particles
- Springs can connect any combination of rigid bodies and particles
- Springs can connect to any point in a rigid body
- A Physical_Envrionment2D class has been made to provide a simple interface to   add objects to an environment and simulate it by calling only two methods (one for   the physics calculations and one for rendering)
- A gravitational constant can be added to an environment which causes all bodies to   be attracted to each other, modeled with Newton's Law of Gravitation
OpenGL:

I have used Nehe's Basecode II to initialize OpenGL in my applications. Since all the applications were very small the code on Nehe's site was perfect. It is very easy to use, and nicely comments the functions where your code should go.
Classes, Namespaces, Enumerations, and Structs:

This is a brief list of all the classes, namespaces, enumerations, and structs used in the engine.


Class Name Description
Array A class for handling resizable arrays in C++. Very similar to the STL Vector class except with a few addition methods.
Camera A Camera class to be used with OpenGL. The class provides methods for moving and rotating, and a method for setting the matrix in OpenGL so that all points set will be transformed.
Force2D Used mainly in the Rigid_Body2D class, this class handles two dimensional forces. The class uses two vectors to complete describe a force: one vector defining where the force is being applied and another defining the direction and magnitude of the force. The force can be held in three different coordinate systems depending on how you want the force to change as the position and orientation of a body changes.
Kinematic_Object2D This class specifies a physical object that has position, velocity, acceleration, orientation, angular velocity, and angular acceleration. This class should be used for objects that do not have forces applied to them and that cannot collide with other objects.
Matrix2x2 Handles all (or most) of the operations that can be performed on 2x2 matrices.
Matrix3x3 Handles all (or most) of the operations that can be performed on 3x3 matrices.
Particle This class specifies a physical object that has position, velocity, acceleration, and mass and can be defined as a single point. You can also add forces to act on the particle to affect its acceleration.
Physical_Environment2D This is a huge class that allows you to add, remove, change, and simulate multiple objects (rigid bodies, particles, kinematic objects, and springs) all in one shot. The interface provides an easy way of adding and changing objects. Once you have initialized your environment you can then simulate and render everything by calling two methods. This is the class the numerical integration calculations, collision detection, and collision handling.
Random_Number A simple class for generating random numbers.
Rigid_Body2D This class specifies a physical object that has position, velocity, acceleration, orientation, angular velocity, angular acceleration, mass, and moment of inertia and can be defined as a set of vertices that make up its shape. The user must set the density of the body as well as the position of its vertices. The class will calculate the surface area, mass, center of mass, and moment of inertia dynamically only given its density and position of its vertices.
Spring2D Models the forces applied to two objects by a spring. Springs can connect two rigid bodies, two particles, or any combination of the two.
String A class made to use strings easily in C++. The class is similar to the STL String class except for additional methods.
Vector2D A class for manipulating two dimensional vectors. Contains a few operations that I have never seen in other vector classes. The ideas for the overloaded functions came mainly from Bas Kuenen.
Vector3D A class for manipulating three dimensional vectors. Contains a few operations that I have never seen in other vector classes. The ideas for the overloaded functions came mainly from Bas Kuenen.
Namespaces Description
Math A namespace I stored all of my miscellaneous math functions and constants that did not exactly belong in any of my classes.
Key A namespace I stored the ASCII value of most of the keys on your keyboard to make it easier to retrieve key hits.
Enumerations Description
ID_TAG Used in the Force2D class for determining what coordinate system the force is held in.
PARTICLE_TYPE Used in the Particle class for determining if the particle is kinetic (moves) or static (still).
PARTICLE_COLLISION_
TYPE
Used in the Particle class for determining if the particle collides with other objects or not.
PHYSICAL_ENVIRONMENT_
STATUS
Used in the Physical_Environment2D class for determining if the system is playing or paused.
RIGID_BODY_ TYPE Used in the Rigid_Body2D class for determining the way the body moves. A rigid body can be either static, kinetic, or, a name stupid enough to be coined my yours truly, kinetic-static. A kinetic-static body is one that rotates but does not translate.
RIGID_BODY_COLLISION_
TYPE
Used in the Rigid_Body2D class for determining if the particle collides with other objects.
SPRING_CONNECTIONS Used in the Spring2D class for determining what types of objects the spring connects.
Screenshots and Demos:

    Here is a list of some sample simulations I have made with the engine. Each system took no more than fifteen lines of code using the library. To navigate the demos use W, A, S, and D to move the camera forward and to the sides, Q and Z to move up and down along the z-axis, and use the mouse to rotate the camera. The demos usually run faster when in fullscreen mode, but sometimes they go a little too fast. You may want to check out the affects in both fullscreen and windowed mode.

Small Scale Collision Samples
    Square - Square Collision
    Heptagon - Pentagon Collision
    Rectangle - Square Collision
    Convex - Concave Collision
    Concave - Concave Collision
    Multiple Collisions
Medium Scale System
 
    Simple 1D Spring
    Simple 2D Spring
    More Complicated Spring
    Two Objects and Springs 1
    Two Objects and Springs 2
    Three Body Gravity System
Large Scale Systems
    Plow
    Batting
    System 1
    System 2
To Do:

Because of the time constraints I was under to show some progress the physics engine is grossly unfinished. Fortunately, it is also apart of my assignment to finish and update the project as the year goes on (by the end of May). Here is a list of what seems to be implemented but isn't, what needs to be fixed, current bugs, and what will be implemented in the future. The files will be updated soon and I will keep a file history log.

What needs to be implemented:
- Collisions with rigid bodies and particles has not yet been implemented entirely. This is    the first thing that will be updated.
- Kinematic objects are not rendered when the member function Render is called in the    Physical Environment2D class.

What needs to be fixed:
- Objects cannot stack up on each other.
- Objects cannot rest on each other.

Bugs:
- Simultaneous collisions sometimes crashes the program.

Future implementations:
- The ability to create a rendering function for each of your objects so that you can control the    way your objects look.
- The use of joints in the environment.
Source Code:

The source is free to use or abuse under no restrictions. This was merely a school project and I have no intention of using this every again, as I hope to never take a computer science class again. I do not think my name appears anywhere on any of the sources either, so do not worry about using it. It may be a little hard to use it in one of your own projects, but if you do it will not bother me in the least.

Download Source Code (63 kb)