Spinning Cube and Collision Detection

Every OpenGL beginner must have written this code somehow.

This post contains the sourcecode and description of how I implemented the spinning cube project.

The source code is available here: cubecollision

ScreenShot of the program

ScreenShot of the program

To use this sourcecode:

  1. Open ./Windows/ogldev.sln and build the program.
  2. Cube is transparent.
  3. Control keys: 0,1,2,3,4,5,6,7, corresponding to 8 corners of the cube.
  4. Program referencing to the tutorial at http://ogldev.atspace.co.uk/
  5. Collision detected by checking vertices coordinates.

For every update, we need to update the location of the 8 vertices of the cube.

The update function:

void Update(){
    	m_translate.m[0][3] = m_translate.m[0][3] + v_velocity.x * dt;
		m_translate.m[1][3] = m_translate.m[1][3] + v_velocity.y * dt;
		m_translate.m[2][3] = m_translate.m[2][3] + v_velocity.z * dt;

		float angularVelocity = sqrt(v_angularVelocity.x* v_angularVelocity.x + v_angularVelocity.y * v_angularVelocity.y
			+ v_angularVelocity.z * v_angularVelocity.z);
		float u = v_angularVelocity.x, v = v_angularVelocity.y, w = v_angularVelocity.z;
		rotate_angle = (angularVelocity*dt + rotate_angle);
		m_rotate.m[0][0] = (u*u + (v*v + w*w)* cosf(rotate_angle))/(angularVelocity*angularVelocity); 
		m_rotate.m[0][1] = (u*v*(1- cosf(rotate_angle))- w*angularVelocity*sinf(rotate_angle))/(angularVelocity*angularVelocity); 
		m_rotate.m[0][2] = (u*w*(1-cosf(rotate_angle)) + v*angularVelocity*sinf(rotate_angle))/(angularVelocity*angularVelocity); 
		m_rotate.m[1][0] = (u*v*(1-cosf(rotate_angle))+ w*angularVelocity*sinf(rotate_angle))/(angularVelocity*angularVelocity);
		m_rotate.m[1][1] = (v*v + (u*u + w*w)*cosf(rotate_angle))/(angularVelocity*angularVelocity);
		m_rotate.m[1][2] = (v*w*(1-cosf(rotate_angle))-u*angularVelocity*sinf(rotate_angle))/(angularVelocity*angularVelocity);
		m_rotate.m[2][0] = (u*w*(1-cosf(rotate_angle))-v*angularVelocity*sinf(rotate_angle))/(angularVelocity*angularVelocity);
		m_rotate.m[2][1] = (v*w*(1-cosf(rotate_angle))+u*angularVelocity*sinf(rotate_angle))/(angularVelocity*angularVelocity);
		m_rotate.m[2][2] = (w*w + (u*u + v*v)*cosf(rotate_angle))/(angularVelocity*angularVelocity);

		m_transform = m_translate * m_rotate * m_rotate_old;

		Check_Collide();

		clock_t newTime = clock();
		clock_t duration = newTime- Time;
		delta_time = duration/ (double) CLOCKS_PER_SEC;
		//if (v_velocity.y > 0.05f || m_translate.m[1][3] >= -0.74)
		//	v_velocity.y = v_velocity.y - 0.1f * delta_time;  // g = 0.1
		//else 
		//	v_velocity.y = 0.f;
	}

Where we update the rotation matrix, angular velocity and rotation angle. After that we calculate the transformation matrix.

To check whether the inner cube is going to collide with the outer cube, I use the following code:

void Check_Collide(){
......

	for(int i= 0; i <= 7; i++){
		Vertices_new.x = Vertices[i].x * m_transform.m[0][0] + Vertices[i].y * m_transform.m[0][1] +
			Vertices[i].z * m_transform.m[0][2] + 1 *  m_transform.m[0][3];
		Vertices_new.y = Vertices[i].x * m_transform.m[1][0] + Vertices[i].y * m_transform.m[1][1] +
			Vertices[i].z * m_transform.m[1][2] + 1 *  m_transform.m[1][3];
		Vertices_new.z = Vertices[i].x * m_transform.m[2][0] + Vertices[i].y * m_transform.m[2][1] +
			Vertices[i].z * m_transform.m[2][2] + 1 *  m_transform.m[2][3];
    
    if(Vertices_new.x > 1.0f || Vertices_new.x < -1.0f || Vertices_new.y > 1.0f || Vertices_new.y < -1.0f||
		Vertices_new.z > 1 || Vertices_new.z < -1){
			Vertices_flag = i;
			break;
			}
		}
......
	}

What it does is to update the location of the vertices and check the boundary. If collision is detected, then a force in the opposite direction would be added onto that vertices. Angular velocity and velocity would be updated.

If additional force is added via user interaction, then add_force would be invoked:

void addForce(int i){
	Vector3f Centroid;
	Vector3f Vertices_new;
	Centroid.x = m_transform.m[0][3];
	Centroid.y = m_transform.m[1][3];
	Centroid.z = m_transform.m[2][3];

    Vertices_new.x = Vertices[i].x * m_transform.m[0][0] + Vertices[i].y * m_transform.m[0][1] +
	Vertices[i].z * m_transform.m[0][2] + 1 *  m_transform.m[0][3];
	Vertices_new.y = Vertices[i].x * m_transform.m[1][0] + Vertices[i].y * m_transform.m[1][1] +
		Vertices[i].z * m_transform.m[1][2] + 1 *  m_transform.m[1][3];
	Vertices_new.z = Vertices[i].x * m_transform.m[2][0] + Vertices[i].y * m_transform.m[2][1] +
		Vertices[i].z * m_transform.m[2][2] + 1 *  m_transform.m[2][3];

	v_velocity.x = 10.f * abs(Vertices_new.x - Centroid.x) + v_velocity.x;
	v_velocity.z = 10.f * abs(Vertices_new.z - Centroid.z) + v_velocity.z;
	v_velocity.y = 10.f * abs(Vertices_new.y - Centroid.y) + v_velocity.y;
}

 

About buttonzzj

Root~
Bookmark the permalink.

Leave a Reply