

#include "CPhysicsCarWheel.h"




void _cdecl PhysicsCarWheelUpdate(const NewtonJoint *vehicle)
{
    void * wheelid = 0;
    for(wheelid = NewtonVehicleGetFirstTireID(vehicle); wheelid; wheelid = NewtonVehicleGetNextTireID(vehicle, wheelid))
    {
        CPhysicsCarWheel *wheel = (CPhysicsCarWheel *)NewtonVehicleGetTireUserData(vehicle, wheelid);
        wheel->setTirePhysics(vehicle, wheelid);
    }
}


CPhysicsCarWheel::CPhysicsCarWheel()
{
    m_steerAngle = 0.0f;
    m_torque = 0.0f;
    m_brakes = 0.0f;

    m_radius = 0.0f;
}

CPhysicsCarWheel::~CPhysicsCarWheel()
{
}

void CPhysicsCarWheel::setSteer(f32 newsteerangle)
{
    m_steerAngle = newsteerangle;
}

void CPhysicsCarWheel::setTorque(f32 torque)
{
	m_torque = torque;
}

void CPhysicsCarWheel::setBrakes(f32 brakes)
{
    m_brakes = brakes;
}

ISceneNode* CPhysicsCarWheel::getNode()
{
	return m_wheelNode;
}

void CPhysicsCarWheel::setNode(ISceneNode* node)
{
	m_wheelNode = node;
}


void CPhysicsCarWheel::setTirePhysics(const NewtonJoint *vehicle, void* id)
{
	f32 omega;
	f32 speed;
	f32 brakeAcceleration;


	dFloat currentSteerAngle;

	currentSteerAngle = NewtonVehicleGetTireSteerAngle (vehicle, id);
	NewtonVehicleSetTireSteerAngle (vehicle, id, currentSteerAngle +  (m_steerAngle - currentSteerAngle) * 0.25f);

	// get the tire angular velocity
	omega = NewtonVehicleGetTireOmega(vehicle, id);

	// add some viscous damp to the tire torque (this prevents out of control spin)
	NewtonVehicleSetTireTorque (vehicle, id, m_torque - (40.f * omega));

	// calculate the tire speed at the contact
	// set the max side slip speed as a fraction of the tire speed
	speed = m_radius * omega;
	NewtonVehicleSetTireMaxSideSleepSpeed (vehicle, id, speed * 0.8f);

	// The side slip is usually proportional to the tire longitudinal speed, and tire load
	NewtonVehicleSetTireSideSleepCoeficient (vehicle, id, speed * 0.5f);

	// if the brakes are applied...
	if (m_brakes > 0.0f) 
	{
		// ask Newton for the precise acceleration needed to stop the tire
		brakeAcceleration = NewtonVehicleTireCalculateMaxBrakeAcceleration (vehicle, id);

		// tell Newton you want this tire stoped but only if the torque needed is less than 
		// the brake pad can withstand (assume max brake pad torque is 500 newton * meter)
		NewtonVehicleTireSetBrakeAcceleration (vehicle, id, brakeAcceleration, 500.0f * m_brakes);

		// set some side slipe as funtion of the linear speed 
		speed = NewtonVehicleGetTireLongitudinalSpeed (vehicle, id);
		NewtonVehicleSetTireMaxSideSleepSpeed (vehicle, id, speed * 0.1f);
	}
	// reset the brakes
	m_brakes = 0.0f;
}

void CPhysicsCarWheel::rigupPhysics(NewtonJoint *vehicle, vector3df wheelPosition, SPhysicsCar* car, CPhysicsCarWheel *wheelpointer, s32 tyreid)
{ 
	m_radius = car->tireRadius;

	// create the tyre's position
    matrix4 tirePosition;
    tirePosition.setTranslation(wheelPosition);

    // the tire will spin around the lateral axis of the same tire space
	f32 tirePin[3];
	tirePin[0] = 0.0f;
	tirePin[1] = 0.0f;
	tirePin[2] = 1.0f;

    
	// add the tire and set this as the user data
    // parent should be the vehicle joint

	NewtonVehicleAddTire (vehicle, tirePosition.pointer(), &tirePin[0], car->tireMass, car->tireWidth, car->tireRadius, 
						  car->tireSuspensionShock, car->tireSuspensionSpring, car->tireSuspensionLength, 
						  wheelpointer, tyreid);
}

