JoeJ wrote:I think you can replicate this way:
Change your grab forde so it acts at body center of mass, not at pick hitpoint.
That's the real difference between our pick stuff!
I hope this helps...
Yes this reproduce it very eassy, thanks
Moderators: Sascha Willems, walaber
JoeJ wrote:I think you can replicate this way:
Change your grab forde so it acts at body center of mass, not at pick hitpoint.
That's the real difference between our pick stuff!
I hope this helps...
dgInt32 dgCollisionCapsule::CalculatePlaneIntersection(const dgVector& normal, const dgVector& origin, dgVector* const contactsOut) const
{
dgInt32 count = 0;
if (dgAbsf(normal.m_x) > dgFloat32(0.999f))
{
dgFloat32 x =(normal.m_x > dgFloat32(0.0f)) ? dgFloat32(1.0f) : dgFloat32(-1.0f);
contactsOut[count] = dgVector(x, dgFloat32(0.0f), dgFloat32(0.0f), dgFloat32(0.0f));
count = 1;
}
else
{
dgFloat32 magInv = dgRsqrt (normal.m_y * normal.m_y + normal.m_z * normal.m_z);
dgFloat32 cosAng = normal.m_y * magInv;
dgFloat32 sinAng = normal.m_z * magInv;
_ASSERTE(dgAbsf (normal.m_z * cosAng - normal.m_y * sinAng) < dgFloat32 (1.0e-4f));
dgVector normal1(normal.m_x, normal.m_y * cosAng + normal.m_z * sinAng, dgFloat32(0.0f), dgFloat32(0.0f));
dgVector origin1(origin.m_x, origin.m_y * cosAng + origin.m_z * sinAng, origin.m_z * cosAng - origin.m_y * sinAng, dgFloat32(0.0f));
dgPlane plane(normal1, -(normal1 % origin1));
dgVector maxDir((normal1.m_x > dgFloat32(0.0f)) ? m_silhuette[3].m_x : -m_silhuette[3].m_x, (normal1.m_y > dgFloat32(0.0f)) ? m_silhuette[3].m_y : -m_silhuette[3].m_y, dgFloat32(0.0f), dgFloat32(0.0f));
dgFloat32 test0 = plane.Evalue(maxDir);
dgFloat32 test1 = plane.Evalue(maxDir.Scale(dgFloat32(-1.0f)));
if ((test0 * test1) > dgFloat32(0.0f))
{
test0 = plane.m_w + plane.m_x * m_height[0];
if (dgAbsf(test0) < m_radius)
{
contactsOut[count] = normal1.Scale(-test0);
contactsOut[count].m_x += m_height[0];
count = 1;
}
else
{
test0 = plane.m_w - plane.m_x * m_height[0];
if (dgAbsf(test0) < m_radius)
{
contactsOut[count] = normal1.Scale(-test0);
contactsOut[count].m_x -= m_height[0];
count = 1;
}
}
}
else
{
dgVector dp(m_silhuette[1] - m_silhuette[0]);
dgFloat32 den = normal1 % dp;
if (dgAbsf(den) > dgFloat32(0.0f))
{
test0 = -plane.Evalue(m_silhuette[0]) / den;
if ((test0 <= dgFloat32(1.0)) && (test0 >= dgFloat32(0.0f)))
{
contactsOut[count] = m_silhuette[0] + dp.Scale(test0);
count++;
}
}
if (count < 2)
{
test0 = plane.m_w - plane.m_x * m_height[0];
if (dgAbsf(test0) < m_radius)
{
dgFloat32 r = -m_height[0];
dgFloat32 d = plane.m_w + r * plane.m_x;
dgFloat32 a = plane.m_x * plane.m_x + plane.m_y * plane.m_y;
dgFloat32 b = dgFloat32(2.0f) * plane.m_x * d;
dgFloat32 c = d * d - m_radius * m_radius * plane.m_y * plane.m_y;
dgFloat32 desc = b * b - dgFloat32(4.0f) * a * c;
if (desc > dgFloat32(0.0f))
{
_ASSERTE(dgAbsf (a) > dgFloat32 (0.0f));
desc = dgSqrt (desc);
a = -dgFloat32(0.5f) * b / a;
dgFloat32 x0 = a + desc;
dgFloat32 x1 = a - desc;
if (x0 > dgFloat32(0.0f))
{
x0 = x1;
}
if (x0 < 0.0f)
{
_ASSERTE(x0 <= dgFloat32 (0.0f));
_ASSERTE(dgAbsf (plane.m_y) > dgFloat32 (0.0f));
dgFloat32 y = -(plane.m_x * x0 + d) / plane.m_y;
contactsOut[count] = dgVector(x0 + r, y, dgFloat32(0.0f),
dgFloat32(0.0f));
count++;
}
}
}
}
if (count < 2)
{
dgVector dp(m_silhuette[3] - m_silhuette[2]);
den = normal1 % dp;
if (dgAbsf(den) > dgFloat32(0.0f))
{
test0 = -plane.Evalue(m_silhuette[2]) / den;
if ((test0 <= dgFloat32(1.0)) && (test0 >= dgFloat32(0.0f)))
{
contactsOut[count] = m_silhuette[2] + dp.Scale(test0);
count++;
}
}
}
if (count < 2)
{
test0 = plane.m_w + plane.m_x * m_height[0];
if (dgAbsf(test0) < m_radius)
{
dgFloat32 r = m_height[0];
dgFloat32 d = plane.m_w + r * plane.m_x;
dgFloat32 a = plane.m_x * plane.m_x + plane.m_y * plane.m_y;
dgFloat32 b = dgFloat32(2.0f) * plane.m_x * d;
dgFloat32 c = d * d - m_radius * m_radius * plane.m_y * plane.m_y;
dgFloat32 desc = b * b - dgFloat32(4.0f) * a * c;
if (desc > dgFloat32(0.0f))
{
_ASSERTE(dgAbsf (a) > dgFloat32 (0.0f));
desc = dgSqrt (desc);
a = -dgFloat32(0.5f) * b / a;
dgFloat32 x0 = a + desc;
dgFloat32 x1 = a - desc;
if (x0 < dgFloat32(0.0f))
{
x0 = x1;
}
if (x0 > 0.0f)
{
_ASSERTE(x0 >= dgFloat32 (0.0f));
_ASSERTE(dgAbsf (plane.m_y) > dgFloat32 (0.0f));
dgFloat32 y = -(plane.m_x * x0 + d) / plane.m_y;
contactsOut[count] = dgVector(x0 + r, y, dgFloat32(0.0f),
dgFloat32(0.0f));
count++;
}
}
}
}
}
for (dgInt32 i = 0; i < count; i++)
{
dgFloat32 y = contactsOut[i].m_y;
dgFloat32 z = contactsOut[i].m_z;
contactsOut[i].m_y = y * cosAng - z * sinAng;
contactsOut[i].m_z = z * cosAng + y * sinAng;
}
}
return count;
}
dgInt32 dgCollisionCapsule::CalculatePlaneIntersection (const dgVector& normal, const dgVector& origin, dgVector* const contactsOut) const
{
dgInt32 count = 0;
if (dgAbsf (normal.m_x) > dgFloat32 (0.25f)) {
contactsOut[0] = SupportVertex (normal);
count = 1;
} else {
dgVector p0 (m_height, dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
dgVector dir0 (p0 - origin);
dgFloat32 dist0 = dir0 % normal;
if ((dist0 * dist0) < (m_radius * m_radius)) {
contactsOut[count] = p0 - normal.Scale (dist0);
count ++;
}
dgVector p1 (-m_height, dgFloat32 (0.0f), dgFloat32 (0.0f), dgFloat32 (0.0f));
dgVector dir1 (p1 - origin);
dgFloat32 dist1 = dir1 % normal;
if ((dist1 * dist1) < (m_radius * m_radius)) {
contactsOut[count] = p1 - normal.Scale (dist1);
count ++;
}
}
return count;
}
JoeJ wrote:With the joint it is still easy to drag anything into static box or sphere.
But i would not call that a bug, i saw it is there since i've implemented the joint.
It's a reason why i don't recommend joints for game interaction and prefer force.
Lowering the joint friction helps, but i loose the joint's advantage too.
At a value, where the collisions keep pretty correct, i can not lift up the ragdoll in a much more responsive way than with the force method alone.
sQuat q0, q1;
BodyGetRotation (body0, q0); q0 *= localRot0; // same as 'cs0' in text above, but in quat form
BodyGetRotation (body1, q1); q1 *= localRot1;
// factor rotation about x axis: sQuat qt = q0.Inversed() * q1; float halfTwistAngle = atan (qt[0] / qt[3]);
float twistAngle = 2.0 * atan (
( ( ( (q0[3] * q1[0]) + (-q0[0] * q1[3]) ) + (-q0[1] * q1[2]) ) - (-q0[2] * q1[1]) ) /
( ( ( (q0[3] * q1[3]) - (-q0[0] * q1[0]) ) - (-q0[1] * q1[1]) ) - (-q0[2] * q1[2]) ) );
// WARNING: i use quaternion form (x,y,z, w) - Julio uses (w, x,y,z) - BodyGetRotation does the conversation for me
sVec3 twistAxis = sVec3(dir0+dir1).Unit(); // use average axis
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]);
dVector localPin(0,1,0);
dVector rotationalPin(0,1,0);
dVector rotationalPinLeft(0,0,1);
dVector rotationalPinFront(1,0,0);
dVector pin0 = matrix0.RotateVector(localPin);
dVector pin1 = matrix1.RotateVector(localPin);
dFloat angle = angleBetweenVectors(pin0, pin1);
if(angle >= m_coneAngle)
{
dVector swing_pin = normalize(pin0 * pin1);
dFloat fixangle = angle - m_coneAngle;
NewtonUserJointAddAngularRow (m_joint, fixangle, &swing_pin[0]);
NewtonUserJointSetRowMinimumFriction (m_joint, 0.0); // important: allow the arm to move inside the cone
}
dVector gRotPin0 = matrix0.RotateVector(rotationalPin);
dVector gRotPin1 = matrix1.RotateVector(rotationalPin);
dVector gRotPinLeft1 = matrix0.RotateVector(rotationalPinLeft);
dQuaternion q0(matrix0);
dQuaternion q1(matrix1);
dQuaternion q01 = q0.Inverse() * q1;
dVector axis = gRotPin0;//(gRotPin0 + gRotPin1); axis = axis.Scale(1/dSqrt(axis % axis));
float twistAngle = 2.0 * atan(q01.m_q1 / q01.m_q0);
//dVector vv0 = p0;
//dVector vv1 = ???;
//dFloat twistAngle = signedAngleBetweenVectors(vv0,vv1,rotationalPin);
//dFloat twistAngle = atan2(p_i.m_z , p_i.m_x);
//std::cout << twistAngle*(180.0 / 3.14) << " " << rot << std::endl;
if (m_minTwistAngle == m_maxTwistAngle) // this joint does NOT allow twisting
{
NewtonUserJointAddAngularRow (m_joint, twistAngle - m_maxTwistAngle, (float*)&axis);
}
else if (twistAngle > m_maxTwistAngle)
{
NewtonUserJointAddAngularRow (m_joint, twistAngle - m_maxTwistAngle, (float*)&axis);
NewtonUserJointSetRowMinimumFriction (m_joint, 0.0f);
}
else if (twistAngle < m_minTwistAngle)
{
NewtonUserJointAddAngularRow (m_joint, twistAngle - m_minTwistAngle, (float*)&axis);
NewtonUserJointSetRowMaximumFriction (m_joint, 0.0f);
}
Users browsing this forum: No registered users and 3 guests