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,