//--------------------------------------------------------------------------------------
// Copyright (C) 2008 http://shift.delblanco.es
//--------------------------------------------------------------------------------------
// SHIFT Videogame is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//--------------------------------------------------------------------------------------
// 3DPhysics.cpp
//--------------------------------------------------------------------------------------
#include "dxstdafx.h"
#include "3DPhyVehicle.h"
#include "3DObjVehicle.h"
#include "3DObject.h"
#include "Player.h"

//--------------------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------------------
C3DPhyVehicle::C3DPhyVehicle()
{
    m_pVehicle = NULL;
    m_pAditionalLSpeed = 0.0f;
}

//--------------------------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------------------------
C3DPhyVehicle::~C3DPhyVehicle()
{
}

//--------------------------------------------------------------------------------------
// Inicializa el sistema físico
//--------------------------------------------------------------------------------------
bool C3DPhyVehicle::initialize(C3DObjVehicle *Vehicle)
{
    // Almacenamos el objeto asociado
    m_pVehicle = Vehicle;
    m_pObject = Vehicle;

    return true;
}

//--------------------------------------------------------------------------------------
// Aplica los parámetros físicos
//--------------------------------------------------------------------------------------
void C3DPhyVehicle::update()
{
    // Tiempo desde la última actualización
    float ElapsedTime = DXUTGetElapsedTime();

	//--------------------------------------------------------------------------------------
	// Física linear
	//--------------------------------------------------------------------------------------
    // Velocidad lineal adicional
    if(m_pAditionalLSpeed != 0)
	{
		// Resto la fricción
		if(m_fLFriction != 0)
		{
			if(m_pAditionalLSpeed > 0) m_pAditionalLSpeed = max(m_pAditionalLSpeed - ((m_pObject->getCollision()->getMass() / PHYVEHICLE_FRICTION_COEF) * m_fLFriction * ElapsedTime), 0);
			else                       m_pAditionalLSpeed = min(m_pAditionalLSpeed + ((m_pObject->getCollision()->getMass() / PHYVEHICLE_FRICTION_COEF) * m_fLFriction * ElapsedTime), 0);
		}

		// Recalculo la dirección de desplazamientos adicionales como la ortogonal a la dirección
		m_pAditionalLDirection = D3DXVECTOR3(m_pLDirection.z, 0.0f , -m_pLDirection.x);

		// Aplico los desplazamientos adicionales
        m_pObject->addPosition(m_pAditionalLDirection * m_pAditionalLSpeed * ElapsedTime);
	}

}

//--------------------------------------------------------------------------------------
// Establece desplazamientos adicionales para el vehículo
//--------------------------------------------------------------------------------------
void C3DPhyVehicle::setAditionalL (D3DXVECTOR3 &Vec)
{
	float factor;

	// Actualizo la velocidad del vehículo
	float SpeedAdd = D3DXVec3Dot(&Vec, &m_pLDirection);
	m_fLSpeed = SpeedAdd;

	// Recalculo la dirección de desplazamientos adicionales como la ortogonal a la dirección
	m_pAditionalLDirection = D3DXVECTOR3(m_pLDirection.z, 0.0f , -m_pLDirection.x);

	// Actualizo el adicional del vehículo
	float AditionalAdd = D3DXVec3Dot(&Vec, &m_pAditionalLDirection);
	m_pAditionalLSpeed = AditionalAdd;

	// Calculo la fuerza de la colisión
	factor = max(min((fabs(m_pVehicle->getLastSpeed() - SpeedAdd) + fabs(AditionalAdd)) / m_pVehicle->getMaxSpeed(), 1.0f), 0.0f);

	// Activo el sonido de colisión en función de la fuerza de la colisión
	m_pVehicle->playCrash(false, (long)(min(9600.0f * 2.0f * factor - 9600.0f, 0.0f)) );

	// Quitamos vida en función de la fuerza de la colisión
	CPlayer *player = m_pVehicle->getPlayer();
	if (player && factor >= 0.5f) player->setHealth(player->getHealth() - factor);
}

//--------------------------------------------------------------------------------------
// Toma el vector normalizado de desplazamientos lineales adicionales
//--------------------------------------------------------------------------------------
D3DXVECTOR3 *C3DPhyVehicle::getAditionalLDirection (void)
{
	// Recalculo la dirección de desplazamientos adicionales como la ortogonal a la dirección
	m_pAditionalLDirection = D3DXVECTOR3(m_pLDirection.z, 0.0f , -m_pLDirection.x);
	return &m_pAditionalLDirection;
}
