/*
	Wheels Of Steel
	Copyright (c) 2006, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   GameObjectManager
// Purpose:      Keeps track of all the objects in the game. Handles things like
//               spatial partitioning (assigning objects to track sections) and
//               collision detection, gravity, and event dispatching
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

#include "GameObjectManager.h"

//------------------------------------------------------------------------------
// Static initialisers
//------------------------------------------------------------------------------

unsigned int    GameObjectManager::objCountStatic                       = 0;
unsigned int    GameObjectManager::objCountMoving                       = 0;
unsigned int    GameObjectManager::objCountDelayedDeletes               = 0;
GameObject *    GameObjectManager::objArrayStatic[MAX_OBJECTS]          = {0};
GameObject *    GameObjectManager::objArrayMoving[MAX_OBJECTS]          = {0};
GameObject *    GameObjectManager::objArrayDelayedDeletes[MAX_OBJECTS]  = {0};
Track *         GameObjectManager::track                                = 0;
bool            GameObjectManager::movingAllObjects                     = false;

//------------------------------------------------------------------------------
// Static helper variables:
//
// Not good practice doing things like this, but these need only be updated once
// for every frame, and I don't want the overhead of passing them between functions,
// or dereferencing pointers constantly, hence the reason they are stuck here.
// Speed of the collision detection system is paramount, and micro-optimisations do
// matter since it is carried out on so many objects.
//
//------------------------------------------------------------------------------

float GameObjectManager::frictionAir    = 0;            // friction multiplier for slowdown in the air
float GameObjectManager::frictionTrack  = 0;            // friction multiplier for slowdown when on the track
float GameObjectManager::frictionGround = 0;            // friction multiplier for slowdown when in the grass
float GameObjectManager::frameTime      = 0;            // Time the last frame took in seconds
float GameObjectManager::gravity        = 0;            // Amount of downwards pull to apply for this frame

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::initObjects
Purpose:  Initialises the game object manager and sets all objects to null
Params:   The games track that all the objects are contained int
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::initObjects(Track * track)
{
    // Set all slots in the object arrays as null

    for ( unsigned int i = 0 ; i < MAX_OBJECTS ; i++ )
    {
        objArrayStatic[i] = 0;
        objArrayMoving[i] = 0;
    }

    // Set the number of objects to zero

    objCountStatic = 0;
    objCountMoving = 0;

    // Save reference to the track containing the game objects

    GameObjectManager::track = track;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::freeObjects
Purpose:  Deletes all the objects in the game object managers internal array
          and sets all references to objects as null
Params:   none
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::freeObjects()
{
    // Delete all valid non null objects in the static array and set pointers to null

    for ( unsigned int i = 0 ; i < objCountStatic ; i++ )
    {
        // delete object and remove hanging pointer

        delete objArrayStatic[i]; objArrayStatic[i] = 0;
    }

    // Delete all valid non null objects in the moving array and set pointers to null

    for ( unsigned int i = 0 ; i < objCountMoving ; i++ )
    {
        // delete object and remove hanging pointer

        delete objArrayMoving[i]; objArrayMoving[i] = 0;
    }

    objCountStatic  = 0;       // Set number of objects to zero
    objCountMoving  = 0;       // Set number of objects to zero
    track           = 0;       // Remove reference to the the object's track
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::addObject
Purpose:  Adds a new object into the games internal array. Issues a error on failure.
Params:   Pointer to the object to add
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::addObject( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Abort if null pointer
    //--------------------------------------------------------------------------

    if ( object == 0 ) return;

    //--------------------------------------------------------------------------
    // See whether to add the object to the static or non static object arrays
    //--------------------------------------------------------------------------

    if ( object->moveable )
    {
        //----------------------------------------------------------------------
        // Moveable non static object
        //----------------------------------------------------------------------

        // abort if no more room in array

        if ( objCountMoving >= MAX_OBJECTS ) return;

        // Add object into next free array slot

        objArrayMoving[objCountMoving] = object;

        // Set object array position for fast deletes in future.

        object->mgrArrayPos = objCountMoving;

        // Increment object count for this array

        objCountMoving++;
    }
    else
    {
        //----------------------------------------------------------------------
        // Static non moveable object
        //----------------------------------------------------------------------

        // abort if no more room in array

        if ( objCountStatic >= MAX_OBJECTS ) return;

        // Add object into next free array slot

        objArrayStatic[objCountStatic] = object;

        // Set object array position for fast deletes in future.

        object->mgrArrayPos = objCountStatic;

        // Increment object count for this array

        objCountStatic++;
    }

    //--------------------------------------------------------------------------
    // Assign object to its section of the track
    //--------------------------------------------------------------------------

    assignTrackReference(object);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::delObject
Purpose:  Trys to remove the specified object from the managers internal array
Params:   Pointer to the object to delete
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::delObject( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Abort if null pointer
    //--------------------------------------------------------------------------

    if ( object == 0 ) return;

    //--------------------------------------------------------------------------
    // If currently moving all the objects then add the object to the delayed
    // deletion array..
    //--------------------------------------------------------------------------

    if ( movingAllObjects )
    {
        //----------------------------------------------------------------------
        // Only add to the delayed delete array if room.
        //----------------------------------------------------------------------

        if ( objCountDelayedDeletes < MAX_OBJECTS )
        {
            // Add object to the last slot of the delayed delete array

            objArrayDelayedDeletes[objCountDelayedDeletes] = object;

            // Increment the number of delayed delets

            objCountDelayedDeletes++;
        }

        //----------------------------------------------------------------------
        // Abort from any further deletion
        //----------------------------------------------------------------------

        return;
    }

    //--------------------------------------------------------------------------
    // See if static or non static object. affects which object array we look in
    //--------------------------------------------------------------------------

    if ( object->moveable )
    {
        //----------------------------------------------------------------------
        // Moveable object.
        //----------------------------------------------------------------------

        // If object is not part of the array then abort

        if ( object->mgrArrayPos < 0 ) return;

        // Otherwise swap the last object into this objects place

        objArrayMoving[object->mgrArrayPos] = objArrayMoving[objCountMoving-1];

        // Set the last object to null

        objArrayMoving[objCountMoving-1] = 0;

        // If object swapped was not null then set its new position in the array

        if ( objArrayMoving[object->mgrArrayPos] )
        {
            // Set the new position of the object in the array

            objArrayMoving[object->mgrArrayPos]->mgrArrayPos = object->mgrArrayPos;
        }

        // Remove the objects track reference. unssign it from a whatever track section its on

        removeTrackReference(object);

        // Delete the object

        delete object;

        // Decrement the number of objects in existance in the moving object array

        objCountMoving--;
    }
    else
    {
        //----------------------------------------------------------------------
        // Non moveable object.
        //----------------------------------------------------------------------

        // If object is not part of the array then abort

        if ( object->mgrArrayPos < 0 ) return;

        // Otherwise swap the last object into this objects place

        objArrayStatic[object->mgrArrayPos] = objArrayStatic[objCountStatic-1];

        // Set the last object to null

        objArrayStatic[objCountStatic-1] = 0;

        // If object swapped was not null then set its new position in the array

        if ( objArrayStatic[object->mgrArrayPos] )
        {
            // Set the new position of the object in the array

            objArrayStatic[object->mgrArrayPos]->mgrArrayPos = object->mgrArrayPos;
        }

        // Remove the objects track reference. unssign it from a whatever track section its on

        removeTrackReference(object);

        // Delete the object

        delete object;

        // Decrement the number of objects in existance in the static object array

        objCountStatic--;
    }

}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::assignTrackReference
Purpose:  Assigns the specified object to a track section based on its position
Params:   Pointer to the object to assign
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::assignTrackReference( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Figure out what section of the track the object is on
    //--------------------------------------------------------------------------

    // Quick divider

    static const float DIV_SECTION_SIZE_Z = 1.0f / Track::SECTION_SIZE_Z;

    // Get the objects section

    object->section = int(object->getPos_z() * DIV_SECTION_SIZE_Z);

    // Clamp to the number of sections

    if ( object->section >= int(track->getSections_count()) )
    {
        // Over array boundary: clamp

        object->section = track->getSections_count() - 1;
    }
    else if ( object->section < 0 )
    {
        // Under array boundary: clamp

        object->section = 0;
    }

    //--------------------------------------------------------------------------
    // Add this object to the section
    //--------------------------------------------------------------------------

    track->getSections_array()[object->section]->addObject(object);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::removeTrackReference
Purpose:  Removes the specified object from a track section based on its position
Params:   Pointer to the object to remove
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::removeTrackReference( GameObject * object )
{
    // Remove this object from the section

    track->getSections_array()[object->section]->delObject(object);
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::moveObjects
Purpose:  Moves all of the objects held by the manager and does collision
          checking and such.
Params:   Time the last frame took in seconds
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::moveObjects( float frameTime )
{
    //--------------------------------------------------------------------------
    // Update the static helper variables
    //--------------------------------------------------------------------------

    GameObjectManager::frameTime        = frameTime;                                // Time the last frame took in seconds
    GameObjectManager::frictionAir      = pow(Game::FRICTION_AIR   ,frameTime);     // friction multiplier for slowdown in the air
    GameObjectManager::frictionTrack    = pow(Game::FRICTION_TRACK ,frameTime);     // friction multiplier for slowdown when on the track
    GameObjectManager::frictionGround   = pow(Game::FRICTION_GROUND,frameTime);     // friction multiplier for slowdown when in the grass
    GameObjectManager::gravity          = Game::GRAVITY * frameTime;                // Amount of downwards pull to apply for this frame

    //--------------------------------------------------------------------------
    // Set the moving objects flag to true. All deletes will have to be deferred
    // until objects have finished moving: if this is not done problems may arise.
    //--------------------------------------------------------------------------

    movingAllObjects = true;

    //--------------------------------------------------------------------------
    // Pointer to the current object pointer in the moving objects array
    //--------------------------------------------------------------------------

    register GameObject ** array = objArrayMoving;

    //--------------------------------------------------------------------------
    // Move all of the objects in the managers internal array
    //--------------------------------------------------------------------------

    while ( * array )
    {
        //----------------------------------------------------------------------
        // Get local reference to object for speed
        //----------------------------------------------------------------------

        register GameObject * object = * array;

        //----------------------------------------------------------------------
        // Call the move function for the object
        //----------------------------------------------------------------------

        object->event_move(track,frameTime);

        //----------------------------------------------------------------------
        // Add the acceleration to the velocity of the object
        //----------------------------------------------------------------------

        object->vel_z += object->acl_z * frameTime;
        object->vel_y += object->acl_y * frameTime;
        object->vel_x += object->acl_x * frameTime;

        //----------------------------------------------------------------------
        // Set the objects acceleration to zero. If the object wants to accelerate
        // again it will set these values once more.
        //----------------------------------------------------------------------

        object->acl_x = 0;
        object->acl_y = 0;
        object->acl_z = 0;

        //----------------------------------------------------------------------
        // Do gravity for the object if applicable
        //----------------------------------------------------------------------

        if ( object->gravityAffected ) object->vel_y -= gravity;

        //----------------------------------------------------------------------
        // Apply air friction to the velocity of the object
        //----------------------------------------------------------------------

        object->vel_x *= frictionAir;
        object->vel_y *= frictionAir;
        object->vel_z *= frictionAir;

        //----------------------------------------------------------------------
        // Only do collision detection if the objects velocity is not zero
        //----------------------------------------------------------------------

        if ( object->vel_x != 0 || object->vel_y != 0 || object->vel_z != 0 )
        {
            //------------------------------------------------------------------
            // Remove reference to the object from its current track section
            //------------------------------------------------------------------

            removeTrackReference(object);

            //------------------------------------------------------------------
            // Define the structure what holds the neccessary information for
            // the object-to-object collision testing functions. Also go to
            // grammar school and be 'learned' how to write proper english.. : )
            //------------------------------------------------------------------

            static CollisionTestData collisionData;

            // Initialise the struct's values

            collisionData.xCollidee  = 0;  // no collision against an object along x axis
            collisionData.yCollidee  = 0;  // no collision against an object along y axis
            collisionData.zCollidee  = 0;  // no collision against an object along z axis

            collisionData.allowedX = object->pos_x + object->vel_x * frameTime;  // point the object is currently allowed to move to: x
            collisionData.allowedY = object->pos_y + object->vel_y * frameTime;  // point the object is currently allowed to move to: y
            collisionData.allowedZ = object->pos_z + object->vel_z * frameTime;  // point the object is currently allowed to move to: z

            //------------------------------------------------------------------
            // Get a null terminated list of potential colliders with this object
            //------------------------------------------------------------------

            register GameObject ** potentialColliders = getPotentialColliders(object);

            //------------------------------------------------------------------
            //
            // Check against each of the potential colliders. Only check in
            // certain directions depending on which way the object is moving.
            // Also, only check initially against solid objects. Non solid
            // objects will be checked if they cross the path of movement after.
            //
            //------------------------------------------------------------------

            //__________________________________________________________________
            // Check for collisions along the x axis
            //__________________________________________________________________

            if ( object->vel_x > 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is not solid

                    if ( (*p)->solid == false ) continue;

                    // Do collision checking against of right against this object

                    performObjectCollision_right
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }
            else if ( object->vel_x < 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is not solid

                    if ( (*p)->solid == false ) continue;

                    // Do collision checking against of left against this object

                    performObjectCollision_left
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }

            //__________________________________________________________________
            // Check for collisions along the y axis
            //__________________________________________________________________

            if ( object->vel_y > 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is not solid

                    if ( (*p)->solid == false ) continue;

                    // Do collision checking against of top against this object

                    performObjectCollision_top
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }
            else if ( object->vel_y < 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is not solid

                    if ( (*p)->solid == false ) continue;

                    // Do collision checking against of bottom against this object

                    performObjectCollision_bottom
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }

            //__________________________________________________________________
            // Check for collisions along the z axis
            //__________________________________________________________________

            if ( object->vel_z > 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is not solid

                    if ( (*p)->solid == false ) continue;

                    // Do collision checking against of front against this object

                    performObjectCollision_front
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }
            else if ( object->vel_z < 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is not solid

                    if ( (*p)->solid == false ) continue;

                    // Do collision checking against of back against this object

                    performObjectCollision_back
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }

            //------------------------------------------------------------------
            //
            // Now check if the non solid objects cross the path of movement of
            // the collider. If so then the collision event function will be
            // called on both the objects.
            //
            //------------------------------------------------------------------

            //__________________________________________________________________
            // Check for collisions along the x axis
            //__________________________________________________________________

            if ( object->vel_x > 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is solid

                    if ( (*p)->solid == true ) continue;

                    // Do cross checking against of right against this object

                    performObjectCrossCheck_right
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }
            else if ( object->vel_x < 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is solid

                    if ( (*p)->solid == true ) continue;

                    // Do cross checking against of left against this object

                    performObjectCrossCheck_left
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }

            //__________________________________________________________________
            // Check for collisions along the y axis
            //__________________________________________________________________

            if ( object->vel_y > 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is solid

                    if ( (*p)->solid == true ) continue;

                    // Do cross checking against of top against this object

                    performObjectCrossCheck_top
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }
            else if ( object->vel_y < 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is solid

                    if ( (*p)->solid == true ) continue;

                    // Do cross checking against of bottom against this object

                    performObjectCrossCheck_bottom
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }

            //__________________________________________________________________
            // Check for collisions along the z axis
            //__________________________________________________________________

            if ( object->vel_z > 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is solid

                    if ( (*p)->solid == true ) continue;

                    // Do cross checking against of front against this object

                    performObjectCrossCheck_front
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }
            else if ( object->vel_z < 0.0f )
            {
                //--------------------------------------------------------------
                // Go through the potential colliders array
                //--------------------------------------------------------------

                for ( GameObject ** p = potentialColliders ; *p ; p++ )
                {
                    // Abort test if object is solid

                    if ( (*p)->solid == true ) continue;

                    // Do collision checking against of back against this object

                    performObjectCrossCheck_back
                    (
                        object,             // collider
                        *p,                 // collidee
                        &collisionData      // collision testing data
                    );
                }
            }

            //------------------------------------------------------------------
            // See whether the collider as hit another object as it moves along
            // the x axis. Adjust velocities of both objects if so.
            //------------------------------------------------------------------

            if ( collisionData.xCollidee != 0 )
            {
                //______________________________________________________________
                //
                // Makey-uppy physics (TM) again...
                //
                // To figure out who gets what velocitys after collision i'm doing the following:
                //
                // Let the collider's velocity vector = vec1
                // Let the collidee's velocity vector = vec2
                // Let the collider's weight = weight1
                // Let the collidee's weight = weight2
                //
                // The velocity of the collider after collision is as follows:
                //
                // vec1 -= ( vec1 - vec2 ) * ( weight2 / weight1 )
                //
                // The velocity of the collidee after collision is as follows:
                //
                // vec2 += ( vec1 - vec2 ) * ( weight1 / weight2 )
                //
                // Thats basically it. It takes into account the the relative velocities of
                // the two objects and their weights and produces the output velocities.
                // Not a text book physics case again, but it does the job nicely...
                //
                //______________________________________________________________

                //--------------------------------------------------------------
                // Use these aliases just for the sake of tidyness..
                //--------------------------------------------------------------

                GameObject & collidee = * collisionData.xCollidee;
                GameObject & collider = * object;

                //--------------------------------------------------------------
                // Need to store the velocities for both objects here tempoarily
                // in order to get the correct result. bit like the usage of
                // tempoarary variables in matrix mutiplication. The original
                // unaltered values are needed to get the right result.
                //--------------------------------------------------------------

                float collider_vel_x = collider.vel_x;
                float collider_vel_y = collider.vel_y;
                float collider_vel_z = collider.vel_z;
                float collidee_vel_x = collidee.vel_x;
                float collidee_vel_y = collidee.vel_y;
                float collidee_vel_z = collidee.vel_z;

                //--------------------------------------------------------------
                // Figure out the collidee's new velocity- but only if it is
                // moveable and solid..
                //--------------------------------------------------------------

                if ( collidee.moveable && collidee.solid )
                {
                    collidee.vel_x += ( collider_vel_x - collidee_vel_x ) * ( collider.weight / collidee.weight);
                    collidee.vel_y += ( collider_vel_y - collidee_vel_y ) * ( collider.weight / collidee.weight);
                    collidee.vel_z += ( collider_vel_z - collidee_vel_z ) * ( collider.weight / collidee.weight);
                }

                //--------------------------------------------------------------
                // Figure out the colliders new velocity- but only if collidee is solid
                //--------------------------------------------------------------

                if ( collidee.solid )
                {
                    collider.vel_x -= ( collider_vel_x - collidee_vel_x ) * ( collidee.weight / collider.weight);
                    collider.vel_y -= ( collider_vel_y - collidee_vel_y ) * ( collidee.weight / collider.weight);
                    collider.vel_z -= ( collider_vel_z - collidee_vel_z ) * ( collidee.weight / collider.weight);
                }

                //--------------------------------------------------------------
                // Call the collision event routines on both objects involved in collision
                //--------------------------------------------------------------

                collidee.event_collision(&collider);
                collider.event_collision(&collidee);

            }   // end if ( collisionData.xCollidee != 0 )

            //------------------------------------------------------------------
            // See whether the collider as hit another object as it moves along
            // the y axis. Adjust velocities of both objects if so.
            //------------------------------------------------------------------

            if ( collisionData.yCollidee != 0 )
            {
                //______________________________________________________________
                //
                // Makey-uppy physics (TM) again...
                //
                // To figure out who gets what velocitys after collision i'm doing the following:
                //
                // Let the collider's velocity vector = vec1
                // Let the collidee's velocity vector = vec2
                // Let the collider's weight = weight1
                // Let the collidee's weight = weight2
                //
                // The velocity of the collider after collision is as follows:
                //
                // vec1 -= ( vec1 - vec2 ) * ( weight2 / weight1 )
                //
                // The velocity of the collidee after collision is as follows:
                //
                // vec2 += ( vec1 - vec2 ) * ( weight1 / weight2 )
                //
                // Thats basically it. It takes into account the the relative velocities of
                // the two objects and their weights and produces the output velocities.
                // Not a text book physics case again, but it does the job nicely...
                //
                //______________________________________________________________

                //--------------------------------------------------------------
                // Use these aliases just for the sake of tidyness..
                //--------------------------------------------------------------

                GameObject & collidee = * collisionData.yCollidee;
                GameObject & collider = * object;

                //--------------------------------------------------------------
                // Need to store the velocities for both objects here tempoarily
                // in order to get the correct result. bit like the usage of
                // tempoarary variables in matrix mutiplication. The original
                // unaltered values are needed to get the right result.
                //--------------------------------------------------------------

                float collider_vel_x = collider.vel_x;
                float collider_vel_y = collider.vel_y;
                float collider_vel_z = collider.vel_z;
                float collidee_vel_x = collidee.vel_x;
                float collidee_vel_y = collidee.vel_y;
                float collidee_vel_z = collidee.vel_z;

                //--------------------------------------------------------------
                // Figure out the collidee's new velocity- but only if it is
                // moveable and solid..
                //--------------------------------------------------------------

                if ( collidee.moveable && collidee.solid )
                {
                    collidee.vel_x += ( collider_vel_x - collidee_vel_x ) * ( collider.weight / collidee.weight);
                    collidee.vel_y += ( collider_vel_y - collidee_vel_y ) * ( collider.weight / collidee.weight);
                    collidee.vel_z += ( collider_vel_z - collidee_vel_z ) * ( collider.weight / collidee.weight);
                }

                //--------------------------------------------------------------
                // Figure out the colliders new velocity- but only if collidee is solid
                //--------------------------------------------------------------

                if ( collidee.solid )
                {
                    collider.vel_x -= ( collider_vel_x - collidee_vel_x ) * ( collidee.weight / collider.weight);
                    collider.vel_y -= ( collider_vel_y - collidee_vel_y ) * ( collidee.weight / collider.weight);
                    collider.vel_z -= ( collider_vel_z - collidee_vel_z ) * ( collidee.weight / collider.weight);
                }

                //--------------------------------------------------------------
                // Call the collision event routines on both objects involved in collision
                //--------------------------------------------------------------

                collidee.event_collision(&collider);
                collider.event_collision(&collidee);

            }   // end if ( collisionData.yCollidee != 0 )

            //------------------------------------------------------------------
            // See whether the collider as hit another object as it moves along
            // the z axis. Adjust velocities of both objects if so.
            //------------------------------------------------------------------

            if ( collisionData.zCollidee != 0 )
            {
                //______________________________________________________________
                //
                // Makey-uppy physics (TM) again...
                //
                // To figure out who gets what velocitys after collision i'm doing the following:
                //
                // Let the collider's velocity vector = vec1
                // Let the collidee's velocity vector = vec2
                // Let the collider's weight = weight1
                // Let the collidee's weight = weight2
                //
                // The velocity of the collider after collision is as follows:
                //
                // vec1 -= ( vec1 - vec2 ) * ( weight2 / weight1 )
                //
                // The velocity of the collidee after collision is as follows:
                //
                // vec2 += ( vec1 - vec2 ) * ( weight1 / weight2 )
                //
                // Thats basically it. It takes into account the the relative velocities of
                // the two objects and their weights and produces the output velocities.
                // Not a text book physics case again, but it does the job nicely...
                //
                //______________________________________________________________

                //--------------------------------------------------------------
                // Use these aliases just for the sake of tidyness..
                //--------------------------------------------------------------

                GameObject & collidee = * collisionData.zCollidee;
                GameObject & collider = * object;

                //--------------------------------------------------------------
                // Need to store the velocities for both objects here tempoarily
                // in order to get the correct result. bit like the usage of
                // tempoarary variables in matrix mutiplication. The original
                // unaltered values are needed to get the right result.
                //--------------------------------------------------------------

                float collider_vel_x = collider.vel_x;
                float collider_vel_y = collider.vel_y;
                float collider_vel_z = collider.vel_z;
                float collidee_vel_x = collidee.vel_x;
                float collidee_vel_y = collidee.vel_y;
                float collidee_vel_z = collidee.vel_z;

                //--------------------------------------------------------------
                // Figure out the collidee's new velocity- but only if it is
                // moveable and solid..
                //--------------------------------------------------------------

                if ( collidee.moveable && collidee.solid )
                {
                    collidee.vel_x += ( collider_vel_x - collidee_vel_x ) * ( collider.weight / collidee.weight);
                    collidee.vel_y += ( collider_vel_y - collidee_vel_y ) * ( collider.weight / collidee.weight);
                    collidee.vel_z += ( collider_vel_z - collidee_vel_z ) * ( collider.weight / collidee.weight);
                }

                //--------------------------------------------------------------
                // Figure out the colliders new velocity- but only if collidee is solid
                //--------------------------------------------------------------

                if ( collidee.solid )
                {
                    collider.vel_x -= ( collider_vel_x - collidee_vel_x ) * ( collidee.weight / collider.weight);
                    collider.vel_y -= ( collider_vel_y - collidee_vel_y ) * ( collidee.weight / collider.weight);
                    collider.vel_z -= ( collider_vel_z - collidee_vel_z ) * ( collidee.weight / collider.weight);
                }

                //--------------------------------------------------------------
                // Call the collision event routines on both objects involved in collision
                //--------------------------------------------------------------

                collidee.event_collision(&collider);
                collider.event_collision(&collidee);

            }   // end if ( collisionData.zCollidee != 0 )

            //------------------------------------------------------------------
            // Move the object to its allowed move point.
            //------------------------------------------------------------------

            object->pos_x = collisionData.allowedX;
            object->pos_y = collisionData.allowedY;
            object->pos_z = collisionData.allowedZ;

            //------------------------------------------------------------------
            // Do object collisions with the track after moving.
            //------------------------------------------------------------------

            performTrackCollision(object);

            //------------------------------------------------------------------
            // Add reference to the object on its now current track section
            //------------------------------------------------------------------

            assignTrackReference(object);

        } // end if ( all of object's xyz velocities are not zero )

        //----------------------------------------------------------------------
        // Move onto the next object pointer in the object array
        //----------------------------------------------------------------------

        array++;
    }

    //--------------------------------------------------------------------------
    // Done moving all objects: set the flag to false
    //--------------------------------------------------------------------------

    movingAllObjects = false;

    //--------------------------------------------------------------------------
    // Delete all objects in the delayed delete array..
    //--------------------------------------------------------------------------

    for ( register unsigned int i = 0 ; i < objCountDelayedDeletes ; i++ )
    {
        delObject(objArrayDelayedDeletes[i]);
    }

    //--------------------------------------------------------------------------
    // Set the number of delayed deletes back to zero if it is not already zero
    //--------------------------------------------------------------------------

    objCountDelayedDeletes = 0;

}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::getPotentialColliders
Purpose:  Returns a null terminated list of pointers to objects the object given
          could potentially colide with. This list is not permanent and should be
          used before the next call to this function. Object should also be removed from
          its own section before calling this, so as to avoid a self collision check..
Params:   Pointer to the object to return list for
Returns:  A null terminated list of objects the object could collide with

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

GameObject ** GameObjectManager::getPotentialColliders( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Secretly this is where the list is stored:
    //--------------------------------------------------------------------------

    static GameObject * colliders[TrackSection::SECTION_MAX_OBJECTS * 4] = {0};

    //--------------------------------------------------------------------------
    // Current list position, object section number and section pointer:
    //--------------------------------------------------------------------------

    register GameObject   **    listPosition = colliders;
    register unsigned           sectionNum   = object->section;
    register TrackSection *     section      = track->getSections_array()[sectionNum];

    //--------------------------------------------------------------------------
    // Add the gameObjects in object's the current section to the list
    //--------------------------------------------------------------------------

    for ( register GameObject ** obj = section->get_objects() ; *obj ; obj++ )
    {
        // Add this object to the list and increment list position

        *listPosition ++ = * obj;
    }

    //--------------------------------------------------------------------------
    // If possible add the colliders in the section behind to the list
    //--------------------------------------------------------------------------

    if  ( sectionNum > 0 )
    {
        // Set the track section pointer

        section = track->getSections_array()[sectionNum-1];

        // Add all the objects in this section to the list

        for ( register GameObject ** obj = section->get_objects() ; *obj ; obj++ )
        {
            // Add this object to the list and increment list position

            *listPosition ++ = * obj;
        }
    }

    //--------------------------------------------------------------------------
    // If possible add the colliders in the section in front to the list
    //--------------------------------------------------------------------------

    if  ( sectionNum < track->getSections_count() - 1 )
    {
        // Set the track section pointer

        section = track->getSections_array()[sectionNum+1];

        // Add all the objects in this section to the list

        for ( register GameObject ** obj = section->get_objects() ; *obj ; obj++ )
        {
            // Add this object to the list and increment list position

            *listPosition ++ = * obj;
        }
    }

    //--------------------------------------------------------------------------
    // Null terminate the list
    //--------------------------------------------------------------------------

    * listPosition = 0;

    //--------------------------------------------------------------------------
    // Return the list of potential colliders
    //--------------------------------------------------------------------------

    return colliders;
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performTrackCollision
Purpose:  Checks for a collision between the track section and the object given.
          Corrects object position if need be and adjusts its velocity and position.
Params:   Object to check for collision against the track.
Returns:  None

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performTrackCollision(GameObject * object)
{
    //--------------------------------------------------------------------------
    // See if the object is underneath or intersecting the track
    //--------------------------------------------------------------------------

    if ( object->pos_y - object->size_y * 0.5f < track->getY(object->pos_z) )
    {
        //----------------------------------------------------------------------
        // Object is underneath or intersecting the track: correct position
        //----------------------------------------------------------------------

        object->pos_y = track->getY(object->pos_z) + object->size_y * 0.5f;

        //----------------------------------------------------------------------
        // Get the objects section as a pointer:
        //----------------------------------------------------------------------

        TrackSection * section = track->getSections_array()[object->section];

        //----------------------------------------------------------------------
        // Makey-uppy physics (TM) ®
        //
        // Initially when deciding what to do with the object's y velocity I
        // decided to set it to zero when it hit a section of the road. This
        // done the job except when going downhill an awful ping-pong ball style
        // bouncing ensued. Since the downward velocity was set to zero on each
        // hit the car was able to float momentarily in the air before crashing
        // down and hitting the track. Not really what I wanted.
        //
        // A second attempt took into account the surface orientation using the
        // z value of the normal. For a completely flat section the velocity would
        // be set to zero, for a more sloped section it would be reduced by some amount.
        // This worked better but still the same problem happened.
        //
        // This third and final attempt does similarily but gets a very large root of
        // normal value and multiplies the velocity by this value. This reduces the
        // velocity loss for sloped surfaces somewhat and eliminates the ping pong motion
        // but still sets the downward velocity to zero on a completely flat surface.
        // Don't ask where this came from, its not based on any real world physics, rather
        // it was derived from experimenting with the numbers to get the sort results
        // I wanted. It works well in this context and thats good enough for me..
        //----------------------------------------------------------------------

        object->vel_y *= powf( fabs(section->get_normal_z()) , 0.05f );

        //----------------------------------------------------------------------
        // Determine from the objects x and z value whether it is off the road
        // or on the road. apply different amounts of friction and effects
        // accordingly...
        //----------------------------------------------------------------------

        if ( object->pos_x < track->getLX(object->pos_z) || object->pos_x > track->getRX(object->pos_z) )
        {
            //------------------------------------------------------------------
            // Object is is in the rough: apply ground friction amount
            //------------------------------------------------------------------

            object->vel_x *= frictionGround;
            object->vel_y *= frictionGround;
            object->vel_z *= frictionGround;
        }
        else
        {
            //------------------------------------------------------------------
            // Object is on the track: apply normal track friction
            //------------------------------------------------------------------

            object->vel_x *= frictionTrack;
            object->vel_y *= frictionTrack;
            object->vel_z *= frictionTrack;
        }

    } // end if ( object is under or intersects track )
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCollision_front
Purpose:  Checks for collision of the front of the collider against the back of
          the collidee. Updates collision data on a collision, if this object
          is the closest collider along the axis which they collide.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCollision_front
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the front of the collider at the allowed z is less than the back z
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedZ + collider->size_z * 0.5f
        <
        collidee->pos_z - collidee->size_z * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the front of the collider is already past the back of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_z + collider->size_z * 0.5f )
        >
        ( collidee->pos_z - collidee->size_z * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the front side of the collider
    // touches the plane formed by the back side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_z - collidee->size_z * 0.5f;
    percent -= collider->pos_z + collider->size_z * 0.5f;
    percent /= collider->vel_z * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the front points of the collider intersect the
    // plane formed by the back side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float xr;                                           // x value where front left  point of collider hits back plane of collidee
    float xl;                                           // x value where front right point of collider hits back plane of collidee

    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original front right x value of collider
    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original front left  x value of collider
    xr += collider->vel_x * frameTime * percent;        // move front right x to where it intersects the back plane of collidee
    xl += collider->vel_x * frameTime * percent;        // move front left  x to where it intersects the back plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the front points of the collider must be
    // within the bounding box x range of the collidee where we calculated they
    // intersect the back plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the left point within the x range ?

            ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
        )
        ||
        (   // Is the right point within the x range ?

            ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
        )

       )
    {
        // Set the new allowed z value to where the front of the collider hits the back of the collidee

        collisionData->allowedZ  = collidee->pos_z;
        collisionData->allowedZ -= collidee->size_z * 0.5f;
        collisionData->allowedZ -= collider->size_z * 0.5f;

        // Set the collidee as the object collided with along the z axis

        collisionData->zCollidee = collidee;
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCollision_back
Purpose:  Checks for collision of the back of the collider against the front of
          the collidee. Updates collision data on a collision, if this object
          is the closest collider along the axis which they collide.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCollision_back
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the back of the collider at the allowed z is greater than the front z
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedZ - collider->size_z * 0.5f
        >
        collidee->pos_z + collidee->size_z * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the back of the collider is already past the front of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_z - collider->size_z * 0.5f )
        <
        ( collidee->pos_z + collidee->size_z * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the back side of the collider
    // touches the plane formed by the front side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_z + collidee->size_z * 0.5f;
    percent -= collider->pos_z - collider->size_z * 0.5f;
    percent /= collider->vel_z * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the back points of the collider intersect the
    // plane formed by the front side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float xr;                                           // x value where back left  point of collider hits front plane of collidee
    float xl;                                           // x value where back right point of collider hits front plane of collidee

    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original back right x value of collider
    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original back left  x value of collider
    xr += collider->vel_x * frameTime * percent;        // move back right x to where it intersects the front plane of collidee
    xl += collider->vel_x * frameTime * percent;        // move back left  x to where it intersects the front plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the back points of the collider must be
    // within the bounding box x range of the collidee where we calculated they
    // intersect the front plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the left point within the x range ?

            ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
        )
        ||
        (   // Is the right point within the x range ?

            ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
        )

       )
    {
        // Set the new allowed z value to where the back of the collider hits the front of the collidee

        collisionData->allowedZ  = collidee->pos_z;
        collisionData->allowedZ += collidee->size_z * 0.5f;
        collisionData->allowedZ += collider->size_z * 0.5f;

        // Set the collidee as the object collided with along the z axis

        collisionData->zCollidee = collidee;
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCollision_left
Purpose:  Checks for collision of the left of the collider against the right of
          the collidee. Updates collision data on a collision, if this object
          is the closest collider along the axis which they collide.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCollision_left
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If            the left of the collider at the allowed x is greater than the right x
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedX - collider->size_x * 0.5f
        >
        collidee->pos_x + collidee->size_x * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the left of the collider is already past the right of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_x - collider->size_x * 0.5f )
        <
        ( collidee->pos_x + collidee->size_x * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the left side of the collider
    // touches the plane formed by the right side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_x + collidee->size_x * 0.5f;
    percent -= collider->pos_x - collider->size_x * 0.5f;
    percent /= collider->vel_x * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the left points of the collider intersect the
    // plane formed by the right side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float zf;                                           // z value where front left of collider hits right plane of collidee
    float zb;                                           // z value where back  left of collider hits right plane of collidee

    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front left z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  left z value of collider
    zf += collider->vel_z * frameTime * percent;        // move front left z to where it intersects the right plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  left z to where it intersects the right plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the left points of the collider must be
    // within the bounding box z range of the collidee where we calculated they
    // intersect the right plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the front within the z range ?

            ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
        )
        ||
        (   // Is the back within the z range ?

            ( zb <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zb >= collidee->pos_z - collidee->size_z * 0.5f )
        )

       )
    {
        // Set the new allowed x value to where the left of the collider hits the right of the collidee

        collisionData->allowedX  = collidee->pos_x;
        collisionData->allowedX += collidee->size_x * 0.5f;
        collisionData->allowedX += collider->size_x * 0.5f;

        // Set the collidee as the object collided with along the x axis

        collisionData->xCollidee = collidee;
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCollision_right
Purpose:  Checks for collision of the right of the collider against the left of
          the collidee. Updates collision data on a collision, if this object
          is the closest collider along the axis which they collide.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCollision_right
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the right of the collider at the allowed x is less than the left x
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedX + collider->size_x * 0.5f
        <
        collidee->pos_x - collidee->size_x * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the right of the collider is already past the left of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_x + collider->size_x * 0.5f )
        >
        ( collidee->pos_x - collidee->size_x * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the right side of the collider
    // touches the plane formed by the left side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_x - collidee->size_x * 0.5f;
    percent -= collider->pos_x + collider->size_x * 0.5f;
    percent /= collider->vel_x * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the right points of the collider intersect the
    // plane formed by the left side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float zf;                                           // z value where front right of collider hits left plane of collidee
    float zb;                                           // z value where back  right of collider hits left plane of collidee

    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front right z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  right z value of collider
    zf += collider->vel_z * frameTime * percent;        // move front right z to where it intersects the left plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  right z to where it intersects the left plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the right points of the collider must be
    // within the bounding box z range of the collidee where we calculated they
    // intersect the left plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the front within the z range ?

            ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
        )
        ||
        (   // Is the back within the z range ?

            ( zb   <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zb >= collidee->pos_z - collidee->size_z * 0.5f )
        )

       )
    {
        // Set the new allowed x value to where the right of the collider hits the left of the collidee

        collisionData->allowedX  = collidee->pos_x;
        collisionData->allowedX -= collidee->size_x * 0.5f;
        collisionData->allowedX -= collider->size_x * 0.5f;

        // Set the collidee as the object collided with along the x axis

        collisionData->xCollidee = collidee;
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCollision_bottom
Purpose:  Checks for collision of the bottom of the collider against the top of
          the collidee. Updates collision data on a collision, if this object
          is the closest collider along the axis which they collide.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCollision_bottom
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the bottom of the collider at the allowed y is greater than the top y
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedY - collider->size_y * 0.5f
        >
        collidee->pos_y + collidee->size_y * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is already past the top of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_y - collider->size_y * 0.5f )
        <
        ( collidee->pos_y + collidee->size_y * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the bottom side of the collider
    // touches the plane formed by the top side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_y + collidee->size_y * 0.5f;
    percent -= collider->pos_y - collider->size_y * 0.5f;
    percent /= collider->vel_y * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the points of the collider intersect the plane formed by
    // the top side of the collidee as they move along the velocity vector.
    //--------------------------------------------------------------------------

    float xl;                                           // x value where left  of collider hits top plane of collidee
    float xr;                                           // x value where right of collider hits top plane of collidee
    float zf;                                           // z value where front of collider hits top plane of collidee
    float zb;                                           // z value where back  of collider hits top plane of collidee

    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original left  x value of collider
    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original right x value of collider
    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  z value of collider

    xl += collider->vel_x * frameTime * percent;        // move left  x to where it intersects the top plane of collidee
    xr += collider->vel_x * frameTime * percent;        // move right x to where it intersects the top plane of collidee
    zf += collider->vel_z * frameTime * percent;        // move front z to where it intersects the top plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  z to where it intersects the top plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the following must be true:
    //
    // (a) either the left or right x values are in the x range of the collidees
    //     bounding box.
    //
    //     *AND*
    //
    // (b) either the front or back z values are in the z range of the collidees
    //     bounding box.
    //
    //--------------------------------------------------------------------------

    if (
         // Check that one of the points is in the z range of bounding box:

         (

            (   // Is the front within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
            ||
            (   // Is the back within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
         )

         &&

         // Check that one of the points is in the x range of bounding box:

         (

            (   // Is the left within the x range ?

                ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
            )
            ||
            (   // Is the right within the x range ?

                ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
            )
         )
       )
       {
            // Set the new allowed y value to where the bottom of the collider hits the top of the collidee

            collisionData->allowedY  = collidee->pos_y;
            collisionData->allowedY += collidee->size_y * 0.5f;
            collisionData->allowedY += collider->size_y * 0.5f;

            // Set the collidee as the object collided with along the y axis

            collisionData->yCollidee = collidee;
       }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCollision_top
Purpose:  Checks for collision of the top of the collider against the bottom of
          the collidee. Updates collision data on a collision, if this object
          is the closest collider along the axis which they collide.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCollision_top
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the top of the collider at the allowed y is less than the bottom y
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedY + collider->size_y * 0.5f
        <
        collidee->pos_y - collidee->size_y * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is already past the bottom of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_y + collider->size_y * 0.5f )
        >
        ( collidee->pos_y - collidee->size_y * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the top side of the collider
    // touches the plane formed by the bottom side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_y - collidee->size_y * 0.5f;
    percent -= collider->pos_y + collider->size_y * 0.5f;
    percent /= collider->vel_y * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the points of the collider intersect the plane formed by
    // the bottom side of the collidee as they move along the velocity vector.
    //--------------------------------------------------------------------------

    float xl;                                           // x value where left  of collider hits bottom plane of collidee
    float xr;                                           // x value where right of collider hits bottom plane of collidee
    float zf;                                           // z value where front of collider hits bottom plane of collidee
    float zb;                                           // z value where back  of collider hits bottom plane of collidee

    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original left  x value of collider
    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original right x value of collider
    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  z value of collider

    xl += collider->vel_x * frameTime * percent;        // move left  x to where it intersects the bottom plane of collidee
    xr += collider->vel_x * frameTime * percent;        // move right x to where it intersects the bottom plane of collidee
    zf += collider->vel_z * frameTime * percent;        // move front z to where it intersects the bottom plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  z to where it intersects the bottom plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the following must be true:
    //
    // (a) either the left or right x values are in the x range of the collidees
    //     bounding box.
    //
    //     *AND*
    //
    // (b) either the front or back z values are in the z range of the collidees
    //     bounding box.
    //
    //--------------------------------------------------------------------------

    if (
         // Check that one of the points is in the z range of bounding box:

         (

            (   // Is the front within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
            ||
            (   // Is the back within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
         )

         &&

         // Check that one of the points is in the x range of bounding box:

         (

            (   // Is the left within the x range ?

                ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
            )
            ||
            (   // Is the right within the x range ?

                ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
            )
         )
       )
       {
            // Set the new allowed y value to where the top of the collider hits the bottom of the collidee

            collisionData->allowedY  = collidee->pos_y;
            collisionData->allowedY -= collidee->size_y * 0.5f;
            collisionData->allowedY -= collider->size_y * 0.5f;

            // Set the collidee as the object collided with along the y axis

            collisionData->yCollidee = collidee;
       }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCrossCheck_front
Purpose:  Like the 'performObjectCollision_front' function, but instead of fixing
          the position of the collider it simply calls the collision event functions
          on both objects involved in the collision. Used on non-solid objects after
          collision checking with solid objects has been done, in order to check if
          the collider when moving along, crosses the bounding box of the collidee.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCrossCheck_front
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the front of the collider at the allowed z is less than the back z
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedZ + collider->size_z * 0.5f
        <
        collidee->pos_z - collidee->size_z * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the front of the collider is already past the back of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_z + collider->size_z * 0.5f )
        >
        ( collidee->pos_z - collidee->size_z * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the front side of the collider
    // touches the plane formed by the back side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_z - collidee->size_z * 0.5f;
    percent -= collider->pos_z + collider->size_z * 0.5f;
    percent /= collider->vel_z * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the front points of the collider intersect the
    // plane formed by the back side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float xr;                                           // x value where front left  point of collider hits back plane of collidee
    float xl;                                           // x value where front right point of collider hits back plane of collidee

    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original front right x value of collider
    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original front left  x value of collider
    xr += collider->vel_x * frameTime * percent;        // move front right x to where it intersects the back plane of collidee
    xl += collider->vel_x * frameTime * percent;        // move front left  x to where it intersects the back plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the front points of the collider must be
    // within the bounding box x range of the collidee where we calculated they
    // intersect the back plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the left point within the x range ?

            ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
        )
        ||
        (   // Is the right point within the x range ?

            ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
        )

       )
    {
        // Collision detected: call collision event on both objects involved
        // Do not correct position of collider because collidee is non solid
        // and that is not what should happen!

        collidee->event_collision(collider);
        collider->event_collision(collidee);
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCrossCheck_back
Purpose:  Like the 'performObjectCollision_back' function, but instead of fixing
          the position of the collider it simply calls the collision event functions
          on both objects involved in the collision. Used on non-solid objects after
          collision checking with solid objects has been done, in order to check if
          the collider when moving along, crosses the bounding box of the collidee.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCrossCheck_back
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the back of the collider at the allowed z is greater than the front z
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedZ - collider->size_z * 0.5f
        >
        collidee->pos_z + collidee->size_z * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the back of the collider is already past the front of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_z - collider->size_z * 0.5f )
        <
        ( collidee->pos_z + collidee->size_z * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the back side of the collider
    // touches the plane formed by the front side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_z + collidee->size_z * 0.5f;
    percent -= collider->pos_z - collider->size_z * 0.5f;
    percent /= collider->vel_z * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the back points of the collider intersect the
    // plane formed by the front side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float xr;                                           // x value where back left  point of collider hits front plane of collidee
    float xl;                                           // x value where back right point of collider hits front plane of collidee

    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original back right x value of collider
    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original back left  x value of collider
    xr += collider->vel_x * frameTime * percent;        // move back right x to where it intersects the front plane of collidee
    xl += collider->vel_x * frameTime * percent;        // move back left  x to where it intersects the front plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the back points of the collider must be
    // within the bounding box x range of the collidee where we calculated they
    // intersect the front plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the left point within the x range ?

            ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
        )
        ||
        (   // Is the right point within the x range ?

            ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
            &&
            ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
        )

       )
    {
        // Collision detected: call collision event on both objects involved
        // Do not correct position of collider because collidee is non solid
        // and that is not what should happen!

        collidee->event_collision(collider);
        collider->event_collision(collidee);
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCrossCheck_left
Purpose:  Like the 'performObjectCollision_left' function, but instead of fixing
          the position of the collider it simply calls the collision event functions
          on both objects involved in the collision. Used on non-solid objects after
          collision checking with solid objects has been done, in order to check if
          the collider when moving along, crosses the bounding box of the collidee.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCrossCheck_left
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If            the left of the collider at the allowed x is greater than the right x
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedX - collider->size_x * 0.5f
        >
        collidee->pos_x + collidee->size_x * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the left of the collider is already past the right of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_x - collider->size_x * 0.5f )
        <
        ( collidee->pos_x + collidee->size_x * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the left side of the collider
    // touches the plane formed by the right side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_x + collidee->size_x * 0.5f;
    percent -= collider->pos_x - collider->size_x * 0.5f;
    percent /= collider->vel_x * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the left points of the collider intersect the
    // plane formed by the right side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float zf;                                           // z value where front left of collider hits right plane of collidee
    float zb;                                           // z value where back  left of collider hits right plane of collidee

    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front left z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  left z value of collider
    zf += collider->vel_z * frameTime * percent;        // move front left z to where it intersects the right plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  left z to where it intersects the right plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the left points of the collider must be
    // within the bounding box z range of the collidee where we calculated they
    // intersect the right plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the front within the z range ?

            ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
        )
        ||
        (   // Is the back within the z range ?

            ( zb <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zb >= collidee->pos_z - collidee->size_z * 0.5f )
        )

       )
    {
        // Collision detected: call collision event on both objects involved
        // Do not correct position of collider because collidee is non solid
        // and that is not what should happen!

        collidee->event_collision(collider);
        collider->event_collision(collidee);
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCrossCheck_right
Purpose:  Like the 'performObjectCollision_right' function, but instead of fixing
          the position of the collider it simply calls the collision event functions
          on both objects involved in the collision. Used on non-solid objects after
          collision checking with solid objects has been done, in order to check if
          the collider when moving along, crosses the bounding box of the collidee.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCrossCheck_right
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the right of the collider at the allowed x is less than the left x
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedX + collider->size_x * 0.5f
        <
        collidee->pos_x - collidee->size_x * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the right of the collider is already past the left of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_x + collider->size_x * 0.5f )
        >
        ( collidee->pos_x - collidee->size_x * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is beneath the bottom of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y + collider->size_y * 0.5
        <
        collidee->pos_y - collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is above the top of the collidee then
    // abort the test also. Objects cannot collide along z-axis.
    //--------------------------------------------------------------------------

    if
    (
        collider->pos_y - collider->size_y * 0.5
        >
        collidee->pos_y + collidee->size_y * 0.5
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the right side of the collider
    // touches the plane formed by the left side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_x - collidee->size_x * 0.5f;
    percent -= collider->pos_x + collider->size_x * 0.5f;
    percent /= collider->vel_x * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the right points of the collider intersect the
    // plane formed by the left side of the collidee as they move along
    // the velocity vector.
    //--------------------------------------------------------------------------

    float zf;                                           // z value where front right of collider hits left plane of collidee
    float zb;                                           // z value where back  right of collider hits left plane of collidee

    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front right z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  right z value of collider
    zf += collider->vel_z * frameTime * percent;        // move front right z to where it intersects the left plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  right z to where it intersects the left plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the right points of the collider must be
    // within the bounding box z range of the collidee where we calculated they
    // intersect the left plane of the collidee as they move along the velocity
    // vector.
    //--------------------------------------------------------------------------

    if (

        (   // Is the front within the z range ?

            ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
        )
        ||
        (   // Is the back within the z range ?

            ( zb   <= collidee->pos_z + collidee->size_z * 0.5f )
            &&
            ( zb >= collidee->pos_z - collidee->size_z * 0.5f )
        )

       )
    {
        // Collision detected: call collision event on both objects involved
        // Do not correct position of collider because collidee is non solid
        // and that is not what should happen!

        collidee->event_collision(collider);
        collider->event_collision(collidee);
    }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCrossCheck_bottom
Purpose:  Like the 'performObjectCollision_bottom' function, but instead of fixing
          the position of the collider it simply calls the collision event functions
          on both objects involved in the collision. Used on non-solid objects after
          collision checking with solid objects has been done, in order to check if
          the collider when moving along, crosses the bounding box of the collidee.
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCrossCheck_bottom
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the bottom of the collider at the allowed y is greater than the top y
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedY - collider->size_y * 0.5f
        >
        collidee->pos_y + collidee->size_y * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the bottom of the collider is already past the top of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_y - collider->size_y * 0.5f )
        <
        ( collidee->pos_y + collidee->size_y * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the bottom side of the collider
    // touches the plane formed by the top side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_y + collidee->size_y * 0.5f;
    percent -= collider->pos_y - collider->size_y * 0.5f;
    percent /= collider->vel_y * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the points of the collider intersect the plane formed by
    // the top side of the collidee as they move along the velocity vector.
    //--------------------------------------------------------------------------

    float xl;                                           // x value where left  of collider hits top plane of collidee
    float xr;                                           // x value where right of collider hits top plane of collidee
    float zf;                                           // z value where front of collider hits top plane of collidee
    float zb;                                           // z value where back  of collider hits top plane of collidee

    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original left  x value of collider
    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original right x value of collider
    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  z value of collider

    xl += collider->vel_x * frameTime * percent;        // move left  x to where it intersects the top plane of collidee
    xr += collider->vel_x * frameTime * percent;        // move right x to where it intersects the top plane of collidee
    zf += collider->vel_z * frameTime * percent;        // move front z to where it intersects the top plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  z to where it intersects the top plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the following must be true:
    //
    // (a) either the left or right x values are in the x range of the collidees
    //     bounding box.
    //
    //     *AND*
    //
    // (b) either the front or back z values are in the z range of the collidees
    //     bounding box.
    //
    //--------------------------------------------------------------------------

    if (
         // Check that one of the points is in the z range of bounding box:

         (

            (   // Is the front within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
            ||
            (   // Is the back within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
         )

         &&

         // Check that one of the points is in the x range of bounding box:

         (

            (   // Is the left within the x range ?

                ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
            )
            ||
            (   // Is the right within the x range ?

                ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
            )
         )
       )
       {
            // Collision detected: call collision event on both objects involved
            // Do not correct position of collider because collidee is non solid
            // and that is not what should happen!

            collidee->event_collision(collider);
            collider->event_collision(collidee);
       }
}

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Name:     GameObjectManager::performObjectCrossCheck_top
Purpose:  Like the 'performObjectCollision_top' function, but instead of fixing
          the position of the collider it simply calls the collision event functions
          on both objects involved in the collision. Used on non-solid objects after
          collision checking with solid objects has been done, in order to check if
          the collider when moving along, crosses the bounding box of the collidee.
          collision checking testing data.
Params:   First object (collider), second object (the collidee),
          collision checking testing data.
Returns:  none

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

void GameObjectManager::performObjectCrossCheck_top
(
    GameObject          * collider,
    GameObject          * collidee,
    CollisionTestData   * collisionData
)
{
    //--------------------------------------------------------------------------
    // If the top of the collider at the allowed y is less than the bottom y
    // value of the collidee then abort the test. Collider cannot collide with
    // collidee because it either doesn't move far enough, or another object
    // has already been found to be in collision with it before this object.
    //--------------------------------------------------------------------------

    if
    (
        collisionData->allowedY + collider->size_y * 0.5f
        <
        collidee->pos_y - collidee->size_y * 0.5f
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // If the the top of the collider is already past the bottom of the collidee
    // then abort the test. these planes cannot collide...
    //--------------------------------------------------------------------------

    if
    (
        ( collider->pos_y + collider->size_y * 0.5f )
        >
        ( collidee->pos_y - collidee->size_y * 0.5f )
    )
    {
        // objects cannot collide. abort test.

        return;
    }

    //--------------------------------------------------------------------------
    // Find how far along the movement vector the top side of the collider
    // touches the plane formed by the bottom side of the collidee
    //--------------------------------------------------------------------------

    float percent;

    percent  = collidee->pos_y - collidee->size_y * 0.5f;
    percent -= collider->pos_y + collider->size_y * 0.5f;
    percent /= collider->vel_y * frameTime;

    //--------------------------------------------------------------------------
    // Now find where the points of the collider intersect the plane formed by
    // the bottom side of the collidee as they move along the velocity vector.
    //--------------------------------------------------------------------------

    float xl;                                           // x value where left  of collider hits bottom plane of collidee
    float xr;                                           // x value where right of collider hits bottom plane of collidee
    float zf;                                           // z value where front of collider hits bottom plane of collidee
    float zb;                                           // z value where back  of collider hits bottom plane of collidee

    xl  = collider->pos_x - collider->size_x * 0.5f;    // get original left  x value of collider
    xr  = collider->pos_x + collider->size_x * 0.5f;    // get original right x value of collider
    zf  = collider->pos_z + collider->size_z * 0.5f;    // get original front z value of collider
    zb  = collider->pos_z - collider->size_z * 0.5f;    // get original back  z value of collider

    xl += collider->vel_x * frameTime * percent;        // move left  x to where it intersects the bottom plane of collidee
    xr += collider->vel_x * frameTime * percent;        // move right x to where it intersects the bottom plane of collidee
    zf += collider->vel_z * frameTime * percent;        // move front z to where it intersects the bottom plane of collidee
    zb += collider->vel_z * frameTime * percent;        // move back  z to where it intersects the bottom plane of collidee

    //--------------------------------------------------------------------------
    // Now for a collision to occur the following must be true:
    //
    // (a) either the left or right x values are in the x range of the collidees
    //     bounding box.
    //
    //     *AND*
    //
    // (b) either the front or back z values are in the z range of the collidees
    //     bounding box.
    //
    //--------------------------------------------------------------------------

    if (
         // Check that one of the points is in the z range of bounding box:

         (

            (   // Is the front within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
            ||
            (   // Is the back within the z range ?

                ( zf <= collidee->pos_z + collidee->size_z * 0.5f )
                &&
                ( zf >= collidee->pos_z - collidee->size_z * 0.5f )
            )
         )

         &&

         // Check that one of the points is in the x range of bounding box:

         (

            (   // Is the left within the x range ?

                ( xl <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xl >= collidee->pos_x - collidee->size_x * 0.5f )
            )
            ||
            (   // Is the right within the x range ?

                ( xr <= collidee->pos_x + collidee->size_x * 0.5f )
                &&
                ( xr >= collidee->pos_x - collidee->size_x * 0.5f )
            )
         )
       )
       {
            // Collision detected: call collision event on both objects involved
            // Do not correct position of collider because collidee is non solid
            // and that is not what should happen!

            collidee->event_collision(collider);
            collider->event_collision(collidee);
       }
}
