CollisionSim
Collision Detection in Three Dimensions




sphere explosionchain reaction





About CollisionSim:

     The goal of this project is to demonstrate real time collision detection in three dimensions. The simulator does this by allowing the user to set up a scene how they wish, adding an arbritrary number of objects determined and customized by the user. It then uses various ray tracing techniques and a simplified physics model  to simulate collisions between objects in real time. To evaluate the system, numererical integration (Euler) is used.  Ultimately, it was my goal to simulate collision detection between complex objects with a very realistic physics model, however I soon came to realize that I did not have time enough to do everything I had hoped. Also, after researching a bit on 3D collision detection methods, I found that most algorithms for complex shape collision detection rely on either axis-aligned bounding boxes (AABBs) or opposing-face algorithms, neither which would fit well into what I had planned for the preliminary steps of the program. However, although I had to scale back some of the originally anticipated features, the result is still an interesting and veratile simulation environment with great usability.
   
    At the core of the simluation is the collision detection algorithm. What it must do is decide whether any objects within the scene will hit each other between and a given time step value, and if so at exactly when. It does this several ways, depending on the types of objects it is evaluating. The simplist example and the easiest to get working by far was a moving sphere and a plane. Since planes have to edges to speak of, I could simply solve for the time at which a ray representing the ball intersected the surface described by a point and a normal, throwing out any time values which were past the given time step or negative (meaning the collision already happened). This solution does have a couple special cases, however. I check the dot product of the ray velocity and the plane normal and make sure it isn't zero or positive, meaning the ray plane are parallel or diverging. This helps throw out many cases without having to compute them. There is one detail I have left out, however, which is the actual process of representing a moving sphere with a ray. In order to properly detect the collision, we must be checking for the point on the sphere which will intersect the plane first, not the center. In order to find that point, I simply scaled the plane normal by the -(ball radius). This point along with the velocity vector of the sphere are enough to represent it as a ray. The next case, an intersection between two moving spheres, is a little more difficult. For this case, I used the common trick of treating the second ball as stationary and the first as having a velocity vector equal the the balls' relative velocities. The first two cases I check for are the relative velocity dot the relative position being zero or greater than one, meaning either there is no change in their distance over time or they are diverging. If neither of those are true, then I check to see if a ray defined by the first ball's center and the relative velocity is within a distance of the sum of the radii of the center of the second sphere. If so, then I must determine if the collision happens after, before or during the given time step. To do this, I resort to a second numerical integration over the time step. I know mathmatical solutions to the problem exist, however I did not have enough time to expirement with implimenting them after I had this working... Thus, unfortunately, this is the routine which makes or breaks the performance of the simulator. Since most the simulations involve a high number of moving spheres, most the physics loop is spent here meaning the number of ealy cases I can throw out and the secondary integration step are critical to performance. I settled on a rather large step, which means that while performance is pretty good, collisions between spheres are not nearly as accurate as they could be. This can be observed by noticing the difference between a sphere sitting stationary on a plane, where it is always perfectly intersecting the surface, and a ball sitting on top of another ball, where it will hover and 'bounce' slightly because the detected collision time is only as accurate as the integration step. Another choice in this function turned out to be more important than it seemed at the time, throwing out collisions between spheres which may be intersecting yet are diverging means that two objects can occupy the same space. This is probably the function which went through the most changes during development, and I experimented with a few different ways of handling the sphere collision. I settled on this method because of a) the fact that the interface makes it really easy to create two objects occupying the same space, and otherwise I'd have to delete all user created objects which accidentally might intersect or handle the problem some other way and b) the interesting effects which this method allowed me to produce. For instance, the top two pictures were both taken of a scene in which a high number of spheres were originially placed at the center, with velocities generated by random spherical coordinates. As the simulation begins, the spheres begin expanding in a nice... well, spherical shape (that is, until they begin hitting things!) 
    This brings me to the last type of collision detection implimented by the simulator, which unfortunately does not work as nicely as the other two. This is the collision between a ball and a rectangular prism. Since this shape has edges past which the ball will not collide with it, I have to also check for the collision point being within the volume of the prism, after the regular sphere-plane intersection test. However, this solution is not totally complete as it does not provide any means to check for intersection between spheres and the edges of the prism. Since planes have no edges, I cannot get away with simply doing planar tests and bounds checking the results. There needs to be a secondary check, which finds the case where the sphere fails the first test yet still intersects an edge (think of a sphere rolling off the surface of a table- as it rolls off, the moment its center is not directly above the surface, it cannot be touching it - however it is touching the edge, until the distance from the center to the edge is greater than the radius.)  I attempted to impliment this by representing the edge as a line segment, and checking the intersection of the all-to-familiar ray representing the moving sphere. However, my solution seems extremely slow and only worked in about half the cases (or very sporadically), so for performance reasons I decided to comment out the checks completely. Perhaps with just a bit more time the routine would have worked, but since it doesn't there are some times when the simulator very obviously misses a collision between a sphere and a prism, or even allows a sphere to pass completely through through a prism if it approaches the edge just right.

    The other half to the simulation is the physics model. It is not too complicated, but it adapts well to many situations and is very customizable. The only force which acts upon the spheres is gravity, which is user defined. Thus the simulator has only to model the effect of this force on the balls over time, given the user-defined initial velocity vectors and collision detection algorithm. To do this I use Euler integration. I track the time since the last frame render, then integrate over that time period using the user-defined integration step, remembering to calculate the remaining fraction of time smaller than a time step. Over each of these integration steps, I adjust velocities for the forces acting upon them (gravity), then check to see if any collisions happen within the remaining time step. If so, I advance the simulation to the collision time, calculate the reflected velocities based on the objects (including their mass - see picture below) and the friction coefficient, then check for collisions again using the remainder of the time step after the collision until the time step has been reduced to zero. If there are no collisions, I simply advance each object by the amount of time in the time step, and repeat the process with another step until I have caught up with the frame render time. Besides the integration step, the user can customize another parameter which affects this process, the time skew factor. What this variable does is stretch or shrink the measured time value, in order to speed up or slow down the simulation. Since it is independent of the integration step, the user can use the time skew to adjust the simulation speed without affecting accuracy. Meaning, the frame rate can be improved by evaluating less and slowing things down (decreasing time skew.) With a minimal time skew value and the largest integration step, over 400 spheres can be simulated at an interactive framerate on a decent machine. At the other end of the scale, the user can  specify parameters accurate enough to realisticly simulate effects such as a stack of spheres toppling over (see images below and the video clip at the bottom of the page.) Since creating a specifying the parameters for 100s of spheres in a scene is extremely tedious, there are various preset scenes which the user may load to watch or play with and alter - which brings me to the user interface guide.


