/*
	Rogue Trader.
	Copyright (c) 2007, 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:   GameObjectScene
// Purpose:      Responsible for managing a scene full of game objects, contains
//               functions for moving the game objects and drawing them as well
//               as adding new objects or removing objects from the scene. One
//               of the base classes for the GameScene class which is a comprised
//               super class of many different types of scenes: lights, particles etc..
//               The game object scene is responsible for managing the memory of
//               every object added into the scene. However the scene does not manage
//               hook memory as this is the responsibility of the class which created
//               them.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

#include "GameObjectScene.h"

//------------------------------------------------------------------------------
// Constant initialisation
//------------------------------------------------------------------------------

// Determines how much objects rebound off each other upon collision

const float GameObjectScene::STATIC_COLLISION_ELASTICITY = 0.75f; // for sphere polygon collision
const float GameObjectScene::MOVING_COLLISION_ELASTICITY = 0.75f; // for sphere sphere  collision

// Determines how much velocity loss is needed before damage occurs or a noise is played:

const float GameObjectScene::MIN_STATIC_COLLISION_VELOCITY_LOSS = 100;

// Determines how much damage loosing velocity on collision does to an object

const float GameObjectScene::STATIC_COLLISION_VELOCITY_LOSS_DAMAGE = 0.15f;

// Determines how much velocity is needed when two moving objects collide before damage happens

const float GameObjectScene::MIN_MOVING_COLLISION_VELCITY = 100;

// Determines how much velocity damages objects in a moving object collision

const float GameObjectScene::MOVING_COLLISION_VELOCITY_DAMAGE = 0.10f;

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::GameObjectScene()
Purpose:  GameObjectScene constructor.
Params:   none
Returns:  n/a

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GameObjectScene::GameObjectScene()
{
    // Create the arrays of pointers to static and moving objects

    movingObjects = new MovingGameObject * [ MAX_OBJECTS ];
    staticObjects = new StaticGameObject * [ MAX_OBJECTS ];

    // Create the array of pointers to hook objects

    hooks = new GameObjectHook * [ MAX_HOOKS ];

    // Initialise the moving and static object count

    movingObjectCount = 0;
    staticObjectCount = 0;

    // Initialise the number of hooks to zero

    hookCount = 0;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::~GameObjectScene()
Purpose:  GameObjectScene destructor. frees all memory used.
Params:   n/a
Returns:  n/a

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GameObjectScene::~GameObjectScene()
{
    // Delete all moving objects

    for ( unsigned i = 0 ; i < movingObjectCount ; i++ ){ delete movingObjects[i]; }

    // Delete all static objects

    for ( unsigned i = 0 ; i < staticObjectCount ; i++ ){ delete staticObjects[i]; }

    // Delete the arrays of pointers to objects

    delete movingObjects;
    delete staticObjects;

    // Delete the array of pointers to hook objects

    delete hooks; hooks = 0;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::addObject()
Purpose:  Trys to add object into the scene. Deletes it on failure.
Params:   object to add.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::addObject( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Don't allow null objects
    //--------------------------------------------------------------------------

    if ( object == 0 ) return;

    //--------------------------------------------------------------------------
    // Abort if object is already in one game scene
    //--------------------------------------------------------------------------

    if ( object->scene != 0 ) return;

    //--------------------------------------------------------------------------
    // See if the object is static or moving
    //--------------------------------------------------------------------------

    if ( object->isStatic() )
    {
        //----------------------------------------------------------------------
        // static object: check if array for these types of objects is full
        //----------------------------------------------------------------------

        if ( staticObjectCount < MAX_OBJECTS )
        {
            // Room left: add to end of the array

            staticObjects[staticObjectCount] = (StaticGameObject*)(object);

            // Set the array position of the object in the scene array

            object->sceneArrayPos = staticObjectCount;

            // Set the scene the object belongs to

            object->scene = this;

            // Increment number of static objects

            staticObjectCount++;

            // Call the on scene enter event for the object

            object->onSceneEnter();
        }
        else
        {
            // Can't insert: no room in array. delete:

            delete object;
        }

    }
    else
    {
        //----------------------------------------------------------------------
        // moving object: check if array for these types of objects is full
        //----------------------------------------------------------------------

        if ( movingObjectCount < MAX_OBJECTS )
        {
            // Room left: add to end of the array

            movingObjects[movingObjectCount] = (MovingGameObject*)(object);

            // Set the array position of the object in the scene array

            object->sceneArrayPos = movingObjectCount;

            // Set the scene the object belongs to

            object->scene = this;

            // Increment number of static objects

            movingObjectCount++;

            // Call the on scene enter event for the object

            object->onSceneEnter();
        }
        else
        {
            // Can't insert: no room in array. delete:

            delete object;
        }

    }   // end else of if ( object->static() )

}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::deleteObject()
Purpose:  Trys to delete an object from the scene. Object is gone forever after
          deletion.
Params:   object to delete.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::deleteObject( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Don't allow null objects
    //--------------------------------------------------------------------------

    if ( object == 0 ) return;

    //--------------------------------------------------------------------------
    // Abort if object is not in this scene
    //--------------------------------------------------------------------------

    if ( object->scene != this ) return;

    //--------------------------------------------------------------------------
    // See if the object is static or moving
    //--------------------------------------------------------------------------

    if ( object->isStatic() )
    {
        //----------------------------------------------------------------------
        // Static object
        //----------------------------------------------------------------------

        // Save the index of the object in the array

        unsigned i = object->sceneArrayPos;

        // Delete the object

        delete object;

        // Decrement object count

        staticObjectCount--;

        // If there is a last object then swap it into this position and set its new array position

        if ( staticObjectCount != 0 && i < staticObjectCount )
        {
            // Do the swap

            staticObjects[i] = staticObjects[staticObjectCount];

            // Set the objects new array position

            staticObjects[i]->sceneArrayPos = i;
        }
    }
    else
    {
        //----------------------------------------------------------------------
        // Moving object
        //----------------------------------------------------------------------

        // Save the index of the object in the array

        unsigned i = object->sceneArrayPos;

        // Delete the object

        delete object;

        // Decrement object count

        movingObjectCount--;

        // If there is a last object then swap it into this position and set its new array position

        if ( movingObjectCount != 0 && i < movingObjectCount )
        {
            // Do the swap

            movingObjects[i] = movingObjects[movingObjectCount];

            // Set the objects new array position

            movingObjects[i]->sceneArrayPos = i;
        }

    }   // end else of if ( object->static() )

    //--------------------------------------------------------------------------
    // Finally, check all the hooks in the scene and see if they refer to the
    // object which has been deleted. If so then set their object pointer to null
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < hookCount ; i++ )
    {
        if ( hooks[i]->object == object ) hooks[i]->object = 0;
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::removeObject()
Purpose:  Trys to removed an object from the scene. Object is only removed and
          not deleted.
Params:   object to remove.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::removeObject( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Don't allow null objects
    //--------------------------------------------------------------------------

    if ( object == 0 ) return;

    //--------------------------------------------------------------------------
    // Abort if object is not in this scene
    //--------------------------------------------------------------------------

    if ( object->scene != this ) return;

    //--------------------------------------------------------------------------
    // See if the object is static or moving
    //--------------------------------------------------------------------------

    if ( object->isStatic() )
    {
        //----------------------------------------------------------------------
        // Static object
        //----------------------------------------------------------------------

        // Get the index of the object in the array

        unsigned i = object->sceneArrayPos;

        // Call the on scene remove event for this object

        object->onSceneRemove();

        // Set the objects scene to null: no longer part of this scene:

        object->scene = 0;

        // Decrement object count

        staticObjectCount--;

        // If there is a last object then swap it into this position and set its new array position

        if ( staticObjectCount != 0 )
        {
            // Do the swap

            staticObjects[i] = staticObjects[staticObjectCount];

            // Set the objects new array position

            staticObjects[i]->sceneArrayPos = i;
        }
    }
    else
    {
        //----------------------------------------------------------------------
        // Moving object
        //----------------------------------------------------------------------

        // Get the index of the object in the array

        unsigned i = object->sceneArrayPos;

        // Call the on scene remove event for this object

        object->onSceneRemove();

        // Set the objects scene to null: no longer part of this scene:

        object->scene = 0;

        // Decrement object count

        movingObjectCount--;

        // If there is a last object then swap it into this position and set its new array position

        if ( movingObjectCount != 0 )
        {
            // Do the swap

            movingObjects[i] = movingObjects[movingObjectCount];

            // Set the objects new array position

            movingObjects[i]->sceneArrayPos = i;
        }

    }   // end else of if ( object->static() )
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::objectExists()
Purpose:  Tells if an object exists in the scene
Params:   object to check for existence
Returns:  true if it was found in the scene, false if not

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

bool GameObjectScene::objectExists( GameObject * object )
{
    //--------------------------------------------------------------------------
    // Search the static object array for the given object:
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < staticObjectCount ; i++ )
    {
        // Return true if the object was found at this index

        if ( staticObjects[i] == object ) return true;
    }

    //--------------------------------------------------------------------------
    // Search the moving object array for the given object:
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < movingObjectCount ; i++ )
    {
        // Return true if the object was found at this index

        if ( movingObjects[i] == object ) return true;
    }

    //--------------------------------------------------------------------------
    // If we have got down to here then it does not exist: return false
    //--------------------------------------------------------------------------

    return false;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::addHook()
Purpose:  Trys to add object into the scene. Makes the hook's pointer null on failure.
Params:   hook to add.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::addHook( GameObjectHook * hook )
{
    //--------------------------------------------------------------------------
    // Abort if hook is null or array of hook pointers is null
    //--------------------------------------------------------------------------

    if ( hook == 0 || hooks == 0 ) return;

    //--------------------------------------------------------------------------
    // Abort if hook is already in a GameObject scene
    //--------------------------------------------------------------------------

    if ( hook->scene != 0 ) return;

    //--------------------------------------------------------------------------
    // See if there is room for another hook in the hook pointer array
    //--------------------------------------------------------------------------

    if ( hookCount >= MAX_HOOKS )
    {
        //----------------------------------------------------------------------
        // No more room for hooks. Make the hooks pointer to null.
        //----------------------------------------------------------------------

        hook->object = 0;
    }
    else
    {
        //----------------------------------------------------------------------
        // Room for the hook. Add into the next free slot in the array
        //----------------------------------------------------------------------

        // Add into the hook array

        hooks[ hookCount ] = hook;

        // Increment the number of hooks

        hookCount++;  
        
        // Set hook scene pointer:
        
        hook->scene = this;    
    
        //----------------------------------------------------------------------
        // Now validate the hooks pointer: see if it refers to a valid object
        // in the scene. if not then set its pointer to null.
        //----------------------------------------------------------------------

        for ( unsigned i = 0 ; i < staticObjectCount ; i++ )
        {
            if ( staticObjects[i] == hook->object ) return;
        }

        for ( unsigned i = 0 ; i < movingObjectCount ; i++ )
        {
            if ( movingObjects[i] == hook->object ) return;
        }
        
        //----------------------------------------------------------------------
        // If this point has been reached then the hook does not refer to an
        // object in this scene. Invalidate its pointer.
        //----------------------------------------------------------------------

        hook->object	= 0;
        hook->scene		= 0;
        
        hookCount--;
    }

}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::removeHook()
Purpose:  Trys to remove the given hook from the scene. Does not delete hook.
Params:   hook to add.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::removeHook( GameObjectHook * hook )
{
    //--------------------------------------------------------------------------
    // Abort if hook is null or array of hook pointers is null
    //--------------------------------------------------------------------------

    if ( hook == 0 || hooks == 0 ) return;

    //--------------------------------------------------------------------------
    // Abort if hook has not been assigned to this scene
    //--------------------------------------------------------------------------

    if ( hook->scene != this ) return;

    //--------------------------------------------------------------------------
    // Search for the hook in the hook array
    //--------------------------------------------------------------------------

    int index = -1;

    for ( unsigned i = 0 ; i < hookCount ; i++ )
    {
        // See if this hook matches hook given

        if ( hooks[i] == hook )
        {
            // found a match. save index of the hook and abort search.

            index = i; break;
        }
    }

    //--------------------------------------------------------------------------
    // Remove the hook if it has been found
    //--------------------------------------------------------------------------

    if ( index > -1 )
    {
        // Swap the last hook in the array into this position

        hooks[index] = hooks[ hookCount - 1 ];

        // Decrease the number of hooks

        hookCount--;

        // Set the hook's scene to null again: not part of a object scene any more

        hook->scene = 0;
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::setObjectPosition()
Purpose:  Moves the object pointed to by the hook to specified position. If object
          is moveable and any other moveable non-indestructable objects are in the
          way then they are killed off:
Params:   as commented
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::setObjectPosition
(
    GameObjectHook * hook,  // hook to object to set position for
    float x ,               // new position for object: x
    float y ,               // new position for object: y
    float z                 // new position for object: z
)
{
    //--------------------------------------------------------------------------
    // Abort on bad hook pointer
    //--------------------------------------------------------------------------

    if ( hook == 0 ) return;

    //--------------------------------------------------------------------------
    // Get hook object and abort if null:
    //--------------------------------------------------------------------------

    GameObject * object = hook->getObject(); if ( object == 0 ) return;

    //--------------------------------------------------------------------------
    // Move the object:
    //--------------------------------------------------------------------------

    object->position[0] = x;
    object->position[1] = y;
    object->position[2] = z;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::drawObjects()
Purpose:  Draws all objects in the scene from given camera position. assumes
          view has been setup into 3D mode.
Params:   camera to view from
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::drawObjects( Camera * camera )
{
    //--------------------------------------------------------------------------
    // Abort on null camera pointer
    //--------------------------------------------------------------------------

    if ( camera == 0 ) return;

    //--------------------------------------------------------------------------
    // Setup the openGL state for drawing the objects in the scene
    //--------------------------------------------------------------------------

    // Setup basic openGL state

    glEnable    (GL_TEXTURE_2D  );  // enables
    glEnable    (GL_CULL_FACE   );
    glEnable    (GL_DEPTH_TEST  );
    glDisable   (GL_BLEND       );  // disables

    // depth buffer setup

    glDepthFunc (GL_LEQUAL  );
    glDepthMask (GL_TRUE    );
    glDepthRange( 0 , 1     );

    // Clear the depth buffer

    glClear(GL_DEPTH_BUFFER_BIT);

    // Cull back faces

    glCullFace(GL_BACK);

    // Enable smooth shading

    glShadeModel(GL_NICEST);

    // Enable vertex, normal and texture coordinate arrays but disable color arrays

    glDisableClientState( GL_COLOR_ARRAY  );
    glEnableClientState ( GL_VERTEX_ARRAY );
    glEnableClientState ( GL_NORMAL_ARRAY );
    glEnableClientState ( GL_TEXTURE_COORD_ARRAY );

    //--------------------------------------------------------------------------
    // View the scene from the camera position
    //--------------------------------------------------------------------------

    camera->viewFrom();

    //--------------------------------------------------------------------------
    // Get the object the camera is following
    //--------------------------------------------------------------------------

    GameObject * cameraObject = camera->getFollowObject();

    //--------------------------------------------------------------------------
    // Draw all static objects
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < staticObjectCount ; i++ )
    {
        // see first if the object has a mesh to draw and is visible

        if ( staticObjects[i]->mesh && staticObjects[i]->visible  )
        {

            // draw the objects mesh in the objects position: but only if the camera doesn't say not to:

            if ( camera->showFollowObject() || cameraObject != staticObjects[i] )
            {
                // Draw the object

                staticObjects[i]->mesh->draw
                (
                    staticObjects[i]->position[0],
                    staticObjects[i]->position[1],
                    staticObjects[i]->position[2],
                    staticObjects[i]->orientation
                );
            }
        }
    }

    //--------------------------------------------------------------------------
    // Draw all moving objects
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < movingObjectCount ; i++ )
    {
        // see first if the object has a mesh to draw and is visible

        if ( movingObjects[i]->mesh && movingObjects[i]->visible  )
        {

            // draw the objects mesh in the objects position: but only if the camera doesn't say not to:

            if ( camera->showFollowObject() || cameraObject != movingObjects[i] )
            {
                // Draw the object

                movingObjects[i]->mesh->draw
                (
                    movingObjects[i]->position[0],
                    movingObjects[i]->position[1],
                    movingObjects[i]->position[2],
                    movingObjects[i]->orientation
                );
            }
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::dispatchEventOnDraw()
Purpose:  Dispatches the on draw event to every object in the scene
Params:   Camera the scene is being viewed from
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::dispatchEventOnDraw( Camera * camera )
{
	//--------------------------------------------------------------------------
	// Safety first: build the safe iteration cache
	//--------------------------------------------------------------------------

	BuildSafeIterationCache();

    //--------------------------------------------------------------------------
    // Call the on draw event for every object:
    //--------------------------------------------------------------------------

    // Call the on-draw event for all static objects

    for ( unsigned i = 0 ; i < safeIterationCache.original_static_count; i++ )
    {
		// Get this hook:
		
		GameObjectHook * hook = safeIterationCache.static_hooks + i;
		
		// Get the object:
		
		StaticGameObject * object = (StaticGameObject*) hook->getObject();
		
		// Only if there:
		
		if ( object ) object->onDraw(camera);
    }

    // Call the on-draw event for all moving objects

    for ( unsigned i = 0 ; i < safeIterationCache.original_moving_count; i++ )
    {
		// Get this hook:
		
		GameObjectHook * hook = safeIterationCache.moving_hooks + i;
		
		// Get the object:
		
		MovingGameObject * object = (MovingGameObject*) hook->getObject();
		
		// Only if there:
		
		if ( object ) object->onDraw(camera);
    }
    
    //--------------------------------------------------------------------------
	// Done with this cache: free all the hooks
	//--------------------------------------------------------------------------

	DestroySafeIterationCache();    
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::dispatchEventOnFrame()
Purpose:  Dispatches the on frame event to every object in the scene
Params:   last frames time in seconds
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::dispatchEventOnFrame( float frameTime )
{
	//--------------------------------------------------------------------------
	// Safety first: build the safe iteration cache
	//--------------------------------------------------------------------------

	BuildSafeIterationCache();

    //--------------------------------------------------------------------------
    // Call the on frame event for every object:
    //--------------------------------------------------------------------------

    // Call the on-frame event for all moving objects

    for ( unsigned i = 0 ; i < safeIterationCache.original_moving_count; i++ )
    {
		// Get this hook:
		
		GameObjectHook * hook = safeIterationCache.moving_hooks + i;
		
		// Get the object:
		
		MovingGameObject * object = (MovingGameObject*) hook->getObject();
		
		// Only if there:
		
		if ( object ) object->onFrame(frameTime);
    }

    // Call the on-frame event for all static objects

    for ( unsigned i = 0 ; i < safeIterationCache.original_static_count; i++ )
    {
		// Get this hook:
		
		GameObjectHook * hook = safeIterationCache.static_hooks + i;
		
		// Get the object:
		
		StaticGameObject * object = (StaticGameObject*) hook->getObject();
		
		// Only if there:
		
		if ( object ) object->onFrame(frameTime);
    }
    
    //--------------------------------------------------------------------------
	// Done with this cache: free all the hooks
	//--------------------------------------------------------------------------

	DestroySafeIterationCache();    
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::moveObjects()
Purpose:  Moves all of the moveable objects in the scene, doing collision detection
          and such.
Params:   Time the last frame took in seconds
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::moveObjects( float frameTime )
{	
	//--------------------------------------------------------------------------
	// Safety first: build the safe iteration cache
	//--------------------------------------------------------------------------

	BuildSafeIterationCache();

    //--------------------------------------------------------------------------
    // Do a death check for all static objects:
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < safeIterationCache.original_static_count ; i++ )
    {
		// Get the object hook:
		
		GameObjectHook * object_hook = safeIterationCache.static_hooks + i;
    
        // Get this object in the array:

        StaticGameObject * object = (StaticGameObject*) object_hook->getObject();
        
        // If not there anymore then abort:
        
        if ( object == 0 ) continue;

        // If it is destructable and its health <= 0 then kill:

        if ( object->indestructable == false && object->health <= 0 ) 
        {
			deleteObject(object);
		}
    }

    //--------------------------------------------------------------------------
    // Go through the moving objects array: moving each object
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < safeIterationCache.original_moving_count ; i++ )
    {
        //----------------------------------------------------------------------
        // Get the object being moved
        //----------------------------------------------------------------------
        
		// Get the object hook:
		
		GameObjectHook * object_hook = safeIterationCache.moving_hooks + i;
		
		// Get the object:   

        MovingGameObject * object = (MovingGameObject*) object_hook->getObject();
        
        // If not there anymore then do nothing:
        
        if ( object == 0 ) continue;

        //----------------------------------------------------------------------
        // Do a death check for this object:
        //----------------------------------------------------------------------

        if ( object->indestructable == false && object->health <= 0 )
        {
            // Kill this object: it is now dead

            deleteObject(object);

            // Done with this object:

            continue;
        }

        //----------------------------------------------------------------------
        // Get the current speed the object is moving at
        //----------------------------------------------------------------------

        float velocityAmount = mlLenght3d( object->velocity );

        //----------------------------------------------------------------------
        // Accelerate the object in the forward direction it is pointing.
        // But normalise the velocity vector afterwards. At this stage I only
        // want the acceleration to have an effect on the direction the ship is
        // moving in, not its speed- that will be decided further down
        //----------------------------------------------------------------------

        object->velocity[0] += object->orientation[6] * object->acceleration * frameTime;
        object->velocity[1] += object->orientation[7] * object->acceleration * frameTime;
        object->velocity[2] += object->orientation[8] * object->acceleration * frameTime;

        mlNormalise3d( object->velocity );

        //----------------------------------------------------------------------
        // If the object is past its maximum velocity then slow down the object,
        // otherwise speed it up and accelerate the object.
        //----------------------------------------------------------------------

        if ( velocityAmount > object->maxVelocity )
        {
            //------------------------------------------------------------------
            // Object is moving too fast: slow down
            //------------------------------------------------------------------

            // Reduce the velocity amount by the objects acceleration amount

            velocityAmount -= frameTime * object->acceleration;

            // If the velocity is less than max velocity then clamp to max velocity

            if ( velocityAmount < object->maxVelocity ) velocityAmount = object->maxVelocity;
        }
        else
        {
            //------------------------------------------------------------------
            // Object can move by acceleration amount
            //------------------------------------------------------------------

            // Add to the velocity amount:

            velocityAmount += object->acceleration * frameTime;

            // Make sure it isn't over the maximum:

            if ( velocityAmount > object->maxVelocity ) velocityAmount = object->maxVelocity;
        }

        //----------------------------------------------------------------------
        // Rescale the normalised velocity vector by adjusted velocity amount
        //----------------------------------------------------------------------

        mlScale3d( object->velocity , velocityAmount );

        //----------------------------------------------------------------------
        // Now move the ship: do collision testing afterwards
        //----------------------------------------------------------------------

        object->position[0] += object->velocity[0] * frameTime;
        object->position[1] += object->velocity[1] * frameTime;
        object->position[2] += object->velocity[2] * frameTime;

        //----------------------------------------------------------------------
        // Only do collision testing if object being moved is solid and has
        // a mesh attached to it:
        //----------------------------------------------------------------------

        if ( object->solid && object->mesh )
        {
            //------------------------------------------------------------------
            // Check the move against all static objects in the scene
            //------------------------------------------------------------------

            for ( unsigned i = 0 ; i < safeIterationCache.original_static_count ; i++ )
            {
				// Make sure our object still exists:
				
				if ( object_hook->getObject() == 0 ) break;
				
				// Get the hook for the second object involved:
		
				GameObjectHook * object_hook2 = safeIterationCache.static_hooks + i;
				
				// Get the object:
				
				StaticGameObject * object2 = (StaticGameObject*) object_hook2->getObject();
		
				// If it isn't there then don't process
				
				if ( object2 == 0 ) continue;
            
                // If object being tested against is not solid then abort.

                if ( object2->solid == false ) continue;

                // If the object being tested against has no mesh then abort

                if ( object2->mesh == 0 ) continue;

                // Do the collision test against this object

                collisionStatic( object, object2 );
            }

            //------------------------------------------------------------------
            // Check the move against all moving objects in the scene
            //------------------------------------------------------------------

            for ( unsigned i = 0 ; i < safeIterationCache.original_moving_count ; i++ )
            {
				// Make sure our object still exists:
				
				if ( object_hook->getObject() == 0 ) break;
				
				// Get the hook for the second object involved:
	
				GameObjectHook * object_hook2 = safeIterationCache.moving_hooks + i;
				
				// Get the object:
				
				MovingGameObject * object2 = (MovingGameObject*) object_hook2->getObject();
				
				// If it isn't there then don't process
				
				if ( object2 == 0 ) continue;				
            
                // If this object is the object being moved then abort. No self collisions.

                if ( object2 == object ) continue;

                // If object being tested against is not solid then abort.

                if ( object2->solid == false ) continue;

                // If the object being tested against has no mesh then abort

                if ( object2->mesh == 0 ) continue;

                // Do the collision test against this object

                collisionMoving( object, object2 );
            }

        } // end if ( object->solid )

    }   // end for every moving object move current object

    //--------------------------------------------------------------------------
	// Done with this cache: free all the hooks
	//--------------------------------------------------------------------------

	DestroySafeIterationCache();  
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::collisionStatic()
Purpose:  Builds safe iteration cache. Done before iteration through a series of 
		  objects. E.G dispatching the OnFrame event.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::BuildSafeIterationCache()
{
	// Set these convience pointers
	
	safeIterationCache.static_hooks = (GameObjectHook*)(safeIterationCache.static_hook_mem);
	safeIterationCache.moving_hooks = (GameObjectHook*)(safeIterationCache.moving_hook_mem);
	
	// Need to keep track of the original object counts
	
	safeIterationCache.original_static_count	= staticObjectCount;
	safeIterationCache.original_moving_count	= movingObjectCount;
	
    // Construct hooks for all objects:
    
    {
		// Do static hooks first:
		
		{			
			// Reinterpret the memory to a hook:
			
			GameObjectHook * hook = safeIterationCache.static_hooks;
			
			// Create all the hooks:
	    
			for ( unsigned i = 0 ; i < staticObjectCount ; i++ )
			{
				// Use in-place new which doesn't allocate any memory:
				
				new (hook) GameObjectHook( staticObjects[i] );
				
				// Add the hook:
				
				addHook(hook); hook++;
			}
		}
		
		// Now moving object hooks:
		
		{			
			// Reinterpret the memory to a hook:
			
			GameObjectHook * hook = safeIterationCache.moving_hooks;
			
			// Create all the hooks:
	    
			for ( unsigned i = 0 ; i < movingObjectCount ; i++ )
			{
				// Use in-place new which doesn't allocate any memory:
				
				new (hook) GameObjectHook( movingObjects[i] );
				
				// Add the hook:
				
				addHook(hook); hook++;
			}
		}		
	}	
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::collisionStatic()
Purpose:  Destroys the safe iteration cache. Required to free up hook slots. 
		  Done after iteration through a series of objects is finshed.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::DestroySafeIterationCache()
{
    // Remove all previously created hooks:    	

	for ( unsigned i = 0 ; i < safeIterationCache.original_static_count ; i++ )
	{
		// Remove this hook:
		
		removeHook( safeIterationCache.static_hooks + i );
	}
	
	// Now moving object hooks:
	
	for ( unsigned i = 0 ; i < safeIterationCache.original_moving_count ; i++ )
	{
		// Remove this hook:
		
		removeHook( safeIterationCache.moving_hooks + i );
	}
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::collisionStatic()
Purpose:  Does collision testing of a moving object against a static object.
          Bounding sphere to polygon testing is used. Assumes both objects are
          solid and have meshes.
Params:   as commented
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::collisionStatic
(
    MovingGameObject * collider,  // object moving
    StaticGameObject * collidee   // object being tested against
)
{
    //--------------------------------------------------------------------------
    // Rough test, Get the distance between the collider and collidee:
    //--------------------------------------------------------------------------

    // First get the positions of their two bounding spheres:

    float colliderSpherePos[3] =
    {
        collider->position[0] + collider->mesh->getSphereCenterX(),
        collider->position[1] + collider->mesh->getSphereCenterY(),
        collider->position[2] + collider->mesh->getSphereCenterZ()
    };

    float collideeSpherePos[3] =
    {
        collidee->position[0] + collidee->mesh->getSphereCenterX(),
        collidee->position[1] + collidee->mesh->getSphereCenterY(),
        collidee->position[2] + collidee->mesh->getSphereCenterZ()
    };

    // Get the distance between these two positions

    float boundingSphereDistance = mlDistance3d
    (
        colliderSpherePos ,
        collideeSpherePos
    );

    // Get the sum of the bounding sphere radii for both objects

    float radiiSum = collider->mesh->getSphereRadius() + collidee->mesh->getSphereRadius();

    // If the distance is greater than the sum of the radii then the two objects
    // cannot intersect. Inflate the radii sum by an error margin of 2% also to
    // account for floating point inaccuracy.

    if ( boundingSphereDistance > radiiSum * 1.02f )
    {
        // No collision can occur: abort

        return;
    }

    //--------------------------------------------------------------------------
    // Save the number of collisions detected here and an averaged normal to
    // reflect the velocity through:
    //--------------------------------------------------------------------------

    int numCollisions = 0; float reflectNormal[3] = { 0 , 0 , 0 };

    //--------------------------------------------------------------------------
    // If the rough bounding sphere test failed, then test every polygon for
    // intersetion with the sphere:
    //--------------------------------------------------------------------------

    // Get the vertex,normal,edge normals, and smoothed edge normals array of the collidee's mesh

    const float * verts             = collidee->mesh->getVertexArray();
    const float * norms             = collidee->mesh->getNormalArray();
    const float * edgeNorms         = collidee->mesh->getEdgeNormalArray();

    //--------------------------------------------------------------------------
    // Because the static model we want to collide with may be positioned and
    // rotated arbitrarily, and because we want to avoid rotating and translating
    // the static object's model vertices- translate the colliders bounding
    // sphere position into the coordinate system of this object and work from
    // within that coordinate system. This simple trick bypasses a whole lot of
    // extra work for the cpu:
    //--------------------------------------------------------------------------

    // First step is to translate the bounding sphere and position of the collider
    // by the inverse position of the collidee:

    colliderSpherePos[0]    -= collidee->position[0];
    colliderSpherePos[1]    -= collidee->position[1];
    colliderSpherePos[2]    -= collidee->position[2];

    collider->position[0]   -= collidee->position[0];
    collider->position[1]   -= collidee->position[1];
    collider->position[2]   -= collidee->position[2];

    // Get the orientation matrix of the collidee:

    float inverse[9]; collidee->getOrientationMatrix(inverse);

    // Transpose it to invert the rotatation operation:

    mlTranspose3x3(inverse);

    // Now transform the colliders position and sphere position by this rotation:

    mlTransform3d( colliderSpherePos  , inverse );
    mlTransform3d( collider->position , inverse );

    //--------------------------------------------------------------------------
    // Do a bounding sphere test against every triangle: but do not move the
    // sphere. We are only interested in getting an averaged reflection normal
    // for collision response in this pass:
    //--------------------------------------------------------------------------

    for ( unsigned i = collidee->mesh->getNumTriangles() ; i != 0 ; i -- )
    {
        //----------------------------------------------------------------------
        // Get the distance from the bounding sphere to the plane formed by the
        // triangle:
        //----------------------------------------------------------------------

        float planeDist = mlPointToPlaneDistance3d
        (
            colliderSpherePos,      // point to get distance to plane from
            norms,                  // plane normal
            verts                   // plane point
        );

        //----------------------------------------------------------------------
        // If the distance is greater than the colliders bounding sphere radius
        // then move onto the next triangle. The polygon and sphere cannot
        // intersect in this case. Also consider the case where the distance is
        // negative- in this case the polygon is a backface to the sphere and
        // the two objects cannot collide:
        //----------------------------------------------------------------------

        if ( planeDist <= 0 || planeDist >= collider->mesh->getSphereRadius() )
        {
            // Sphere-Polygon cannot intersect: Move onto the next triangle

            verts               += 9;
            norms               += 9;
            edgeNorms           += 9;

            // Next loop iteration

            continue;
        }

        //----------------------------------------------------------------------
        // Do a dot product of sphere position with the edge plane normals
        // for all three edges:
        //----------------------------------------------------------------------

        float dot1 =
        {
            edgeNorms[0] * ( colliderSpherePos[0] - verts[0] )
            +
            edgeNorms[1] * ( colliderSpherePos[1] - verts[1] )
            +
            edgeNorms[2] * ( colliderSpherePos[2] - verts[2] )
        };

        float dot2 =
        {
            edgeNorms[3] * ( colliderSpherePos[0] - verts[3] )
            +
            edgeNorms[4] * ( colliderSpherePos[1] - verts[4] )
            +
            edgeNorms[5] * ( colliderSpherePos[2] - verts[5] )
        };

        float dot3 =
        {
            edgeNorms[6] * ( colliderSpherePos[0] - verts[6] )
            +
            edgeNorms[7] * ( colliderSpherePos[1] - verts[7] )
            +
            edgeNorms[8] * ( colliderSpherePos[2] - verts[8] )
        };

        //----------------------------------------------------------------------
        // If all 3 dot products are positive then the bounding sphere center
        // lies within the planes defined by the edges of the triangle:
        //----------------------------------------------------------------------

        if ( dot1 > 0 && dot2 > 0 && dot3 > 0 )
        {
            // Increment the number of collisions:

            numCollisions++;

            // Add the normal of this triangle to the reflection normal

            reflectNormal[0] += norms[0];
            reflectNormal[1] += norms[1];
            reflectNormal[2] += norms[2];
        }
        else
        {
            //------------------------------------------------------------------
            // If there has been no collision detected yet then check for a
            // collision against each edge: we are not interested which edge
            // was collided with, only if there has been some form of collision.
            // In the case where the sphere of the collider only hits an edge
            // we want to still reverse the direction of the colliders velocity
            //------------------------------------------------------------------

            // Save the colliders original bounding sphere position

            float sphereOriginalPos[3] =
            {
                colliderSpherePos[0],
                colliderSpherePos[1],
                colliderSpherePos[2]
            };

            // Do collision detection against edge 1:

            if (    mlSphereLineCollision3d
                    (
                        verts,
                        verts + 3,
                        colliderSpherePos,
                        collider->mesh->getSphereRadius()
                    )
                )
            {
                // Increment the number of collisions:

                numCollisions++;

                // Add the normal of this triangle to the reflection normal

                reflectNormal[0] += norms[0];
                reflectNormal[1] += norms[1];
                reflectNormal[2] += norms[2];
            }

            // Do collision detection against edge 2:

            if (    mlSphereLineCollision3d
                    (
                        verts + 3,
                        verts + 6,
                        colliderSpherePos,
                        collider->mesh->getSphereRadius()
                    )
                )
            {
                // Increment the number of collisions:

                numCollisions++;

                // Add the normal of this triangle to the reflection normal

                reflectNormal[0] += norms[0];
                reflectNormal[1] += norms[1];
                reflectNormal[2] += norms[2];
            }

            // Do collision detection against edge 3:

            if (    mlSphereLineCollision3d
                    (
                        verts + 6,
                        verts,
                        colliderSpherePos,
                        collider->mesh->getSphereRadius()
                    )
                )
            {
                // Increment the number of collisions:

                numCollisions++;

                // Add the normal of this triangle to the reflection normal

                reflectNormal[0] += norms[0];
                reflectNormal[1] += norms[1];
                reflectNormal[2] += norms[2];
            }

            // Restore the colliders original bounding sphere position

            colliderSpherePos[0] = sphereOriginalPos[0];
            colliderSpherePos[1] = sphereOriginalPos[1];
            colliderSpherePos[2] = sphereOriginalPos[2];
        }

        //----------------------------------------------------------------------
        // Move onto the next triangle
        //----------------------------------------------------------------------

        verts               += 9;
        norms               += 9;
        edgeNorms           += 9;

    } //  end of for each triangle do collision response

    //--------------------------------------------------------------------------
    // Move the pointers of all the vertex arrays back to the start:
    //--------------------------------------------------------------------------

    // Get the vertex,normal,edge normals, and smoothed edge normals array of the collidee's mesh

    verts             = collidee->mesh->getVertexArray();
    norms             = collidee->mesh->getNormalArray();
    edgeNorms         = collidee->mesh->getEdgeNormalArray();

    //--------------------------------------------------------------------------
    // Do a bounding sphere test against every triangle: this time only move the
    // sphere and do not consider collision response
    //--------------------------------------------------------------------------

    for ( unsigned i = collidee->mesh->getNumTriangles() ; i != 0 ; i -- )
    {
        //----------------------------------------------------------------------
        // Get the distance from the bounding sphere to the plane formed by the
        // triangle:
        //----------------------------------------------------------------------

        float planeDist = mlPointToPlaneDistance3d
        (
            colliderSpherePos,      // point to get distance to plane from
            norms,                  // plane normal
            verts                   // plane point
        );

        //----------------------------------------------------------------------
        // If the distance is greater than the colliders bounding sphere radius
        // then move onto the next triangle. The polygon and sphere cannot
        // intersect in this case. Also consider the case where the distance is
        // negative- in this case the polygon is a backface to the sphere and
        // the two objects cannot collide:
        //----------------------------------------------------------------------

        if ( planeDist <= 0 || planeDist >= collider->mesh->getSphereRadius() )
        {
            // Sphere-Polygon cannot intersect: Move onto the next triangle

            verts               += 9;
            norms               += 9;
            edgeNorms           += 9;

            // Next loop iteration

            continue;
        }

        //----------------------------------------------------------------------
        // Do a dot product of sphere position with the edge plane normals
        // for all three edges:
        //----------------------------------------------------------------------

        float dot1 =
        {
            edgeNorms[0] * ( colliderSpherePos[0] - verts[0] )
            +
            edgeNorms[1] * ( colliderSpherePos[1] - verts[1] )
            +
            edgeNorms[2] * ( colliderSpherePos[2] - verts[2] )
        };

        float dot2 =
        {
            edgeNorms[3] * ( colliderSpherePos[0] - verts[3] )
            +
            edgeNorms[4] * ( colliderSpherePos[1] - verts[4] )
            +
            edgeNorms[5] * ( colliderSpherePos[2] - verts[5] )
        };

        float dot3 =
        {
            edgeNorms[6] * ( colliderSpherePos[0] - verts[6] )
            +
            edgeNorms[7] * ( colliderSpherePos[1] - verts[7] )
            +
            edgeNorms[8] * ( colliderSpherePos[2] - verts[8] )
        };

        //----------------------------------------------------------------------
        // If all 3 dot products are positive then the bounding sphere center
        // lies within the planes defined by the edges of the triangle:
        //----------------------------------------------------------------------

        if ( dot1 > 0 && dot2 > 0 && dot3 > 0 )
        {
            //------------------------------------------------------------------
            // Bounding sphere center within all three plane half spaces of the
            // polygon. Move back along the polygon normal by the amount it
            // penetrates the plane:
            //------------------------------------------------------------------

            float penetration = collider->mesh->getSphereRadius() - planeDist;

            colliderSpherePos[0]  += norms[0] * penetration;
            colliderSpherePos[1]  += norms[1] * penetration;
            colliderSpherePos[2]  += norms[2] * penetration;

            collider->position[0] += norms[0] * penetration;
            collider->position[1] += norms[1] * penetration;
            collider->position[2] += norms[2] * penetration;
        }
        else
        {
            //------------------------------------------------------------------
            // If this test failed then do an edge to sphere collision test
            // and move the position of the sphere if it comes too close to
            // an edge:
            //------------------------------------------------------------------

            // Save the original bounding sphere position first

            float sphereOriginalPos[3] =
            {
                colliderSpherePos[0],
                colliderSpherePos[1],
                colliderSpherePos[2]
            };

            // Save whether there has been an edge collision here:

            bool edgeCollision = false;

            // Do collision detection against edge 1:

            edgeCollision |= mlSphereLineCollision3d
            (
                verts,
                verts + 3,
                colliderSpherePos,
                collider->mesh->getSphereRadius()
            );

            // Do collision detection against edge 2:

            edgeCollision |= mlSphereLineCollision3d
            (
                verts + 3,
                verts + 6,
                colliderSpherePos,
                collider->mesh->getSphereRadius()
            );

            // Do collision detection against edge 3:

            edgeCollision |= mlSphereLineCollision3d
            (
                verts + 6,
                verts,
                colliderSpherePos,
                collider->mesh->getSphereRadius()
            );

            // Move the collider if there was a collision

            if ( edgeCollision )
            {
                // Move the collider by the difference between the orginal bounding sphere position and its current position:

                collider->position[0] += colliderSpherePos[0] - sphereOriginalPos[0];
                collider->position[1] += colliderSpherePos[1] - sphereOriginalPos[1];
                collider->position[2] += colliderSpherePos[2] - sphereOriginalPos[2];
            }
        }

        //----------------------------------------------------------------------
        // Move onto the next triangle
        //----------------------------------------------------------------------

        verts               += 9;
        norms               += 9;
        edgeNorms           += 9;

    } //  end of for each triangle do collision correction

    //--------------------------------------------------------------------------
    // Now because we previously transformed the collider into the coordinate
    // system of the collidee, we need to translate back to get back into world
    // coordinates:
    //--------------------------------------------------------------------------

    // Undo the previous rotation on the colliders position

    mlTransform3d( collider->position , collidee->orientation );

    // Undo the previous translation on the colliders position

    collider->position[0] += collidee->position[0];
    collider->position[1] += collidee->position[1];
    collider->position[2] += collidee->position[2];

    //--------------------------------------------------------------------------
    // If there was a collision then call the on collision event on the collider
    // and collidee and reverse the colliders velocity direction
    //--------------------------------------------------------------------------

    if ( numCollisions != 0 )
    {
        // Calculate the averaged normal for all the faces and edges the collider has collided with:

        reflectNormal[0] /= float(numCollisions);
        reflectNormal[1] /= float(numCollisions);
        reflectNormal[2] /= float(numCollisions);

        mlNormalise3d(reflectNormal);

        // Transform the colliders velocity into the coordinate system of the collidee

        mlTransform3d( collider->velocity , inverse );

        // Reflect this vector about the reflection normal calculated

        mlReflect3d( collider->velocity , reflectNormal );

        // Now transform the velocity back into world coordinates

        mlTransform3d( collider->velocity , collidee->orientation );

        // Reverse the velocity direction of the collider also. This is done after all reflections.

        collider->velocity[0] *= -1;
        collider->velocity[1] *= -1;
        collider->velocity[2] *= -1;

        //======================================================================
        //======================================================================
        //
        // FAO: JOE BENNET - PHYSICS
        //
        // If there has been a collision between a moveable object and an
        // inmovable object then the principle of conversation of linear momentum
        // will not apply. In this case I define the speed of the moving object
        // after collision to be the speed of this object before collision, times
        // the co-efficient of restitution. In this case a certain amount of the
        // moving object's momementum has been lost.
        //
        // In other words:
        //
        // E = ( Separation Speed / Approach speed )
        //
        // ( E ) * ( Approach Speed ) = ( Separation Speed )
        //
        // Now only the moving objects speed is considered here, since the other
        // object being collided with is static and doesn't move, so this is
        // really:
        //
        // ( Moving Object Speed After Collision ) = ( E ) * ( Moving object speed before collision )
        //
        //======================================================================
        //======================================================================

        // Get the velocity amount of the collider before collision:

        float velocityBefore = collider->getVelocityAmount();

        // Multiply the velocity by the collision elasticity constant or co-efficient of restitution

        collider->velocity[0] *= STATIC_COLLISION_ELASTICITY;
        collider->velocity[1] *= STATIC_COLLISION_ELASTICITY;
        collider->velocity[2] *= STATIC_COLLISION_ELASTICITY;

        // Get the velocity amount of the collider after the collision:

        float velocityAfter = velocityBefore * STATIC_COLLISION_ELASTICITY;

        // Calculate the loss in velocity:

        float velocityLoss = velocityBefore - velocityAfter;

        // If the loss in velocity is sufficient enough, then play a hit sound and damage the collider:

        if ( velocityLoss >= MIN_STATIC_COLLISION_VELOCITY_LOSS )
        {
            // Play a collision noise on the collider:

            collider->playCollisionSound();

            // Damage the collider by the amount of velocity it has lost times the damage constant:

            collider->damage( STATIC_COLLISION_VELOCITY_LOSS_DAMAGE * velocityLoss , 0 );            
        }
        
        // Call the collision events

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

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::collisionMoving()
Purpose:  Does collision testing of a moving object against another moving object.
          Bounding sphere to bounding sphere testing is used. Assumes both objects
          are solid and have meshes.
Params:   as commented
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GameObjectScene::collisionMoving
(
    MovingGameObject * collider ,  // object moving
    MovingGameObject * collidee    // object being tested against
)
{
    // Get the bounding sphere position of the collider and collidee

    float colliderSpherePos[3] =
    {
        collider->position[0] + collider->mesh->getSphereCenterX(),
        collider->position[1] + collider->mesh->getSphereCenterY(),
        collider->position[2] + collider->mesh->getSphereCenterZ()
    };

    float collideeSpherePos[3] =
    {
        collidee->position[0] + collidee->mesh->getSphereCenterX(),
        collidee->position[1] + collidee->mesh->getSphereCenterY(),
        collidee->position[2] + collidee->mesh->getSphereCenterZ()
    };

    // Get the bounding sphere radius of both the collider and collidee

    float colliderRadius = collider->mesh->getSphereRadius();
    float collideeRadius = collidee->mesh->getSphereRadius();

    // Get the distance between the two bounding spheres

    float distance = mlDistance3d( colliderSpherePos , collideeSpherePos );

    // If the distance is less than the sum of the radii then the two objects collide:

    if ( distance < colliderRadius + collideeRadius )
    {
        //----------------------------------------------------------------------
        // Collision: find out the depth of penetration
        //----------------------------------------------------------------------

        float penetration = colliderRadius + collideeRadius - distance;

        // Now get a vector from the center of the collidee to the collider:

        float moveVector[3] =
        {
            colliderSpherePos[0] - collideeSpherePos[0],
            colliderSpherePos[1] - collideeSpherePos[1],
            colliderSpherePos[2] - collideeSpherePos[2]
        };

        // Normalise the vector

        mlNormalise3d( moveVector );

        // Scale it by the penetration amount:

        moveVector[0] *= penetration;
        moveVector[1] *= penetration;
        moveVector[2] *= penetration;

        // Now move the collider back to where it doesn't collide by this vector amount:

        collider->position[0] += moveVector[0];
        collider->position[1] += moveVector[1];
        collider->position[2] += moveVector[2];

        //----------------------------------------------------------------------
        // Damage both objects, but by how much ?
        //----------------------------------------------------------------------

        // Get the weight, and combined weight of both objects:

        float w1 = collider->getMass();
        float w2 = collider->getMass();
        float cw = w1 + w2;

        // Get the velocity and total velocity for both objects

        float v1 = collider->getVelocityAmount();
        float v2 = collider->getVelocityAmount();
        float tv = v1 + v2;

        // See if the velocity is enough to warrant damage and a collision noise:

        if ( tv >= MIN_MOVING_COLLISION_VELCITY )
        {
            // Play the damage noise for both parties

            collider->playCollisionSound();
            collidee->playCollisionSound();

            // Get the total amount of damage to be applied to both objects:

            float totalDamage = tv * MOVING_COLLISION_VELOCITY_DAMAGE;

            // Figure out how much damage both objects take and damage them

            float p1 = w1 / cw;     collider->damage( totalDamage * p1 , 0 );
            float p2 = w2 / cw;     collidee->damage( totalDamage * p2 , 0 );
        }

        //======================================================================
        //======================================================================
        //
        // FAO: JOE BENNET - PHYSICS
        //
        // *********************************************************************
        // ************************* Variables *********************************
        //
        // Let 'iv1' be the initial velocity of object 1
        // Let 'iv2' be the initial velocity of object 2
        //
        // Let 'fv1' be the final velocity (after collision) of object 1
        // Let 'fv2' be the final velocity (after collision) of object 2
        //
        // Let 'm1' be the mass of object 1
        // Let 'm2' be the mass of object 2
        //
        // Let 'e' be the coefficient of restitution
        //
        // *********************************************************************
        // ********************** Basic Equations ******************************
        //
        // From newtons conservation of linear momentum it is found that:
        //
        // ( m1 * iv1 ) + ( m2 * iv2 ) = ( m1 * fv1 ) + ( m2 * fv2 )    .... equation 1
        //
        // And from newtons law of restitution the coefficient of restituion is:
        //
        // e = ( separation speed ) / ( approach speed )
        //
        // e = ( fv1 - fv2 ) / ( iv1 - iv2 )                            .... equation 2
        //
        // where e is a constant which defines the elasiticity of the collision
        //
        // *********************************************************************
        // ************************ From the equation 2: ***********************
        //
        // fv2 = fv1 - (e)( iv1 - iv2 )                         .... equation 3
        // fv1 = fv2 + (e)( iv1 - iv2 )                         .... equation 4
        //
        // *********************************************************************
        // ******************** Solving for fv1 and fv2:  **********************
        //
        // Substituting equation 3 into equation 1 and solving for fv1 we find:
        //
        // fv1 = ( ( m1 * iv1 ) + ( m2 * iv2 ) + ( m2 * e * ( iv1 - iv2 ) ) ) / ( m1 + m2 )
        //
        // Substituting equation 4 into equation 1 and solving for fv2 we find:
        //
        // fv2 = ( ( m1 * iv1 ) + ( m2 * iv2 ) - ( m1 * e * ( iv1 - iv2 ) ) ) / ( m1 + m2 )
        //
        // *********************************************************************
        // ********************* Acutal implementation  ************************
        //
        // This is a 3 dimensional problem since all objects in the game have
        // 3 dimensional positions and velocities. With the code below I split
        // this problem into three separate dimensions and solve for the velocities
        // in each dimension separately.
        //
        //======================================================================
        //======================================================================

        // Get the variables needed for the problem:

        float iv1[3] =
        {
            collider->velocity[0] ,     // x velocity
            collider->velocity[1] ,     // y velocity
            collider->velocity[2]       // z velocity
        };

        float iv2[3] =
        {
            collidee->velocity[0] ,     // x velocity
            collidee->velocity[1] ,     // y velocity
            collidee->velocity[2]       // z velocity
        };

        float m1 = collider->getMass();             // mass of the object
        float m2 = collidee->getMass();             // mass of the object
        float e  = MOVING_COLLISION_ELASTICITY;     // coefficient of restitution

        // Hold final velocities here:

        float fv1[3];
        float fv2[3];

        // Solve for fv1 in all 3 dimensions:

        fv1[0] = ( m1 * iv1[0] + m2 * iv2[0] + ( m2 * e * ( iv1[0] - iv2[0] ) ) ) / ( m1 + m2 );
        fv1[1] = ( m1 * iv1[1] + m2 * iv2[1] + ( m2 * e * ( iv1[1] - iv2[1] ) ) ) / ( m1 + m2 );
        fv1[2] = ( m1 * iv1[2] + m2 * iv2[2] + ( m2 * e * ( iv1[2] - iv2[2] ) ) ) / ( m1 + m2 );

        // Solve for fv2 in all 3 dimensions:

        fv2[0] = ( m1 * iv1[0] + m2 * iv2[0] - ( m1 * e * ( iv1[0] - iv2[0] ) ) ) / ( m1 + m2 );
        fv2[1] = ( m1 * iv1[1] + m2 * iv2[1] - ( m1 * e * ( iv1[1] - iv2[1] ) ) ) / ( m1 + m2 );
        fv2[2] = ( m1 * iv1[2] + m2 * iv2[2] - ( m1 * e * ( iv1[2] - iv2[2] ) ) ) / ( m1 + m2 );

        // Set the actual final velocity of both objects:

        collider->velocity[0] = fv1[0];
        collider->velocity[1] = fv1[1];
        collider->velocity[2] = fv1[2];

        collidee->velocity[0] = fv2[0];
        collidee->velocity[1] = fv2[1];
        collidee->velocity[2] = fv2[2];

        //======================================================================
        //======================================================================
        //
        // My own adjustments. Takes into account where the two spheres hit
        // and causes one object to bounce away from the other.
        //
        //======================================================================
        //======================================================================

        // Reverse the colliders and collidees velocity:

        mlScale3d( collider->velocity , -1 );

        // Reflect the colliders velocity vector through the vector to the centre of the collidee

        mlReflect3d( collider->velocity , moveVector );

        // Reflect the collidees velocity vector through the vector to the centre of the collidee

        mlReflect3d( collidee->velocity , moveVector );

        //----------------------------------------------------------------------
        // Finally call the collision events on both objects
        //----------------------------------------------------------------------

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

}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::rayCast()
Purpose:  Casts a ray from given point and in given direction and returns what
          it hits, if anything. If nothing is hit then null gets returned. Also
          saves the position of hit on finding a hit.
Params:   as commented
Returns:  object that was hit, null if no object was hit.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GameObject * GameObjectScene::rayCast
(
    const GameObject  *  excludeObject,    // an object to exclude from the test: may be null
    const float       *  origin,           // point ray starts at
    const float       *  direction,        // direction ray goes in (does not need to be normalised)
    float             *  hitPoint          // 3d vector to save hit position to
)
{
    //--------------------------------------------------------------------------
    // Save the closest object that was hit here:
    //--------------------------------------------------------------------------

    GameObject * hitObject = 0;

    //--------------------------------------------------------------------------
    // Check against every static object:
    //--------------------------------------------------------------------------

    StaticGameObject ** staticObjectArray = staticObjects;

    for ( unsigned i = staticObjectCount ; i ; i-- )
    {
        // If the current object is the object to exclude from testing then go onto the next iteration:

        if ( * staticObjectArray == excludeObject )
        {
            // This object must be excluded: move onto the next object

            staticObjectArray++;

            // Next loop iteration:

            continue;
        }

        // Save the hit position here:

        float position[3];

        // Do a check against the object: check if it is the closest hit if hit by ray

        if ( rayCastObject(*staticObjectArray,origin,direction,position) )
        {
            // Hit the object: see if we have a hit to date...

            if ( hitObject )
            {
                // Get vector going from ray start to current hit position

                float hitVec1[3] =
                {
                    hitPoint[0] - origin[0],
                    hitPoint[1] - origin[1],
                    hitPoint[2] - origin[2]
                };

                // Get vector going from ray start to new hit point

                float hitVec2[3] =
                {
                    position[0] - origin[0],
                    position[1] - origin[1],
                    position[2] - origin[2]
                };

                // Get the magnitude of both vectors

                float hitMag1 = mlMagnitude3d(hitVec1);
                float hitMag2 = mlMagnitude3d(hitVec2);

                // If the new hit magnitude is smaller then new hit point is closer and hence should be saved:

                if ( hitMag2 < hitMag1 )
                {
                    // New hit point is closer: save object hit

                    hitObject = * staticObjectArray;

                    // Save also the position of the hit:

                    hitPoint[0] = position[0];
                    hitPoint[1] = position[1];
                    hitPoint[2] = position[2];
                }
            }
            else
            {
                // Haven't hit any object yet: save object hit

                hitObject = * staticObjectArray;

                // Save the position where the ray strikes object also

                hitPoint[0] = position[0];
                hitPoint[1] = position[1];
                hitPoint[2] = position[2];
            }

        }  // end if hit the object

        // Move onto the next object pointer in the array

        staticObjectArray++;

    }   // end for all static objects do hit testing

    //--------------------------------------------------------------------------
    // Check against every moving object:
    //--------------------------------------------------------------------------

    MovingGameObject ** movingObjectArray = movingObjects;

    for ( unsigned i = movingObjectCount ; i ; i-- )
    {
        // If the current object is the object to exclude from testing then go onto the next iteration:

        if ( * movingObjectArray == excludeObject )
        {
            // This object must be excluded: move onto the next object

            movingObjectArray++;

            // Next loop iteration:

            continue;
        }

        // Save the hit position here:

        float position[3];

        // Do a check against the object: check if it is the closest hit if hit by ray

        if ( rayCastObject(*movingObjectArray,origin,direction,position) )
        {
            // Hit the object: see if we have a hit to date...

            if ( hitObject )
            {
                // Get vector going from ray start to current hit position

                float hitVec1[3] =
                {
                    hitPoint[0] - origin[0],
                    hitPoint[1] - origin[1],
                    hitPoint[2] - origin[2]
                };

                // Get vector going from ray start to new hit point

                float hitVec2[3] =
                {
                    position[0] - origin[0],
                    position[1] - origin[1],
                    position[2] - origin[2]
                };

                // Get the magnitude of both vectors

                float hitMag1 = mlMagnitude3d(hitVec1);
                float hitMag2 = mlMagnitude3d(hitVec2);

                // If the new hit magnitude is smaller then new hit point is closer and hence should be saved:

                if ( hitMag2 < hitMag1 )
                {
                    // New hit point is closer: save object hit

                    hitObject = * movingObjectArray;

                    // Save also the position of the hit:

                    hitPoint[0] = position[0];
                    hitPoint[1] = position[1];
                    hitPoint[2] = position[2];
                }
            }
            else
            {
                // Haven't hit any object yet: save object hit

                hitObject = * movingObjectArray;

                // Save the position where the ray strikes object also

                hitPoint[0] = position[0];
                hitPoint[1] = position[1];
                hitPoint[2] = position[2];
            }

        }  // end if hit the object

        // Move onto the next object pointer in the array

        movingObjectArray++;

    }  // end for all static objects do hit testing

    //--------------------------------------------------------------------------
    // Returnt the object hit:
    //--------------------------------------------------------------------------

    return hitObject;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::rayCastObject()
Purpose:  Casts a ray from given point and in given direction and checks against
          the given object. Returns true on a hit and false on no hit. Saves the
          point of hit if there was a collision.
Params:   as commented
Returns:  true if the object was hit by the ray, false if not

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

bool GameObjectScene::rayCastObject
(
    GameObject  *  object,         // object to check against
    const float *  origin,         // point ray starts at
    const float *  direction,      // direction ray goes in (does not need to be normalised)
    float       *  hitPoint        // 3d vector to save hit position to
)
{
    //--------------------------------------------------------------------------
    // If the object concerned has no mesh or isn't solid then don't bother
    // checking.. There is absolutely no point in this...
    //--------------------------------------------------------------------------

    if ( object->mesh == 0 || object->solid == false ) return false;

    //--------------------------------------------------------------------------
    // Save whether a triangle in the object was hit yet here:
    //--------------------------------------------------------------------------

    bool hit = false;

    //--------------------------------------------------------------------------
    // Get the objects bounding sphere position and sphere radius (squared):
    //--------------------------------------------------------------------------

    // bounding sphere position

    float spherePos[3] =
    {
        object->position[0] + object->mesh->getSphereCenterX(),
        object->position[1] + object->mesh->getSphereCenterY(),
        object->position[2] + object->mesh->getSphereCenterZ()
    };

    // bounding sphere radius squared

    float sphereRadius = object->mesh->getSphereRadius(); sphereRadius *= sphereRadius;

    //--------------------------------------------------------------------------
    // Early out: reject objects that are behind the ray if the ray start
    // point does not fall within the bounding sphere of the object:
    //--------------------------------------------------------------------------

    // Get a vector from the the ray start to the bounding sphere center of the object:

    float rayToSphereVec[3] =
    {
        spherePos[0] - origin[0],
        spherePos[1] - origin[1],
        spherePos[2] - origin[2]
    };

    // Do a dot product with the ray direction:

    float raySphereVecDotRayDirection;

    raySphereVecDotRayDirection =  rayToSphereVec[0] * direction[0];
    raySphereVecDotRayDirection += rayToSphereVec[1] * direction[1];
    raySphereVecDotRayDirection += rayToSphereVec[2] * direction[2];

    //--------------------------------------------------------------------------
    // Now if the dot product is negative then the sphere center is behind the
    // ray start, we will have to check if the ray is within the sphere:
    //--------------------------------------------------------------------------

    if ( raySphereVecDotRayDirection < 0 )
    {
        //----------------------------------------------------------------------
        // Ok this test failed. Get the squared distance from the ray start to
        // the bounding spheres position:
        //----------------------------------------------------------------------

        float distance = mlSquaredDistance3d( origin , spherePos );

        //----------------------------------------------------------------------
        // If this distance is greater than the bounding sphere radius of the
        // mesh then abort the test. The ray will not intersect any geometry:
        //----------------------------------------------------------------------

        if ( distance > sphereRadius )
        {
            // Ray cannot intersect with the sphere: abort test

            return false;
        }
    }

    //--------------------------------------------------------------------------
    // Get the minimum squared distance from this to the ray line:
    //--------------------------------------------------------------------------

    float distance = mlPointSquaredDistanceToLine3d
    (
        spherePos,
        origin,
        direction
    );

    //--------------------------------------------------------------------------
    // Another early out: If the squared distance not is less than the bounding
    // sphere squared radius then there is no chance of the ray hitting this
    // object. Also add in a 2% error margin to allow for floating point inprecision:
    //--------------------------------------------------------------------------

    if ( distance < sphereRadius * 1.02f )
    {
        //----------------------------------------------------------------------
        // Ok, so the object passed the broad phase check. First job is to
        // transform the ray into the object's coordinate system to save on
        // the job of rotating/translating all the polygons in the objects mesh
        //----------------------------------------------------------------------

        // Declare a position and direction for the ray in local object coordinates:

        float localPos[3] =
        {
            origin[0],
            origin[1],
            origin[2]
        };

        float localDir[3] =
        {
            direction[0],
            direction[1],
            direction[2]
        };

        // Translate the ray position by inverse of object position:

        localPos[0] -= object->position[0];
        localPos[1] -= object->position[1];
        localPos[2] -= object->position[2];

        // Get object orientation matrix:

        float orientation[9]; object->getOrientationMatrix(orientation);

        // Invert the orientation matrix:

        mlTranspose3x3(orientation);

        // Now rotate the ray direction and position vector by the inverted rotation:

        mlTransform3d( localPos , orientation );
        mlTransform3d( localDir , orientation );

        //----------------------------------------------------------------------
        // Now do per polygon hit testing for against every object polygon:
        //----------------------------------------------------------------------

        // First get access to the objects vertex and normal, and edge normal arrays:

        const float * vertex       = object->mesh->getVertexArray();
        const float * normal       = object->mesh->getNormalArray();
        const float * edgeNormal   = object->mesh->getEdgeNormalArray();

        // Save the magnitude of the vector to the current closest ray-triangle intersection point here:

        float closestHitMag = 99999999999.0f;

        // Now check against every single polygon:

        for ( unsigned i = object->mesh->getNumTriangles() ; i ; i-- )
        {
            //------------------------------------------------------------------
            //
            // Ray-plane intersection theory:
            //
            // Let 'P' be a plane. Any point p on the plane is defined as:
            //
            // n.p = n.p0
            //
            // where n is the plane normal, p any arbitrary point on the plane,
            // and p0 one of the points on the plane used to define the plane.
            //
            // Now the equation of a ray is:
            //
            // s + tv
            //
            // where s is the start point, v is the ray direction and t a varible.
            //
            // Now substituting the ray equation for 'p' in the plane equation
            // we get the following expression:
            //
            // n.( s + tv ) = n.p0
            //
            // Expanding to solve for t we find:
            //
            // n.s + tn.v = n.p0
            // tn.v = n.p0 - n.s
            // t = ( n.p0 - n.s ) / ( n.v )
            //
            // Substituting value for 't' into ray equation yields point of intersection
            //
            //------------------------------------------------------------------

            //------------------------------------------------------------------
            // Find n.v first:
            //------------------------------------------------------------------

            float n_dot_v;

            n_dot_v  = normal[0] * localDir[0];
            n_dot_v += normal[1] * localDir[1];
            n_dot_v += normal[2] * localDir[2];

            //------------------------------------------------------------------
            // If n.v is greater or equal to zero then the ray is either on a paralel
            // plane to polygon (in which case it will never intersect) or polygon
            // is a back face to the ray, in which case no test is performed:
            //------------------------------------------------------------------

            if ( n_dot_v > 0 )
            {
                // Ray cannot intersect polygon. continue onto next polygon:

                vertex      += 9;
                normal      += 9;
                edgeNormal  += 9;

                // next loop iteration:

                continue;
            }

            //------------------------------------------------------------------
            // Now find n.s
            //------------------------------------------------------------------

            float n_dot_s;

            n_dot_s  = normal[0] * localPos[0];
            n_dot_s += normal[1] * localPos[1];
            n_dot_s += normal[2] * localPos[2];

            //------------------------------------------------------------------
            // Now find n.p0
            //------------------------------------------------------------------

            float n_dot_p0;

            n_dot_p0  = normal[0] * vertex[0];
            n_dot_p0 += normal[1] * vertex[1];
            n_dot_p0 += normal[2] * vertex[2];

            //------------------------------------------------------------------
            // Now that we have all the elements to find t, solve for t:
            //------------------------------------------------------------------

            float t = ( n_dot_p0 - n_dot_s ) / ( n_dot_v );

            //------------------------------------------------------------------
            // If t is negative then we have gone past ray start, abort the
            // test with this polygon:
            //------------------------------------------------------------------

            if ( t < 0 )
            {
                // Move pointers onto the next polygon:

                normal      += 9;
                vertex      += 9;
                edgeNormal  += 9;

                // Next loop iteration:

                continue;
            }

            //------------------------------------------------------------------
            // Now given t, find the point where the ray strikes the polygons plane:
            //------------------------------------------------------------------

            float planePoint[3] =
            {
                localPos[0] + localDir[0] * t,
                localPos[1] + localDir[1] * t,
                localPos[2] + localDir[2] * t
            };

            //------------------------------------------------------------------
            // Do a dot product of plane intersect point with the plane normals
            // for all three edges: if any of the dot products are greater than
            // zero then take an early out since the point is not inside the
            // triangle
            //------------------------------------------------------------------

            // Get the 1st dot product

            float dot1;

            dot1  = edgeNormal[0] * ( planePoint[0] - vertex[0] );
            dot1 += edgeNormal[1] * ( planePoint[1] - vertex[1] );
            dot1 += edgeNormal[2] * ( planePoint[2] - vertex[2] );

            // Get the 2nd dot product

            float dot2;

            dot2  = edgeNormal[3] * ( planePoint[0] - vertex[3] );
            dot2 += edgeNormal[4] * ( planePoint[1] - vertex[4] );
            dot2 += edgeNormal[5] * ( planePoint[2] - vertex[5] );

            // Get the 3rd dot product

            float dot3;

            dot3  = edgeNormal[6] * ( planePoint[0] - vertex[6] );
            dot3 += edgeNormal[7] * ( planePoint[1] - vertex[7] );
            dot3 += edgeNormal[8] * ( planePoint[2] - vertex[8] );

            //------------------------------------------------------------------
            // If all 3 dot products are positive then the plane intersect point
            // lies within the planes defined by the edges of the triangle:
            //------------------------------------------------------------------

            if ( dot1 >= 0 && dot2 >= 0 && dot3 >= 0 )
            {
                //--------------------------------------------------------------
                // See if there was already a hit with a polygon:
                //--------------------------------------------------------------

                if ( hit )
                {
                    // Get the vector from the ray start to the current hit point

                    float hitVec[3] =
                    {
                        planePoint[0] - localPos[0],
                        planePoint[1] - localPos[1],
                        planePoint[2] - localPos[2]
                    };

                    // Get the magnitude of this vector

                    float hitMag =
                    {
                        hitVec[0] * hitVec[0]
                        +
                        hitVec[1] * hitVec[1]
                        +
                        hitVec[2] * hitVec[2]
                    };

                    // Now if the new hit point is closer than the current closest hit point then save as the new hit point

                    if ( hitMag < closestHitMag )
                    {
                        // Save the new hit point:

                        hitPoint[0] = planePoint[0];
                        hitPoint[1] = planePoint[1];
                        hitPoint[2] = planePoint[2];

                        // Save the magntitude of the vector to this point:

                        closestHitMag = hitMag;
                    }
                }
                else
                {
                    // No hit with a polygon yet: save current plane point as hit point

                    hitPoint[0] = planePoint[0];
                    hitPoint[1] = planePoint[1];
                    hitPoint[2] = planePoint[2];

                    // Get the vector from the ray start to the current hit point

                    float hitVec[3] =
                    {
                        planePoint[0] - localPos[0],
                        planePoint[1] - localPos[1],
                        planePoint[2] - localPos[2]
                    };

                    // Save the magnitude of this vector as the magnitude to the closest hit point

                    closestHitMag  = hitVec[0] * hitVec[0];
                    closestHitMag += hitVec[1] * hitVec[1];
                    closestHitMag += hitVec[2] * hitVec[2];

                    // Set the 'hit' flag to true to indicate a polygon was hit

                    hit = true;
                }

            }   // end if plane point is inside polygon edges

            //------------------------------------------------------------------
            // Move onto the next polygon:
            //------------------------------------------------------------------

            vertex      += 9;
            normal      += 9;
            edgeNormal  += 9;

        }   // end of for every polygon do hit test

        //----------------------------------------------------------------------
        // If there was a hit then transform the hit position back into world
        // coordinates:
        //----------------------------------------------------------------------

        if ( hit )
        {
            // First rotate the hit point by the objects orientation

            mlTransform3d( hitPoint , object->orientation );

            // Now translate it back by the objects position:

            hitPoint[0] += object->position[0];
            hitPoint[1] += object->position[1];
            hitPoint[2] += object->position[2];
        }

    }  // end if ray distance to bounding sphere center is less than sphere radius

    //--------------------------------------------------------------------------
    // Return whether the object was hit or not
    //--------------------------------------------------------------------------

    return hit;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::getBestTargetForObject()
Purpose:  Gives a pointer back to an object for which the vector between the source
          object and this object is closest in direction to that of the source objects
          forward vector.
Params:   Source object to get best target for
Returns:  Best target object, null if no suitable target is found

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GameObject * GameObjectScene::getBestTargetForObject( GameObject * sourceObject )
{
    //--------------------------------------------------------------------------
    // If the source object is null then return null:
    //--------------------------------------------------------------------------

    if ( sourceObject == 0 ) return 0;

    //--------------------------------------------------------------------------
    // Set the current largest dot product between the normalised vector going
    // from the source/target and source forward vector as zero:
    //--------------------------------------------------------------------------

    float largestDot = 0;

    //--------------------------------------------------------------------------
    // Set the current best target as null:
    //--------------------------------------------------------------------------

    GameObject * bestTarget = 0;

    //--------------------------------------------------------------------------
    // Search the static object array for a suitable target
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < staticObjectCount ; i++ )
    {
        //----------------------------------------------------------------------
        // If this object is the same as source object then continue on:
        //----------------------------------------------------------------------

        if ( staticObjects[i] == sourceObject ) continue;

        //----------------------------------------------------------------------
        // If this object is not targetable then abort
        //----------------------------------------------------------------------

        if ( staticObjects[i]->isTargetable() == false ) continue;

        //----------------------------------------------------------------------
        // Get a vector from the source object to this object:
        //----------------------------------------------------------------------

        float vectorTo[3] =
        {
            staticObjects[i]->position[0] - sourceObject->position[0],
            staticObjects[i]->position[1] - sourceObject->position[1],
            staticObjects[i]->position[2] - sourceObject->position[2]
        };

        // Normalise this vector:

        mlNormalise3d(vectorTo);

        //----------------------------------------------------------------------
        // Now get a dot product between this and the source objects forward vector
        //----------------------------------------------------------------------

        float dot =
        {
            vectorTo[0] * sourceObject->orientation[6]
            +
            vectorTo[1] * sourceObject->orientation[7]
            +
            vectorTo[2] * sourceObject->orientation[8]
        };

        //----------------------------------------------------------------------
        // If this dot product is greater then the current largest dot then
        // make this object the current best target object:
        //----------------------------------------------------------------------

        if ( dot > largestDot )
        {
            // Set the new best target object

            bestTarget = staticObjects[i];

            // Set the new largest dot product:

            largestDot = dot;
        }

    } // end for every static object check if best target

    //--------------------------------------------------------------------------
    // Search the moving object array for a suitable target
    //--------------------------------------------------------------------------

    for ( unsigned i = 0 ; i < movingObjectCount ; i++ )
    {
        //----------------------------------------------------------------------
        // If this object is the same as source object then continue on:
        //----------------------------------------------------------------------

        if ( movingObjects[i] == sourceObject ) continue;

        //----------------------------------------------------------------------
        // If this object is not targetable then abort
        //----------------------------------------------------------------------

        if ( movingObjects[i]->isTargetable() == false ) continue;

        //----------------------------------------------------------------------
        // Get a vector from the source object to this object:
        //----------------------------------------------------------------------

        float vectorTo[3] =
        {
            movingObjects[i]->position[0] - sourceObject->position[0],
            movingObjects[i]->position[1] - sourceObject->position[1],
            movingObjects[i]->position[2] - sourceObject->position[2]
        };

        // Normalise this vector:

        mlNormalise3d(vectorTo);

        //----------------------------------------------------------------------
        // Now get a dot product between this and the source objects forward vector
        //----------------------------------------------------------------------

        float dot =
        {
            vectorTo[0] * sourceObject->orientation[6]
            +
            vectorTo[1] * sourceObject->orientation[7]
            +
            vectorTo[2] * sourceObject->orientation[8]
        };


        //----------------------------------------------------------------------
        // If this dot product is greater then the current largest dot then
        // make this object the current best target object:
        //----------------------------------------------------------------------

        if ( dot > largestDot )
        {
            // Set the new best target object

            bestTarget = movingObjects[i];

            // Set the new largest dot product:

            largestDot = dot;
        }

    } // end for every moving object check if best target

    //--------------------------------------------------------------------------
    // Finally, return the best target object
    //--------------------------------------------------------------------------

    return bestTarget;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::findObject()
Purpose:  Searches the scene for the first instance of a given object
Params:   Name of the object to look for
Returns:  Null if no object of this type was found, otherwise a pointer to the
          first object in the scene of this type

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GameObject * GameObjectScene::findObject( const char * objectName )
{
    // If the name given was null then return null:

    if ( objectName == 0 ) return 0;

    // Search the static object array first for the given object:

    for ( unsigned i = 0 ; i < staticObjectCount ; i++ )
    {
        // If this object has no name then move onto the next object:

        if ( staticObjects[i]->name == 0 ) continue;

        // See if the name of this object matches the name given:

        if ( strcmp( objectName , staticObjects[i]->name ) == 0 )
        {
            // Found the object we were looking for: return it

            return staticObjects[i];
        }
    }

    // Search the moving object for the given object:

    for ( unsigned i = 0 ; i < movingObjectCount ; i++ )
    {
        // If this object has no name then move onto the next object:

        if ( movingObjects[i]->name == 0 ) continue;

        // See if the name of this object matches the name given:

        if ( strcmp( objectName , movingObjects[i]->name ) == 0 )
        {
            // Found the object we were looking for: return it

            return movingObjects[i];
        }
    }

    // If we have got down to here return null: object not found

    return 0;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GameObjectScene::findNextObject()
Purpose:  Searches the scene for the next instance of a given object
Params:   Object to look for the next instance of the same type of
Returns:  Null if no other object of this type was found, otherwise a pointer
          to the next object in the scene of this type

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GameObject * GameObjectScene::findNextObject( const GameObject * object )
{
    // If the object given was null then return null:

    if ( object == 0 ) return 0;

    // Fix to allow object->isStatic to be called: reinterpret constant

    GameObject * obj = (GameObject*)(object);

    // See if the object is static or moveable:

    if ( obj->isStatic() )
    {
        // Static object: look in the static object array for the next of this type

        for ( unsigned i = obj->sceneArrayPos + 1 ; i < staticObjectCount ; i++ )
        {
            // See if the name of this object matches that of the object given:

            if ( staticObjects[i]->name == obj->name )
            {
                // Found another object of the same type: return it

                return staticObjects[i];
            }
        }
    }
    else
    {
        // Moveable object: look in the moving object array for the next of this type

        for ( unsigned i = obj->sceneArrayPos + 1 ; i < movingObjectCount ; i++ )
        {
            // See if the name of this object matches that of the object given:

            if ( movingObjects[i]->name == obj->name )
            {
                // Found another object of the same type: return it

                return movingObjects[i];
            }
        }
    }

    // If we have got to down here then return null: no object found

    return 0;
}
