/*
	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:   GameObject
// Purpose:      Very important class that serves as a base class for the two
//               main types of objects in the game, moving and static objects.
//               These two sub classes then in turn serve as the basis for every
//               single object in the game.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

#include "GameObject.h"

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

Name:     GameObject::GameObject()
Purpose:  Constructor for base game object class
Params:   as commented
Returns:  n/a

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

GameObject::GameObject
(
    float       pos_x,      // initial position: x
    float       pos_y,      // initial position: y
    float       pos_z,      // initial position: z
    Mesh    *   mesh        // object's mesh
)
{
    // Set position

    position[0] = pos_x;
    position[1] = pos_y;
    position[2] = pos_z;

    // Set the mesh used

    this->mesh = mesh;

    // Object is visible by default:

    visible = true;

    // Object is solid by default:

    solid = true;

    // Object is indestructable by default:

    indestructable = true;

    // Reset object orientation

    resetOrientation();

    // Set the GameObjectScene the object belongs to as null

    scene = 0;

    // Set the objects name to no name by default:

    name = "";

    // By default all objects are targetable

    targetable = true;
}

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

Name:     GameObject::resetOrientation()
Purpose:  Resets the objects orientation to the default
Params:   none
Returns:  none

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

void GameObject::resetOrientation()
{
    // Initialise object orientation matrix to the identity

    orientation[0] = 1;
    orientation[1] = 0;
    orientation[2] = 0;

    orientation[3] = 0;
    orientation[4] = 1;
    orientation[5] = 0;

    orientation[6] = 0;
    orientation[7] = 0;
    orientation[8] = 1;
}

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

Name:     GameObject::rotateX()
Purpose:  Rotate objects orientation about its own X axis by given angle (in radians)
Params:   amount to rotate by
Returns:  none

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

void GameObject::rotateX( float angle )
{
    // Make up two unit vectors: representing the y and z axis

    float vecy[3] = { 0 , 1 , 0 };
    float vecz[3] = { 0 , 0 , 1 };

    // Rotate these vectors about the y axis

    mlRotate3dX( vecy , -angle );
    mlRotate3dX( vecz , -angle );

    // Now make up a 3x3 matrix with the two rotated vectors as columns and another column for the other axis (x)

    float rotation[9] =
    {
        1 ,  vecy[0] , vecz[0],
        0 ,  vecy[1] , vecz[1],
        0 ,  vecy[2] , vecz[2]
    };

    // Describe the rotation in terms of the objects orientation: save to orientation matrix

    mlMatrixMult3x3( rotation, orientation );

    // Orthogonalise orientation matrix: done to prevent error build up

    mlOrthogonalise3x3(orientation);

    // Normalise the orientation matrix: done to prevent error build up

    mlNormalise3x3(orientation);
}

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

Name:     GameObject::rotateY()
Purpose:  Rotate objects orientation about its own Y axis by given angle (in radians)
Params:   amount to rotate by
Returns:  none

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

void GameObject::rotateY( float angle )
{
    // Make up two unit vectors: representing the x and z axis

    float vecx[3] = { 1 , 0 , 0 };
    float vecz[3] = { 0 , 0 , 1 };

    // Rotate these vectors about the y axis

    mlRotate3dY( vecx , angle );
    mlRotate3dY( vecz , angle );

    // Now make up a 3x3 matrix with the two rotated vectors as columns and another column for the other axis (y)

    float rotation[9] =
    {
        vecx[0] , 0 , vecz[0],
        vecx[1] , 1 , vecz[1],
        vecx[2] , 0 , vecz[2]
    };

    // Describe the rotation in terms of the objects current orientation

    mlMatrixMult3x3( rotation , orientation );

    // Orthogonalise orientation matrix: done to prevent error build up

    mlOrthogonalise3x3(orientation);

    // Normalise the orientation matrix: done to prevent error build up

    mlNormalise3x3(orientation);
}

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

Name:     GameObject::rotateZ()
Purpose:  Rotate objects orientation about its own Z axis by given angle (in radians)
Params:   amount to rotate by
Returns:  none

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

void GameObject::rotateZ( float angle )
{
    // Make up two unit vectors: representing the x and y axis

    float vecx[3] = { 1 , 0 , 0 };
    float vecy[3] = { 0 , 1 , 0 };

    // Rotate these vectors about the z axis

    mlRotate3dZ( vecx , angle );
    mlRotate3dZ( vecy , angle );

    // Now make up a 3x3 matrix with the two rotated vectors as columns and another column for the other axis (z)

    float rotation[9] =
    {
        vecx[0] , vecy[0] , 0 ,
        vecx[1] , vecy[1] , 0 ,
        vecx[2] , vecy[2] , 1
    };

    // Describe the rotation in terms of the objecst orientation

    mlMatrixMult3x3( rotation , orientation );

    // Orthogonalise orientation matrix: done to prevent error build up

    mlOrthogonalise3x3(orientation);

    // Normalise the orientation matrix: done to prevent error build up

    mlNormalise3x3(orientation);
}

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

Name:     GameObject::getOrientationMatrix()
Purpose:  Saves objects orientation matrix to the matrix given.
Params:   Matrix to save orientation to.
Returns:  none

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

void GameObject::getOrientationMatrix( float * matrix ) const
{
    // Abort on null pointer

    if ( matrix == 0 ) return;

    // Otherwise save the orientation matrix to matrix given

    matrix[0] = orientation[0];
    matrix[1] = orientation[1];
    matrix[2] = orientation[2];

    matrix[3] = orientation[3];
    matrix[4] = orientation[4];
    matrix[5] = orientation[5];

    matrix[6] = orientation[6];
    matrix[7] = orientation[7];
    matrix[8] = orientation[8];
}

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

Name:     GameObject::setOrientationMatrix()
Purpose:  Sets the objects orientation matrix to the 3x3 matrix given:
Params:   Matrix to set orientation to
Returns:  none

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

void GameObject::setOrientationMatrix( float * matrix )
{
    // Abort on null pointer:

    if ( matrix == 0 ) return;

    // Otherwise set:

    for ( unsigned i = 0 ; i < 9 ; i++ ) this->orientation[i] = matrix[i];
}

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

Name:     GameObject::damage()
Purpose:  Damages object by given amount and calls on damage event for the object
Params:   amount to damage by, object which did the damage- can be null
Returns:  none

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

void GameObject::damage( float amount , GameObject * damager )
{
    // If damage amount is nothing or negative then abort:

    if ( amount <= 0 ) return;

    // Otherwise reduce this objects health:

    this->health -= amount;

    // Make sure health doesn't go negative:

    if ( this->health < 0 ) this->health = 0;

    // Call the on dammage event on this object:

    this->onDamage( damager );
}

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

Name:     GameObject::toObjectCoordinates()
Purpose:  Converts the given world position into the objects local coordinate system.
Params:   position to convert into object coordinates
Returns:  none

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

void GameObject::toObjectCoordinates( float * position ) const
{
    // Put the objects inverse position into a 4x4 homgenous matrix:

    float translation[16];

    translation[0 ] = 1;
    translation[1 ] = 0;
    translation[2 ] = 0;
    translation[3 ] = 0;

    translation[4 ] = 0;
    translation[5 ] = 1;
    translation[6 ] = 0;
    translation[7 ] = 0;

    translation[8 ] = 0;
    translation[9 ] = 0;
    translation[10] = 1;
    translation[11] = 0;

    translation[12] = -this->position[0];
    translation[13] = -this->position[1];
    translation[14] = -this->position[2];
    translation[15] = 1;

    // Convert the objects inverse orientation into a 4x4 homgenous matrix:

    float rotation[16];

    rotation[0 ] = this->orientation[0];
    rotation[1 ] = this->orientation[3];
    rotation[2 ] = this->orientation[6];
    rotation[3 ] = 0;

    rotation[4 ] = this->orientation[1];
    rotation[5 ] = this->orientation[4];
    rotation[6 ] = this->orientation[7];
    rotation[7 ] = 0;

    rotation[8 ] = this->orientation[2];
    rotation[9 ] = this->orientation[5];
    rotation[10] = this->orientation[8];
    rotation[11] = 0;

    rotation[12] = 0;
    rotation[13] = 0;
    rotation[14] = 0;
    rotation[15] = 1;

    // Combine these two operations, rotation and translation- but do translation first:

    mlMatrixMult4x4( translation , rotation );

    // Now convert the position vector into a homogenous vector:

    float pos[4] =
    {
        position[0],
        position[1],
        position[2],
        1
    };

    // Transform this position by the combined rotation and translation, this will
    // conver the position given into the objects coordinate system:

    mlTransform4d( pos , rotation );

    // Save the result back to the vector given:

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


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

Name:     GameObject::faceObject()
Purpose:  Makes this object face towards the given object.
Params:   Object to face towards
Returns:  none

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

void GameObject::faceObject( const GameObject * object )
{
    // Get the world position of the object and make this object face it:

    if ( object )
    {
        float pos[3] =
        {
            object->getPosX(),
            object->getPosY(),
            object->getPosZ()
        };

        facePoint(pos);
    }
}

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

Name:     GameObject::faceObject()
Purpose:  Makes this object face towards the given object.
Params:   Object to face towards, maximum allowed rotation to face that point
Returns:  none

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

void GameObject::faceObject( const GameObject * object , float maxRotation )
{
    // Get the world position of the object and make this object face it:

    if ( object )
    {
        float pos[3] =
        {
            object->getPosX(),
            object->getPosY(),
            object->getPosZ()
        };

        facePoint(pos,maxRotation);
    }
}

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

Name:     GameObject::facePoint()
Purpose:  Makes this object face towards the given point in world coordinates.
Params:   Point to face towards
Returns:  none

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

void GameObject::facePoint( const float * point )
{
    // If the given point is null then abort:

    if ( point == 0 ) return;

    // Ttransform the points position into this objects coordinate system:

    float pointPosition[3] =
    {
        point[0],
        point[1],
        point[2]
    };

    this->toObjectCoordinates(pointPosition);

    // Normalise the points position vector:

    mlNormalise3d(pointPosition);

    // Make sure the point position z coordinate is in the right range for the inverse cosine function:

    pointPosition[2] = pointPosition[2] < -1 ? -1 : pointPosition[2];
    pointPosition[2] = pointPosition[2] >  1 ?  1 : pointPosition[2];

    // Get the inverse cosine of the z component:

    float acosz = acosf( pointPosition[2] );

    //--------------------------------------------------------------------------
    // If either the x and z coordinates of the points position are not zero
    // then make this object face towards given point on its own xz plane:
    //--------------------------------------------------------------------------

    if ( pointPosition[0] != 0 || pointPosition[2] != 0 )
    {
        //----------------------------------------------------------------------
        // The inverse cosine of the z component gives the angle between the
        // this objects forward vector and the points position. If the x component
        // of the points position vector is negative we need to rotate by the
        // negative of this angle to make this object face the given point on its
        // own xz plane, if the x component is positive however then rotate by the
        // positive of this angle:
        //----------------------------------------------------------------------

        if ( pointPosition[0] > 0 )
        {
            rotateY(  acosz );
        }
        else
        {
            rotateY( -acosz );
        }

    }

    // Now get the points position again and re-transform into this objects coordinates:

    pointPosition[0] = point[0];
    pointPosition[1] = point[1];
    pointPosition[2] = point[2];

    this->toObjectCoordinates(pointPosition);

    // Normalise the points position vector:

    mlNormalise3d(pointPosition);

    // Make sure the point position z coordinate is in the right range for the inverse cosine function:

    pointPosition[2] = pointPosition[2] < -1 ? -1 : pointPosition[2];
    pointPosition[2] = pointPosition[2] >  1 ?  1 : pointPosition[2];

    // Get the inverse cosine of the z component:

    acosz = acosf( pointPosition[2] );

    //--------------------------------------------------------------------------
    // If either the y and z coordinates of the points position vector are not
    // zero then make the object face towards its target on its own yz plane:
    //--------------------------------------------------------------------------

    if ( pointPosition[1] != 0 || pointPosition[2] != 0 )
    {
        //----------------------------------------------------------------------
        // The inverse cosine of the z component gives the angle between this
        // objects forward vector and the points position. If the y component
        // of the points position vector is positive we need to rotate by the
        // negative of this angle to make this object face the point on its own
        // yz plane, if the y component is negative however then rotate by the
        // positive of this angle:
        //----------------------------------------------------------------------

        if ( pointPosition[1] >= 0 )
        {
            rotateX( -acosz );
        }
        else
        {
            rotateX(  acosz );
        }
    }
}

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

Name:     GameObject::facePoint()
Purpose:  Makes this object face towards the given point in world coordinates.
Params:   Point to face towards. maximum amount of rotation allowed to face the
          point.
Returns:  none

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

void GameObject::facePoint( const float * point , float maxRotation )
{
    // If the given point is null then abort:

    if ( point == 0 ) return;

    // Make sure max rotation is positive

    maxRotation = fabs(maxRotation);

    // Ttransform the points position into this objects coordinate system:

    float pointPosition[3] =
    {
        point[0],
        point[1],
        point[2]
    };

    this->toObjectCoordinates(pointPosition);

    // Normalise the points position vector:

    mlNormalise3d(pointPosition);

    // Make sure the point position z coordinate is in the right range for the inverse cosine function:

    pointPosition[2] = pointPosition[2] < -1 ? -1 : pointPosition[2];
    pointPosition[2] = pointPosition[2] >  1 ?  1 : pointPosition[2];

    // Get the inverse cosine of the z component:

    float acosz = acosf( pointPosition[2] );

    //--------------------------------------------------------------------------
    // Since this inverse cosine gives the angle to move to face an object and
    // we want to restrict that angle, make sure the angle does not go above the
    // maximum allowed rotation amount:
    //--------------------------------------------------------------------------

    if ( acosz < 0 )
    {
        // Negative case: clamp to -maximum rotate amount

        acosz = acosz < -maxRotation ? -maxRotation : acosz;
    }
    else
    {
        // Positive case: clamp to maximum rotate amount

        acosz = acosz > maxRotation ? maxRotation : acosz;
    }

    //--------------------------------------------------------------------------
    // If either the x and z coordinates of the points position are not zero
    // then make this object face towards given point on its own xz plane:
    //--------------------------------------------------------------------------

    if ( pointPosition[0] != 0 || pointPosition[2] != 0 )
    {
        //----------------------------------------------------------------------
        // The inverse cosine of the z component gives the angle between the
        // this objects forward vector and the points position. If the x component
        // of the points position vector is negative we need to rotate by the
        // negative of this angle to make this object face the given point on its
        // own xz plane, if the x component is positive however then rotate by the
        // positive of this angle:
        //----------------------------------------------------------------------

        if ( pointPosition[0] > 0 )
        {
            rotateY(  acosz );
        }
        else
        {
            rotateY( -acosz );
        }
    }

    // Now get the points position again and re-transform into this objects coordinates:

    pointPosition[0] = point[0];
    pointPosition[1] = point[1];
    pointPosition[2] = point[2];

    this->toObjectCoordinates(pointPosition);

    // Normalise the points position vector:

    mlNormalise3d(pointPosition);

    // Make sure the point position z coordinate is in the right range for the inverse cosine function:

    pointPosition[2] = pointPosition[2] < -1 ? -1 : pointPosition[2];
    pointPosition[2] = pointPosition[2] >  1 ?  1 : pointPosition[2];

    // Get the inverse cosine of the z component:

    acosz = acosf( pointPosition[2] );

    //--------------------------------------------------------------------------
    // Since this inverse cosine gives the angle to move to face an object and
    // we want to restrict that angle, make sure the angle does not go above the
    // maximum allowed rotation amount:
    //--------------------------------------------------------------------------

    if ( acosz < 0 )
    {
        // Negative case: clamp to -maximum rotate amount

        acosz = acosz < -maxRotation ? -maxRotation : acosz;
    }
    else
    {
        // Positive case: clamp to maximum rotate amount

        acosz = acosz > maxRotation ? maxRotation : acosz;
    }

    //--------------------------------------------------------------------------
    // If either the y and z coordinates of the points position vector are not
    // zero then make the object face towards its target on its own yz plane:
    //--------------------------------------------------------------------------

    if ( pointPosition[1] != 0 || pointPosition[2] != 0 )
    {

        //----------------------------------------------------------------------
        // The inverse cosine of the z component gives the angle between this
        // objects forward vector and the points position. If the y component
        // of the points position vector is positive we need to rotate by the
        // negative of this angle to make this object face the point on its own
        // yz plane, if the y component is negative however then rotate by the
        // positive of this angle:
        //----------------------------------------------------------------------

        if ( pointPosition[1] >= 0 )
        {
            rotateX( -acosz );
        }
        else
        {
            rotateX(  acosz );
        }
    }
}

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

Name:     GameObject::distanceTo()
Purpose:  Finds the distance between this object and another given object
Params:   Object to find distance to
Returns:  distance between the two objects

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

float GameObject::distanceTo( const GameObject * object )
{
    // Return zero if the other object is null

    if ( object == 0 ) return 0;

    // Makeup a vector going between the two objects:

    float betweenVec[3] =
    {
        this->getPosX() - object->getPosX(),
        this->getPosY() - object->getPosY(),
        this->getPosZ() - object->getPosZ()
    };

    // Return the lenght of this vector

    return mlLenght3d(betweenVec);
}

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

Name:     GameObject::squareDistanceTo()
Purpose:  Finds the square distance between this object and another given object
Params:   Object to find distance to
Returns:  distance between the two objects

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

float GameObject::squareDistanceTo( const GameObject * object )
{
    // Return zero if the other object is null

    if ( object == 0 ) return 0;

    // Makeup a vector going between the two objects:

    float betweenVec[3] =
    {
        this->getPosX() - object->getPosX(),
        this->getPosY() - object->getPosY(),
        this->getPosZ() - object->getPosZ()
    };

    // Return the magnitude of this vector

    return mlMagnitude3d(betweenVec);
}
