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 )