#include "CPhysicsBallSocket.h"

/// Break force needed to break the join.
//! This variable is declared static as it is called in
//! static newton callbacks.
vector3df CPhysicsBallSocket::m_breakForce;

/// Empty constructor for the joint.
CPhysicsBallSocket::CPhysicsBallSocket()
{

}

/// The destructor is also empty as the joint destruction
//! is handled by the IPhysicsJoint base class.
CPhysicsBallSocket::~CPhysicsBallSocket()
{

}

/// This function initializes the ball socket joint.
void CPhysicsBallSocket::init(NewtonWorld* world, SPhysicsBallSocketJoint* jnt)
{
	m_world = world;

	jnt->pivot *= IrrToNewton;
	jnt->pin *= IrrToNewton;

	m_breakForce = jnt->breakForce;

	m_joint = NewtonConstraintCreateBall(m_world,&jnt->pivot.X,jnt->child->getBody(),jnt->parent->getBody());
	NewtonBallSetConeLimits(m_joint, &jnt->pin.X, jnt->maxAngle * PI / 180.0f, jnt->maxTwistAngle * PI / 180.0f);

	NewtonBallSetUserCallback(m_joint, ballCallback);
}

/// Callback for the ball socket joint
//! This callback handles the joint breaking.
void CPhysicsBallSocket::ballCallback(const NewtonJoint* ball)
{
	if (m_breakForce == vector3df(0,0,0))
		return;

	vector3df force;
	NewtonBallGetJointForce(ball, &force.X);

	if ((force.X > m_breakForce.X) || (force.Y > m_breakForce.Y) || (force.Z > m_breakForce.Z))
		NewtonDestroyJoint(m_world, ball);
}

/// This function is used to change the limits of the ball socket.
void CPhysicsBallSocket::changeJointLimits(vector3df pin, f32 maxConeAngle, f32 maxTwistAngle)
{
	NewtonBallSetConeLimits(m_joint, &pin.X, maxConeAngle * PI / 180.0f, maxTwistAngle * PI / 180.0f);
}

/// This function is used to have a user joint callback.
void CPhysicsBallSocket::setUserCallback(NewtonBallCallBack callback)
{
	NewtonBallSetUserCallback(m_joint, callback);
}

/// This function is used to get the current agle of the joint.
vector3df CPhysicsBallSocket::getAngle()
{
	vector3df angle;
	NewtonBallGetJointAngle(m_joint, &angle.X);
	return angle;
}

/// This function is used to get the omega of the joint.
vector3df CPhysicsBallSocket::getOmega()
{
	vector3df omega;
	NewtonBallGetJointOmega(m_joint, &omega.X);
	return omega;
}

/// This function is used to get the force applied on the joint.
vector3df CPhysicsBallSocket::getForce()
{
	vector3df force;
	NewtonBallGetJointForce(m_joint,&force.X);
	return force;
}

/// This function returns a pointer to the newton joint object.
NewtonJoint* CPhysicsBallSocket::getJoint()
{
	return m_joint;
}