Differences:
* LimitBallSocket has friction behaviour when touching limit cone, this one slides freely at the cone
* LimitBallSocket has flipping problems at poles perpendicular to pin axis, this one has not, cone angle can be larger than 90 degrees
* otherwise pretty compatible, for different twist limit options see cpp
I'll do some more testing tomorrow...
Feel free to add it to the Joint Library.
CustomConeTwist.h
- Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/
#ifndef _CUSTOMCONETWIST_H_
#define _CUSTOMCONETWIST_H_
#include "CustomBallAndSocket.h"
class JOINTLIBRARY_API CustomConeTwist: public CustomBallAndSocket
{
public:
dAddRtti(NewtonCustomJoint);
CustomConeTwist(const dMatrix& pinsAndPivoFrame, NewtonBody* const child, NewtonBody* const parent = NULL);
virtual ~CustomConeTwist();
void SetConeAngle (dFloat angle);
void SetTwistAngle (dFloat minAngle, dFloat maxAngle);
protected:
virtual void SubmitConstraints (dFloat timestep, int threadIndex);
virtual void GetInfo (NewtonJointRecord* info) const;
dFloat m_minTwistAngle;
dFloat m_maxTwistAngle;
dFloat m_coneAngle;
};
#endif
CustomConeTwist.cpp
- Code: Select all
/* Copyright (c) <2009> <Newton Game Dynamics>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely
*/
// Cone twist joint with quaternion twist by Joe Joechler, 2012
//
//////////////////////////////////////////////////////////////////////
#include "CustomJointLibraryStdAfx.h"
#include "CustomConeTwist.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
dInitRtti(CustomConeTwist);
CustomConeTwist::CustomConeTwist(const dMatrix& pinAndPivotFrame, NewtonBody* const child, NewtonBody* const parent)
:CustomBallAndSocket(pinAndPivotFrame, child, parent)
{
dMatrix matrix0;
dMatrix matrix1;
SetTwistAngle (0.0f, 0.0f);
SetConeAngle (0.0f);
// calculate the twist handle vector
CalculateGlobalMatrix (m_localMatrix0, m_localMatrix1, matrix0, matrix1);
}
CustomConeTwist::~CustomConeTwist()
{
}
void CustomConeTwist::SetConeAngle (dFloat angle)
{
if (angle > 2.9) angle = 2.9;
if (angle < 0.05) angle = 0.05;
m_coneAngle = angle;
}
void CustomConeTwist::SetTwistAngle (dFloat minAngle, dFloat maxAngle)
{
m_minTwistAngle = minAngle;
m_maxTwistAngle = maxAngle;
}
void CustomConeTwist::GetInfo (NewtonJointRecord* info) const
{
CustomBallAndSocket::GetInfo (info);
strcpy (info->m_descriptionType, "limitconetwist");
}
void CustomConeTwist::SubmitConstraints (dFloat timestep, int threadIndex)
{
dMatrix matrix0;
dMatrix matrix1;
// calculate the position of the pivot point and the Jacobian direction vectors, in global space.
CalculateGlobalMatrix (m_localMatrix0, m_localMatrix1, matrix0, matrix1);
const dVector& p0 = matrix0.m_posit;
const dVector& p1 = matrix1.m_posit;
// Restrict the movement on the pivot point along all tree orthonormal direction
NewtonUserJointAddLinearRow (m_joint, &p0[0], &p1[0], &matrix0.m_front[0]);
NewtonUserJointAddLinearRow (m_joint, &p0[0], &p1[0], &matrix0.m_up[0]);
NewtonUserJointAddLinearRow (m_joint, &p0[0], &p1[0], &matrix0.m_right[0]);
const dVector& coneDir0 = matrix0.m_front;
const dVector& coneDir1 = matrix1.m_front;
float dot = coneDir0 % coneDir1;
if (dot < -0.999) return; // should never happen
// do the twist
if (m_maxTwistAngle >= m_minTwistAngle) // twist restricted?
{
dQuaternion quat0(matrix0), quat1(matrix1);
// factor rotation about x axis: qt = q0.Inversed() * q1; halfTwistAngle = atan (qt[0] / qt[3]);
float *q0 = (float*)&quat0;
float *q1 = (float*)&quat1;
float twistAngle = 2.0 * atan (
( ( ( (q0[0] * q1[1]) + (-q0[1] * q1[0]) ) + (-q0[2] * q1[3]) ) - (-q0[3] * q1[2]) ) /
( ( ( (q0[0] * q1[0]) - (-q0[1] * q1[1]) ) - (-q0[2] * q1[2]) ) - (-q0[3] * q1[3]) ) );
//dVector twistAxis = coneDir0;
dVector twistAxis = coneDir0 + coneDir1; // @ Julio: using any interpolant works here - average seemed best after some tests
twistAxis.Scale (1.0 / sqrt (twistAxis % twistAxis));
if (m_maxTwistAngle == m_minTwistAngle) // no freedom for any twist
{
NewtonUserJointAddAngularRow (m_joint, twistAngle - m_maxTwistAngle, (float*)&twistAxis);
}
else if (twistAngle > m_maxTwistAngle)
{
NewtonUserJointAddAngularRow (m_joint, twistAngle - m_maxTwistAngle, (float*)&twistAxis);
NewtonUserJointSetRowMinimumFriction (m_joint, 0.0f);
}
else if (twistAngle < m_minTwistAngle)
{
NewtonUserJointAddAngularRow (m_joint, twistAngle - m_minTwistAngle, (float*)&twistAxis);
NewtonUserJointSetRowMaximumFriction (m_joint, 0.0f);
}
}
// do the swing
float angle = acos (dot) - m_coneAngle;
if (angle > 0)
{
dVector swingAxis = (coneDir0 * coneDir1);
swingAxis.Scale (1.0 / sqrt (swingAxis % swingAxis));
NewtonUserJointAddAngularRow (m_joint, angle, (float*)&swingAxis);
NewtonUserJointSetRowMinimumFriction (m_joint, 0.0);
}
}
EDIT: Changed max cone angle from 1.5 to 2.9 radians