Introduction

Author: Movania Muhammad Mobeen

Hello readers, In this article, we will learn how to port the 12th tutorial on Physics Collision Detection and Collision Response in OpenGL3.3. We saw in the last tutorial how to calculate realtime physics. We will extend our physics simulation by adding collision response. The collision response gives the reponse of an object in case of collision with another object. Among the other forces acting on the object, this is yet another force whose amount and direction are dependent on the convex hull of the object and the force with which the collision took place. The OpenGL rendering code, the geometry management and shaders for the meshes and AABB are identical to the last tutorial so we would not discuss them again here. The new addition to this tutorial is the collision reponse calculation in the main.cpp file.

Calculation of collision response (extension of the MainLoop)

The main loop is modified to handle the collision response by adding new variables for storing the current, last, elapsed time and collision result:

	void MainLoop(void)
	{
	   int i,j; // Counters
	   unsigned long l_start_time; // Start time for time based physics
	   unsigned long l_elapsed_time; // Elapsed time for time based physics
	   unsigned int l_frame_time; // Frame time for time based physics
	   char l_collision_value; // Collision result

Next, the frameworks events are handled.

	   // Events
	   FrameworkEvents(); // Process incoming events

This ensures that the application remains responsive to the user's input as well as the common window events and it does not stall. Next, the current time is obtained (using Framework_GetTicks function) and the display function (RenderDisplay) is called. Then, the elapsed time is calculated. This also gives us the time taken for the current frame (l_frame_time) and the remaining time (remaining_time) for physics calculation:

	   // Elapsed time calculation
	   l_elapsed_time=Framework_GetTicks()-l_start_time+remaining_time; // Elapsed time (we add also the previous remaining time)
	   l_frame_time=l_elapsed_time / msecxdframe; // Frames quantity we must cycle for physics
	   remaining_time=l_elapsed_time % msecxdframe; // Get the remaining time because we are working with integer values

Next, the physics loop is run which loops until all of the current frame's render time is used. It also increases the current physics fps counter. Then, it loops through each object and applies drag and dynamics forces on it:

	// Physics
	while (l_frame_time-->0) // Now do physics as many times as we need to match the elapsed time of the rendering phase
	{
	   fps_count_physics++; // Increase physics FPS counter

	   for(i=0;i< obj_qty;i++) //
	   {
	      ObjDrag(&object[i]); // Add Drag
	      ObjDynamics(&object[i],(float)1.0/(float)set_fps_physics); // Do dynamics
	   }

After the application of drag and dynamic forces on each object, the collision response calculation is initiated:

	   // Check for collisions: we check only the unique pair
	   for(i=0;i< obj_qty-1;i++)
	   {
	      for(j=i+1;j< obj_qty;j++)
	      {
             l_collision_value=ObjCollisionCheck(&object[i],&object[j]); // Check all the unique objects pairs
		     if (l_collision_value==2) // If the objects are colliding
		     {
		        ObjCollisionResponse(&object[i],&object[j]); // Collision response
			    FrameworkAudioPlayWave("sounds/impa1019.wav"); // Play a CRASH!
	   	     }
	      }
  	   }
	}

The first thing we do is identify a unique pair. This is done by iterating over all objects using two loops and identifying if any two objects have collided. If yes, the ObjCollisionCheck returns true. This function does the calculation based on the distance between the bounding spheres of the two objects. If this distance is less than the sum of their bounding sphere radii, there is a collision. Once there is a collision, the collision response is calculated. This calculation uses the two colliding objects' masses to adjust their linear velocities. After calculating the colliison response, we play the collision audio file to signify that the collision has taken place. Finally, the fps for display and physics calculation are recalculated and the counters are reset for the next frame:

	// Rendering and Physics FPS calculation
	if ((Framework_GetTicks()-last_ticks)>=1000) // Every second
	{
	   last_ticks = Framework_GetTicks(); // Save the current ticks to catch the next second
	   // Assings the current FPS count to the global variables
	   fps_physics=fps_count_physics;
	   fps_rendering=fps_count_rendering;
	   // Clear the local counters
	   fps_count_physics = 0;
	   fps_count_rendering = 0;
	}

Note that all of the functions calculating the physics like ObjDrag, ObjDynamics, ObjCollisionResponse etc. are based on physical laws and we are not discussing them here since this information is well desribed in elementary physics text.

Choosing between GLUT framework or SDL framework

The code in this and the subsequent tutorials has two frameworks to choose from. The glut framework that we developed in the last tutorial and the SDL framework that we developed in this tutorial. To use GLUT framework, you need to define the preprocessor FRAMEWORK_GLUT in your compiler setting. In Visual Studio 2008, you can go to Project -> Properties -> Configuration Properties-> C/C++ ->Preprocessor and add FRAMEWORK_GLUT to the preprocessor definitions. To enable SDL framework, define FRAMEWORK_SDL. Note that you can only use one framework at a time and not both. In addition, if you want to use the GLM matrix library, add the preprocessor USE_GLM otherwise the spacesimulator.net's matrix library is used. Running the code gives us the following output. You may press the 'w','a','s','d' keys along with several other keys to transform the camera and see the result:

Tut collisiondetection opengl3d3.png

SOURCE CODE

The Source Code of this lesson can be downloaded from the Tutorials Main Page