# Nonuniform scaling - dilemma

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 08/05/2006 at 17:02, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   9.102
Platform:   Windows  ; Mac  ;  Mac OSX  ;
Language(s) :     C++  ;

---------
I've found probably the best solution available for handling shear in nonuniform scaling - SoftImage 'SI transformation' as it's called. It works by sort of rearranging the concatenation of transformation matrices - from classical (in C4D concatenation order) :

A(global) = B(global) x A(local)

to 'SI':

A(global) = AB(pos) x B(rot) x A(rot) x B(scale) x A(scale)

where AB(pos) = MatrixMove(A(pos) * B(global))

This works for the most part, but scaling gets wonky as the hierarchy gets deeper. And I can't seem to understand why this occurs, so here is an example of my code which sets the 'bone' rotation:

``````// IPPDial.UpdateRotation
//*---------------------------------------------------------------------------*
void IPPDial::UpdateRotation(BaseObject* obj, UCHAR sub, Real value)
//*---------------------------------------------------------------------------*
{
// Get the changed rotation component
BaseContainer*     bc =     obj->GetDataInstance();
Vector               rotV =     bc->GetVector(IPP_ROTATION);
if          (sub == CHAN_SUB_X)     rotV.x =     Rad(value);
else if (sub == CHAN_SUB_Y)     rotV.y =     Rad(value);
else if (sub == CHAN_SUB_Z)     rotV.z =     Rad(-value);
bc->SetVector(IPP_ROTATION, rotV);

// Create an axis-ordered rotation matrix with the updated rotation component
Matrix               rot;
UCHAR               order =          bc->GetBool(IPP_RORDER);
if          (order == ROTORDER_XYZ)     rot = bc->GetMatrix(IPP_ORIENTMATRIX) * MatrixRotZ(rotV.z) * MatrixRotY(rotV.y) * MatrixRotX(rotV.x);
else if (order == ROTORDER_XZY)     rot = bc->GetMatrix(IPP_ORIENTMATRIX) * MatrixRotY(rotV.y) * MatrixRotZ(rotV.z) * MatrixRotX(rotV.x);
else if (order == ROTORDER_YXZ)     rot = bc->GetMatrix(IPP_ORIENTMATRIX) * MatrixRotZ(rotV.z) * MatrixRotX(rotV.x) * MatrixRotY(rotV.y);
else if (order == ROTORDER_YZX)     rot = bc->GetMatrix(IPP_ORIENTMATRIX) * MatrixRotX(rotV.x) * MatrixRotZ(rotV.z) * MatrixRotY(rotV.y);
else if (order == ROTORDER_ZXY)     rot = bc->GetMatrix(IPP_ORIENTMATRIX) * MatrixRotY(rotV.y) * MatrixRotX(rotV.x) * MatrixRotZ(rotV.z);
else if (order == ROTORDER_ZYX)     rot = bc->GetMatrix(IPP_ORIENTMATRIX) * MatrixRotX(rotV.x) * MatrixRotY(rotV.y) * MatrixRotZ(rotV.z);
// SI transformation
Matrix               mg =          obj->GetUpMg();
mg =               MatrixMove(obj->GetPos()*mg) * HPBToMatrix(MatrixToHPB(mg)) * rot * MatrixScale(Vector(Len(mg.v1),Len(mg.v2),Len(mg.v3))) * MatrixScale(obj->GetScale());
obj->SetMg(mg, FALSE);
obj->Message(MSG_UPDATE);
}
``````

For position and scale, the same basic format applies for the SI transformation. If anyone can spot an error or has a better algorithmic approach, love to hear about it.

Thanks,