///////// Material Manager Class ////////////////////
/// This class handles all calls to newton material
/// manager.
/////////////////////////////////////// IPhysics ////


#include "IMaterialCallback.h"

/// Constructor for the class.
IMaterialCallback::IMaterialCallback()
{

}

IMaterialCallback::~IMaterialCallback()
{

}

/// Disables the contact for this material.
void IMaterialCallback::disableContact(bool disable)
{
	NewtonMaterialDisableContact(m_material);
}

/// Returns the attribute the face with which the contact had occured.
unsigned IMaterialCallback::getContactFaceAttribute()
{
	return NewtonMaterialGetContactFaceAttribute(m_material);;
}

f32 IMaterialCallback::getTimeStep()
{
	return NewtonMaterialGetCurrentTimestep(m_material);;
}

f32 IMaterialCallback::getContactNormalSpeed()
{
	return NewtonMaterialGetContactNormalSpeed(m_material, m_contact);
}

f32 IMaterialCallback::getContactTangentSpeed(int tangentIndex)
{
	return NewtonMaterialGetContactTangentSpeed(m_material, m_contact, tangentIndex);;
}

vector3df IMaterialCallback::getContactPosition()
{
	vector3df contactPos, temp;
	NewtonMaterialGetContactPositionAndNormal(m_material, &contactPos.X, &temp.X);
	return contactPos * NewtonToIrr;
}

vector3df IMaterialCallback::getContactNormal()
{
	vector3df contactNorm;
	NewtonMaterialGetContactPositionAndNormal(m_material, NULL, &contactNorm.X);
	return contactNorm;
}

vector3df IMaterialCallback::getContactForce()
{
	vector3df contactForce;
	NewtonMaterialGetContactForce(m_material, &contactForce.X);
	return contactForce;
}

vector3df IMaterialCallback::getContactPrimaryTangent()
{
	vector3df contactPTangent;
	NewtonMaterialGetContactTangentDirections(m_material, &contactPTangent.X, NULL);
	return contactPTangent;
}

vector3df IMaterialCallback::getContactSecondaryTangent()
{
	vector3df contactSTangent;
	NewtonMaterialGetContactTangentDirections(m_material, NULL, &contactSTangent.X);
	return contactSTangent;
}

int IMaterialCallback::getBodyCollisionID()
{
	//return NewtonMaterGetBodyCollisionID(material, contact);
	return 0;
}

void IMaterialCallback::setContactSoftneess(f32 softness)
{
	NewtonMaterialSetContactSoftness(m_material, softness);
}

void IMaterialCallback::setContactElasticity(f32 elasticity)
{
	NewtonMaterialSetContactElasticity(m_material, elasticity);
}

void IMaterialCallback::setContactFriction(bool friction, int tangentIndex)
{
	NewtonMaterialSetContactFrictionState(m_material, friction, tangentIndex);
}

void IMaterialCallback::setContactStaticFriction(f32 staticFriction, int tangentIndex)
{
	NewtonMaterialSetContactStaticFrictionCoef(m_material,  staticFriction, tangentIndex);
}

void IMaterialCallback::setContactKineticFriction(f32 kineticFriction, int tangentIndex)
{
	NewtonMaterialSetContactKineticFrictionCoef(m_material,  kineticFriction, tangentIndex);
}

void IMaterialCallback::setContactNormalAcceleration(f32 accel)
{
	NewtonMaterialSetContactNormalAcceleration(m_material, accel);
}

void IMaterialCallback::setContactNormalDirection(vector3df dir)
{
	NewtonMaterialSetContactNormalDirection(m_material, &dir.X);
}

void IMaterialCallback::setContactTangentAcceleration(f32 accel, int tangentIndex)
{
	NewtonMaterialSetContactTangentAcceleration(m_material, accel, tangentIndex);
}

void IMaterialCallback::contactRotateTangentDirections(vector3df alignVector)
{
	NewtonMaterialContactRotateTangentDirections(m_material, &alignVector.X);
}

/// The default callback when any two materials without a
//! user callback begin contact.
int IMaterialCallback::beginContact (const NewtonMaterial* material, const NewtonBody* body0, const NewtonBody* body1)
{
	IMaterialCallback* me;

	me = (IMaterialCallback*)NewtonMaterialGetMaterialPairUserData( material );

	me->m_material = (NewtonMaterial*)material;

	//save the bodies...
	me->m_body0 = (NewtonBody*)body0;
	me->m_body1 = (NewtonBody*)body1;

	return me->beginCallback();
}

/// The default callback when contact between any two materials 
//! without a user callback is to be processed.
int IMaterialCallback::processContact (const NewtonMaterial* material, const NewtonContact* contact)
{
	IMaterialCallback *me;

	me = (IMaterialCallback*)NewtonMaterialGetMaterialPairUserData( material );

	me->m_material = (NewtonMaterial*)material;
	me->m_contact = (NewtonContact*)contact;

	// call the user-defined callback function!
	return me->processCalback();
}

/// The default callback when any two materials without a
//! user callback end contact.
void IMaterialCallback::endContact (const NewtonMaterial* material)
{
	IMaterialCallback* me;

	me = (IMaterialCallback*)NewtonMaterialGetMaterialPairUserData( material );

	me->m_material = (NewtonMaterial*)material;

	me->endCallback();
}

