Custom Joints and Ogre Bones....Help!

SFAOK

10-05-2007 22:14:30

So I've got this skeleton that I have imported from 3DS Max.



I am trying to convert the skeleton into an articulated one, using OgreNewt Custom Joints. Simple right?

I've spent a week+ trying to get this to work, I get the feeling I'm going round in circles! :(



Above you can see that I've sort of got it working. The joints hinge along the Z-axis (red), with X-axis being blue and Y-axis green. It works very well.

However, the system only behaves as it should when the imported skeleton is aligned like the first screenshot here:



If I rotate it, like the second image, the joints don't orientate properly! :oops:

Can anyone help me here (oh god please)? I've been staring at the ragdoll and prebuilt custom joint examples for hours, but I just can't see an obvious problem!


Here's how I create the bones + joints :

for (int x=1;x<numBones-1;x++)
{
//Get parent and child Positions
Vector3 curr = mLegBones[x]->_getDerivedPosition() * mLegScale;
Vector3 next = mLegBones[x+1]->_getDerivedPosition() * mLegScale;

//get vector difference between parent and child
Vector3 difference = next-curr;
Vector3 forward = difference.normalisedCopy();

//Get bone Orientation and re-align
Quaternion new_orient = mLegBones[x]->getWorldOrientation();

//length of bone
size = Vector3(difference.length(), 1, 1);

//mid point of bone
pos = curr + (forward * (difference.length() * 0.5));

// make the next box.
child[x] = makeSimpleBox(size, pos, new_orient);
child[x]->setCustomForceAndTorqueCallback<OgreNewtonApplication>(&OgreNewtonApplication::defaultCallback, this );


// make the joint right between the bodies...
Vector3 axis = new_orient.zAxis();
joint[x] = new myCustomJoint(mSceneMgr, child[x], parent, curr, axis);

joint[x]->setCollisionState(0);
// save the last body for the next loop!
parent = child[x];

}


The CustomJoint constructor :


myCustomJoint::myCustomJoint(OgreNewt::Body* child, OgreNewt::Body* parent, Ogre::Vector3 point, Ogre::Vector3 pin) : OgreNewt::CustomJoint( 6, child, parent)
{
pinAndDirToLocal(point, pin, mLocalOrient0, mLocalPos0, mLocalOrient1, mLocalPos1 );
}



And the contents of submitConstraint() :


// get globals.
Ogre::Vector3 globalPos0, globalPos1;
Ogre::Quaternion globalOrient0, globalOrient1;

localToGlobal( mLocalOrient0, mLocalPos0, globalOrient0, globalPos0, 0 );
localToGlobal( mLocalOrient1, mLocalPos1, globalOrient1, globalPos1, 1 );


// apply the constraints!
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_X );
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Y );
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Z );

// now find a point off 10 units away.
globalPos0 = globalPos0 + (globalOrient0 * (Ogre::Vector3::UNIT_X * 10.0f));
globalPos1 = globalPos1 + (globalOrient1 * (Ogre::Vector3::UNIT_X * 10.0f));

// apply the constraints!
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Y );
addLinearRow( globalPos0, globalPos1, globalOrient0 * Ogre::Vector3::UNIT_Z );

// Now for hinge rotations
Ogre::Vector3 bod0X = globalOrient0 * Ogre::Vector3(Ogre::Vector3::UNIT_X );

if (mAngle != 0.0f)
{
addAngularRow(Radian(mAngle), bod0X );
setRowStiffness( 1.0f );
}


:shock:

SFAOK

15-05-2007 21:09:37

Right I've narrowed down the problem.

If I use the standard OgreNewt Hinge, everything works perfectly.

joint[x] = OgreNewt::BasicJoints::Hinge(m_World, child[x], parent, curr, axis);

As far as I can tell from looking at the source code, and the Newton SDK, my Custom Hinge code is pretty standard.

I've gone over the code very carefully, but I simply can't find anything different between my custom hinge and ones that are reported to work.

Should my custom hinge behave exactly like a standard BasicJoint::Hinge? Walaber?

walaber

16-05-2007 04:52:13

hmmm... a quick glance at the code looks like your hinge should be OK.

maybe there is an error in my PinAndDirToLocal function...

SFAOK

16-05-2007 15:20:03

One thing I've noticed is that with a flat chain, everything initializes as expected, as long as the rotation of the chain on the Y-axis is between < 54 degrees and -125.

i.e


(the green box is the end of the chain).

That chain is rotated about 45 degrees.

This angle is also the one found in the grammSchmidt function (0.577 radians). I've had a look at the three functions (PinAndDirToLocal, LocalToGlobal and grammSchmidt) but I can't see any obvious problems.

I can get the flat chain to initialize properly at all angles if I negate the pin axis passed to the custom joint beyond the 54 degrees, but this obviously only works for a flat chain.