stack1stack2stack3mass matters



User Interface:

    Using the simulator is pretty straightforward, but there are a couple things you need to know off the bat or it may seem a bit confusing. First off, the pause/break key will start/stop the simulation. Note that you have to have the simulation window active (not object settings or simulation parameters windows) for this to work (FLTK's keyboard event model seems a little convoluted to me.) Once you know this, you can easily load preset scenes through the preset menu and load them (by clicking the load button, if that wasn't obvious) to watch.
    Now might be a good time to introduce the camera controls.  To rotate the camera, click somewhere in the scene (not in empty space or on an object) and drag with the left mouse button. This will manipulate the quaternion-based trackball. Currently the trackball suffers from gimbal lock when the user has rotated such that the camera is looking straight down the y axis from above with no rotation about the y axis, which, ironically, was not a problem of the trackball before I converted the class to a quaternion vs. Euler angle model.  To translate the scene in the xy window plane, click and drag with the right mouse button the same as for rotation. Dragging with the middle mouse button will controll the zoom (z translation.)
    Now that you can simulate preset scenes and alter the camera, you may want to be able to manipulate scenes yourself! To insert a new ball into a scene, click the new ball button (the one with a ball and a red plus sign, again if that wasn't completely obvious.) If no ball is currently selected, a ball with default parameters is placed at the center of the scene. If a ball is currently selected, an exactly copy of it is placed where the selected ball is (you won't see anything happen.) You can click on the selected ball to seperate it from the identical newly created ball and do what you want with it. To manipulate a ball, select it by clicking it with any mouse button. Once selected, you can drag with the left button to translate it in the xy window plane (the mouse coordinates are unprojected into world space coordinates so that this translation vector always acts as the user expects it),  the middle button to translate it along the z axis (again, unprojected), or drag with the right button to increase the radius (and mass) of the ball. Manipulating boxes (recangular prisms)  within the scene is pretty similar. The only difference is that you must use the object settings window to change box size, the mouse is only for translation. The object settings window can be accessed by highlighting an object and clicking the object settings button. If the object is deselected, the proper settings window is brought up for the newly selected object, or it is close if nothing is selected. Here you can see the actual values for the object parameters, and adjust them manually if you like. If you wish to use the mouse and settings window at the same time, that's ok, they stay current with each other. Note that you have to click the 'apply' button to actually adjust the settings, if you close the window or manipulate the object with the mouse your typed in values will disappear.  If you decide you're tired of an object you can get rid of it by clicking the delete (X) button.
    Besides manipulating the objects within a scene, you can alter the parameters for the physics simulation itself. To do so, click the sim settings button to bring up the Simulation Settings window. Here you can change the time skew, integration step, friction coefficient (note that when it is set to one certain optimizations are implimented, so altering this value will affect performance),  gravity vector and specify whether to draw the velocity vectors of objects while simulating (they are always drawn while paused.)
    That about wraps up my introduction to the user interface, I'm pretty sure I covered everything. Remember you can resize the window, and quit either through the file menu or by closing the window.


Known Problems/Bugs:

  
* Trackball rotation suffers from gimbal lock in rare cases.

    * Focus may still not be properly returned to simulation window with certain buttons (requires user to manually click on window)

    * Simulation of friction is rather fast and dirty, it can cause problems in situations where one ball on top of another ball should roll off but doesn't, or does so too slowly because each frame the velocities are being scaled down by the same friction coefficient regardless of the relative speed of the balls.

    * Due to the 100% detection nature of the collision detection algorithm (it never throws out a collision it can find), extremely complex scenes have the possibility of generating the occasional exception due to overflow. (This may have been corrected, it is difficult to say due to the elusive nature of the problem.)

    * Edge collisions were not sufficiently implimented and thus are removed. In general, it is not very noticable, but in certain cases this omission is very obvious.

   




Downloads:

Windows Installer

Spherical Explosion - requires XViD MPEG-4 codec
Toppling Stack        - requires XViD MPEG-4 codec

Spherical Explosion - (no XViD)
Toppling Stack        - (no XViD)