Custom "Rope" Joint - help needed

zuur

17-04-2008 02:47:22

Hi All,

So I'm trying to make a joint that I can use to string lots of cylinders together and make a rope from,.. I have some code below that largely works but has problems when bending, (I guess a joint that has problems bending is a problem joint..).

Actually, flexible polythene pipe is a lot more along the lines of the result I'm trying to achieve - like this stuff:


My requirements are:
* It should try and straighten itself if bent.
* It shouldn't "twist" (torque) between segments.
* It should maintain its length - I'm going to have about 50 segments and it'll be a problem if I push the tail segment at one end and the thing condenses a bit before the head gets the idea it needs to move forward.

So, following my list of demands, here's my first attempt at some custom joint code:
TubeJoint::TubeJoint( OgreNewt::Body* child, OgreNewt::Body* parent, Vector3 point, Vector3 pin,
Real bendiness, Real twistiness, Real stretchiness,
Degree minBend, Degree maxBend ) : OgreNewt::CustomJoint( 6, child, parent )
{
mBendiness = bendiness;
mTwistiness = twistiness;
mStretchiness = stretchiness;

mMinBend = minBend;
mMaxBend = maxBend;
mBend = Degree(0.0);

pinAndDirToLocal( point, pin, mLocalOrient0, mLocalPos0, mLocalOrient1, mLocalPos1 );
}

void TubeJoint::submitConstraint()
{
// find the global orientation of the joint relative to the 2 bodies.
Quaternion globalOrient0, globalOrient1;
Vector3 globalPos0, globalPos1;
Vector3 globalPos0b, globalPos1b;
localToGlobal( mLocalOrient0, mLocalPos0, globalOrient0, globalPos0, 0 );
localToGlobal( mLocalOrient1, mLocalPos1, globalOrient1, globalPos1, 1 );

//Connect the 2 points together on all three axis
addLinearRow( globalPos0, globalPos1, globalOrient0 * Vector3(Vector3::UNIT_X) ); setRowStiffness(1.0-mStretchiness);
addLinearRow( globalPos0, globalPos1, globalOrient0 * Vector3(Vector3::UNIT_Y) ); setRowStiffness(1.0-mStretchiness);
addLinearRow( globalPos0, globalPos1, globalOrient0 * Vector3(Vector3::UNIT_Z) ); setRowStiffness(1.0-mStretchiness);

//Bending horizontal constraint
globalPos0b = globalPos0 + (globalOrient0 * (Vector3::UNIT_X*10.0));
globalPos1b = globalPos1 + (globalOrient1 * (Vector3::UNIT_X*10.0));
addLinearRow( globalPos0b, globalPos1b, globalOrient0 * Vector3::UNIT_Z ); setRowStiffness(1.0-mBendiness);

//Bending vertical constraint (bent by mBend Degrees)
Vector3 a0 = globalOrient0 * Quaternion( mBend/2.0, Vector3::UNIT_X).yAxis();
Vector3 a1 = globalOrient1 * Quaternion(-mBend/2.0, Vector3::UNIT_X).yAxis();
globalPos0b = globalPos0 + a0;
globalPos1b = globalPos1 + a1;
addLinearRow( globalPos0b, globalPos1b, globalOrient0 * Vector3::UNIT_Z ); setRowStiffness(1.0-mBendiness);

//Twisting constraint
globalPos0b = globalPos0 + (globalOrient0 * (Vector3::UNIT_X*10.0));
globalPos1b = globalPos1 + (globalOrient1 * (Vector3::UNIT_X*10.0));
addLinearRow( globalPos0b, globalPos1b, globalOrient0 * Vector3::UNIT_Y ); setRowStiffness(1.0-mTwistiness);
}


You'll notice "mBend" being used there as well - I also need to be able to specify what angle (only in one axis) the tube tries to spring back to - so I can make pipes that are bent, but you can try and straighten them or bend them more, and they spring back to a bent state.

My main problem at the moment is that if you move the tube through a tunnel with a bend in it, then twist one end, the bend in the middle of the tube wants to do a big arc through space and move to somewhere else, where as the desired result is that the tube stays physically in the same place, but all twists uniformly the whole way through. Imagine that polythene pipe being inserted into a piece of drain pipe with a 90 degree bend in it: when you twist one end 10 degrees clockwise the other end will twist 10 degrees clockwise as well.

Any thoughts on my code, or any better ways to achieve this are hugely appreciated.

Thanks in advance,