interpolating between two rotations / quaternions - in DS - source code

mCasualmCasual Posts: 4,604

rotations in Daz studios are expressed as quaternions,

obtained and set using functions like node.getWSRot and node.SetWSRot

or as three euler angles, which are driven by the parameter tab's XRotate, YRotate and ZRotate controllers

a quaternion can be seen as a hinge-vector and a rotation angle

For figure joints, interpolating between two rotations using the three controllers can lead to problems

but interpolating between two rotations using quaternions and the SLERP method leads to good results

here's Daz scripting code for SLERPing between a pose at frame 218 and a pose at frame 228


var tick = 1 * Scene.getTimeStep();
var node = Scene.getPrimarySelection();
var sin = Math.sin;

var frchk = [218, 228]
var fra = frchk[0];
var frb = frchk[1];
var qa = new DzQuat( node.getWSRot( fra * tick ) );
var qb = new DzQuat( node.getWSRot( frb * tick ) );

var d = frb - fra;
for( var i = 1; i < d; i++ )
{
 var qc = slerp( qa, qb, i / d );
 var t = ( fra + i ) * tick;
 node.setWSRot( t, qc )
}

function slerp( q1, q2, t ) 
{
 var ddd = quatDot( q1, q2 ); 
 //dot = cos( angle ) 
 //if (dot < 0) ang > 90 deg, so we invert one of the two
 if( ddd < 0 )
 {
  ddd = -ddd;
  q3 = quatScale( q2, -1 );
 }
 else
 {
  q3 = q2;
 } 
 var s = 1 - t;
 var q1b = quatScale( q1, s );
 var q2b = quatScale( q3, t );

 if( ddd < 0.95 )
 {
  var angle = Math.acos( ddd );
  var sa = sin( angle )
  q1b = quatScale( q1, sin( angle * s ) / sa );
  q2b = quatScale( q3, sin( angle * t ) / sa );
 }
 else
 {
  q1b = quatScale( q1, s );
  q2b = quatScale( q3, t );
 }

 return( quatAdd( q1b, q2b ) ); 
}

function quatScale( q, scale)
{ 
 var nq = new DzQuat();
 nq.x = q.x * scale; 
 nq.y = q.y * scale; 
 nq.z = q.z * scale; 
 nq.w = q.w * scale; 
 return( nq );
}

function quatAdd( q, r )
{ 
 var nq = new DzQuat();
 nq.x = q.x + r.x; 
 nq.y = q.y + r.y; 
 nq.z = q.z + r.z; 
 nq.w = q.w + r.w; 
 return( nq );
}

function quatDot( q, r )
{
 var qq = new DzVec3( q.x, q.y, q.z );
 var rr = new DzVec3( r.x, r.y, r.z );
 return( qq.dot( rr ) ); 
}
Post edited by mCasual on
Sign In or Register to comment.