mcjChainChainChain

An experimental script

1 - load a chain figure like this one https://sites.google.com/site/mcasualsdazscripts2/mcjchain

2 - scale it ( The Root Node not one of the bones ) down until it is the desired length

3 - rotate it so it points down

4 - run the script

For each frame of your current timeline playrange

the script will rotate chain segments above the floor level so they point straight down

endpoints of the segments that fall below floor level will be brought to floor level

by ZRotating their bones

note that the floor level is hard coded to be Y = 19.33215 + 2;

if you want to change this you have to open the script in a text editor or in Daz Studio's Scripting IDE panel and modify the line that reads

//altitude of the floor

var yFloor = 19.33215 + 2; //2cm offset

The code

TEXT BOX

// DAZ Studio version 4.9.0.63 filetype DAZ Script

//selected node must be the root of the chain figure

var node = Scene.getPrimarySelection();

var bones;

//"this chain is built along the -Z axis"

var myAxis = DzVec3( 0, 0, -1 );

//altitude of the floor

var yFloor = 19.33215 + 2; //2cm offset

// 90 in radians

var degrees90 = Math.PI / 2;

if( initialize( node ) ) //lay the groundwork

{

var tr = Scene.getPlayRange();

var tick = Scene.getTimeStep();

var frStart = Math.round( tr.start / tick );

var frEnd = Math.round( tr.end / tick );

for( i = frStart; i <= frEnd; i++ )

{

Scene.setFrame( i );

doit( node, yFloor ); //process

}

}

//================================================================================

function doit()

{

var n = bones.length;

// now for each bone-joint, starting from the top

// if a node is below floor level, bend the parent joint

// up to an angle of 90 degrees, just the correct amount

// to get that node above floor

for( var i = 1; i < n; i++ )

{

var position = bones[i].getWSPos();

var y = position.y;

if( y > yFloor )

{

//we must make sure the parent bone is pointing straight-down

var vWanted = DzVec3( 0, -1, 0 );

var parentBone = bones[i-1];

var r = parentBone.getWSRot();

vActual = r.getZAxis();

vActual.x *= -1;

vActual.y *= -1;

vActual.z *= -1;

rerot = vWanted.getRotationTo( vActual );

r = r.multiply( rerot );

parentBone.setWSRot( r );

//re-measure position

position = bones[i].getWSPos();

y = position.y;

}

if( y < yFloor )

{

var parentBone = bones[i-1];

var posParentBone = parentBone.getWSPos();

var boneLength = position.subtract( posParentBone ).length();

var dy = posParentBone.y - yFloor

var angle = Math.asin( dy / boneLength );

var dx = Math.cos( angle );

var dy = Math.sin( angle );

var vWanted = DzVec3( dx, -dy, 0 );

var r = parentBone.getWSRot();

vActual = r.getZAxis();

vActual.x *= -1;

vActual.y *= -1;

vActual.z *= -1;

rerot = vWanted.getRotationTo( vActual );

r = r.multiply( rerot );

parentBone.setWSRot( r );

}

}

}

//================================================================================

function initialize( node )

{

if( !node )

{

return( false );

}

if( node.inherits( "DzBone" ) )

{

node = node.getSkeleton();

}

if( !node.inherits( "DzSkeleton" ) )

{

return( false );

}

bones = node.getAllBones();

var n = bones.length;

var endPointNode = Scene.findNodeByLabel( "mcjEndPointNode" );

if( !endPointNode ) //

{

endPointNode = new DzNode();

Scene.addNode( endPointNode );

endPointNode.setName( "mcjEndPointNode" );

endPointNode.setLabel( "mcjEndPointNode" );

}

//parent it to the last bone-joint

var lastBone = bones[n-1];

lastBone.addNodeChild( endPointNode );

//place it ad the extremity

endPointNode.setLocalPos( lastBone.getEndPoint() );

//add it to the list of bones

bones.push( endPointNode );

return( true );

}

this script is attached below

don't forget to click on the down-arrow, to download it

clicking anywhere else will lead to confusion ! ( google's fault )