Emulating Reset Transform and Reset Scale

The 3ds Max user interface provides users with an Adjust Transform rollout which can be used to reset transform or reset scale.

In order to emulate the reset transform and reset scale behavior you can use the following code snippet:

Interface *ip = theResetScale.ip;
TimeValue t = ip->GetTime();
Control *tmControl = node->GetTMController();
BOOL lookAt = tmControl->GetRollController() ? TRUE : FALSE;
Matrix3 ntm = node->GetNodeTM(t);
Matrix3 ptm = node->GetParentTM(t);
Matrix3 rtm = ntm * Inverse(ptm);
Matrix3 otm(1);
Quat rot;
 
// Grab the transform
Point3 trans = rtm.GetTrans();
 
// Clear the transform on the matrix
rtm.NoTrans();
 
// We're only doing scale - save out the
// rotation so we can put it back
AffineParts parts;
decomp_affine(rtm, &parts);
rot = parts.q;
 
// Build the offset transform matrix
otm.PreTranslate(node->GetObjOffsetPos());
if (node->GetObjOffsetRot()!=IdentQuat()) {
    PreRotateMatrix(otm,node->GetObjOffsetRot());
}
Point3 tS(1,1,1);
 
if ( node->GetObjOffsetScale().s != tS ) {
    ApplyScaling(otm,node->GetObjOffsetScale());
}
 
// Apply the relative transform matrix to the offset
otm = otm * rtm;
decomp_affine(otm, &parts);
node->SetObjOffsetPos( parts.t);
node->SetObjOffsetScale( ScaleValue(parts.k*parts.f,parts.u));
 
// Now set the transform controller with a matrix
// that has no rotation or scale
rtm.IdentityMatrix();
rtm.SetTrans(trans);
if (!lookAt) {
    PreRotateMatrix(rtm,rot);
}
 
// But first, want to keep children stationary.
Matrix3 ttm = rtm*ptm;
for (int i=0; iNumberOfChildren(); i++)  {
    Control *tmc  = node->GetChildNode(i)->GetTMController();
    Matrix3 oldtm = node->GetChildNode(i)->GetNodeTM(t);
     SetXFormPacket pk(oldtm,ttm);
    tmc->SetValue(t,&pk);
}
SetXFormPacket pckt(rtm);
tmControl->SetValue(t,&pckt);

See Also