Hi all,
I am looking for some source of a simple ragdoll sandbox (ie. a ragdoll and a floor) with which I can have a play with the code. Any ideas?
Moderators: Sascha Willems, walaber
void AddPointToPointConstraint (sMat4 &matrix0, sMat4 &matrix1) // simple point to point constraint
{
NewtonUserJointAddLinearRow (joint, (float*)&matrix0[3], (float*)&matrix1[3], (float*)&matrix0[0]);
NewtonUserJointAddLinearRow (joint, (float*)&matrix0[3], (float*)&matrix1[3], (float*)&matrix0[1]);
NewtonUserJointAddLinearRow (joint, (float*)&matrix0[3], (float*)&matrix1[3], (float*)&matrix0[2]);
}
void SubmitHingeConstraints (float timestep, int threadIndex) // newton calls this as callback
{
sMat4 matrix0, matrix1; // construct joint matrices in global space
BodyGetMatrix ((Body*)body0, *((sMat4*)&matrix0)); matrix0 *= localMatrix0;
BodyGetMatrix ((Body*)body1, *((sMat4*)&matrix1)); matrix1 *= localMatrix1;
sQuat q0, q1; // same as matrix0 orientation, but in quat form...
BodyGetRotation (body0, q0); q0 *= localRot0; // note: BodyGetRotation does (w,x,y,z)->(x,y,z,w) conversation
BodyGetRotation (body1, q1); q1 *= localRot1;
AddPointToPointConstraint (matrix0, matrix1);
const sVec3& dir0 = matrix0[0]; // direction vectors along upper and lower leg
const sVec3& dir1 = matrix1[0];
float dot = dir0.Dot (dir1); if (dot < -0.999) return; // todo: lazy hack for now, remove!
// do the twist (avoid lower leg turning around it's length)
{
// very nice quaternion trick to get rotation about x axis between 2 orientations
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]) ) );
sVec3 twistAxis = sVec3(dir0+dir1).Unit(); // could use dir0 OR dir1 too, but average seems most stable - unsure about that
NewtonUserJointAddAngularRow (joint, twistAngle, (float*)&twistAxis); // newton will try to correct the twistAngle error for us
}
// additional hinge constraints...
// plane constraint...
sVec3 d = matrix1.Unrotate (dir0);
float planeAngle = asin (d[2]);
d[2] = 0; d.Normalize();
sVec3 swingAxis (matrix1.Rotate(sVec3 (-d[1], d[0], 0)));
NewtonUserJointAddAngularRow (joint, planeAngle, (float*)&swingAxis);
// hinge limits...
float minHingeAngle = ...
float maxHingeAngle = ...
float limitAngle = atan2 (d[1], d[0]);
if (limitAngle < minHingeAngle)
{
NewtonUserJointAddAngularRow (joint, minHingeAngle - limitAngle, (float*)&matrix1[2]);
NewtonUserJointSetRowMinimumFriction (joint, 0.0f);
}
else if (limitAngle > maxHingeAngle)
{
NewtonUserJointAddAngularRow (joint, maxHingeAngle - limitAngle, (float*)&matrix1[2]);
NewtonUserJointSetRowMaximumFriction (joint, 0.0f);
}
// powering
{
float m_maxAngularFriction = 2000.0; // max muscle strength
sVec3 omega0, omega1;
BodyGetAngVel(body0, omega0); // == NewtonBodyGetOmega
BodyGetAngVel(body1, omega1);
sVec3 &axis = matrix1[2];
float relAccel;
float motorAngle = ...target knee angle
relAccel = (motorAngle - limitAngle);
relAccel -= sVec3(omega0 - omega1).Dot(axis) * ...some value (0...1) like 0.5, to take current velocity into account
relAccel *= ...some value to drive speed... / timestep;
NewtonUserJointAddAngularRow (joint, 0.0f, &axis[0]); // now we don't want to fix an error, so use 0.0
NewtonUserJointSetRowAcceleration (joint, relAccel); // instead, provide acceleration
NewtonUserJointSetRowMinimumFriction (joint, -m_maxAngularFriction);
NewtonUserJointSetRowMaximumFriction (joint, m_maxAngularFriction);
}
}
Users browsing this forum: No registered users and 1 guest