On 28/11/2013 at 11:53, xxxxxxxx wrote:
Cinema 4D Version: R15
Platform: Windows ; Mac ; Mac OSX ;
Language(s) : C++ ;
Matrix stuff is still a little confusing to me - even (or especially) after reading the COFFEE SDK piece on it.
I am trying to align two objects in C4D.
Where the root object (A) is stationary and a second object (B) is aligned to one of the sides taking into consideration rotation of both objects.
At the moment I can do this by making B a child of A and clear its position and rotation. Then it's easy to move it to the required position relative object A. After it's all lined up I move it out of the hierarchy and reinsert it at the top-level. Not very elegant since it messes around with the hierarchy.
Is there a way to do this via matrix manipulation where each object can stay at its place in the hierarchy?
I have tried various approaches while reading through the COFFEE chapter about matrices but not achieved much.
In a nutshell: Object B needs to be moved/rotated as if it was a child of A.
On 29/11/2013 at 06:05, xxxxxxxx wrote:
In hierarchies, each object has its own 'local matrix' which describes its position, scale, rotation with respect to its own coordinate system (typically, the object's origin). In relation to an object's parents in the hierarchy, each parent is related thus:
ObjectA: Local Matrix OA; ObjectB matrix relative to ObjectA = OA x OB, ObjectC matrix relative to ObjectA = OA x OB x OC
->ObjectB: Local Matrix OB; ObjectC matrix relative to ObjectB = OB x OC
--->ObjectC : Local matrix OC
If ObjectA is at the root of the hierarchy, its coordinate system is relative to the global coordinate system. The combination for ObjectB and ObjectC to put each into this Global space is called the Global matrix.
Therefore, if you want to move ObjectC out of the hierarchy to the root (global space), you must update its matrix to include the influences of its previous parents so as to maintain its orientation. This is called a coordinate system or spatial transform. In the case of Cinema 4D, you can get the global matrix prior to moving out of the hierarchy using ObjectC->GetMg() (where Mg is the 'Matrix global'). After you insert ObjectC at the root (into global space), you can then SetMg() with the matrix retrieved by GetMg() in order to maintain that orientation.
On 29/11/2013 at 06:59, xxxxxxxx wrote:
I think I didn't explain clearly.
Currently my object to be aligned (B) is a child of A.
I would like to align B without it being a child of A. So it never changes hierarchy.
On 29/11/2013 at 08:51, xxxxxxxx wrote:
Robert did explain what you asked for.
It's hard to learn this matrix stuff using just words. You really need some code to play with to understand it.
Create two objects in your scene and call them "master" and "slave". And Don't make the slave object a child of the master.
Then try out these two examples on them to see what it does.
//Get the two object's and their global matrix BaseObject *master = doc->SearchObject("master"); Matrix masterMtx = master->GetMg(); BaseObject *slave = doc->SearchObject("slave"); Matrix slaveMtx = slave->GetMg(); //This will make the slave use the master's matrix. So it will rotate with the master //But...it also positions the slave at the master's axis position too!! //Sometimes this is a desired thing..sometimes it's not slave->SetMg(masterMtx); slave->Message(MSG_UPDATE);
BaseObject *master = doc->SearchObject("master"); Matrix masterMtx = master->GetMg(); //Convert the master's matrix values to vector values Vector mRot = MatrixToHPB(masterMtx, ROTATIONORDER_DEFAULT); BaseObject *slave = doc->SearchObject("slave"); slave->SetAbsRot(mRot); //Apply the rotation to the slave object using the vectors from the masterMtx //slave->SetAbsRot(Vector(mRot.x, 0 , 0)); //<--You can also write it like this to only follow master's X rotations slave->Message(MSG_UPDATE);
This is the kind of stuff the constraint tags are doing in C4D behind the scenes.
On 02/12/2013 at 21:21, xxxxxxxx wrote:
After some more experimenting I got it figured out. The key for me was to use
matrixSlave = matrixSlave * matrixMaster;
On 03/12/2013 at 04:59, xxxxxxxx wrote:
In 'matrix speak' (not, 'take the blue pill'), that is 'matrix concatenation'. The * operator for the Matrix class is a nice convenience to the more complex process involved in concatenating two matrices. As you see, hierarchical (or parental) relationships of matrices allow for a matrix for an object (its own space) and application of other objects' spaces through their matrices via concatenation. This is how you can easily rotate 'Master' and it affects 'Slave'. The spatial changes to Master are passed along to Slave through matrix concatenation (just as you showed above). It is not a passive response - it is active by application to the Slave's global matrix.
On 03/12/2013 at 05:23, xxxxxxxx wrote:
I myself now use Matrices all the time, together with Quaternions. I must admit I am not always sure what is really happening, it just works. Especially Quaternions, opened up a new door.