# Getting an Object to Follow Another Regardless of Hierarchy

• @m_magalhaes Manuel, I am SO grateful for your help, thank you. I've spent a lot of time so far and was feeling very frustrated. Thank you!

I have a couple of questions about your code if I may:

1. As mentioned in the original post, I'm starting with a single, local space dimension value. I try and change `tmg`'s position X value then change it to global space, as in the example below, (`posX`). This code works when the objects are siblings or children of other objects, but when the Object is parented to the Target, the Object rotates and scales (even with the Option set to 2). Can you please teach me how to change a single value like this that will work anywhere in the hierarchy in your code?
``````        posX = curve.GetValue(newTime, fps) # 'curve' is the CCurve for the relative Pos.x CTrack
tmg = target.GetMg()
vec = c4d.Vector(posX, tmg.off.y, tmg.off.z)
parentMat = target.GetUpMg() #get Parent's matrix
tmg.off = vec * parentMat #convert position vector from Curve to Global Matrix
``````

1. `# option 1 only rotation`
This didn't only affect rotation when I set the option to 1. The position & scale were also affected. The code is adding the offset with `tmg.off += offset[1]`, but would adding the target's rotation involve `MatrixToHPB`?

Thanks so much, again!

• hi,

I've modified my code a bit, just to remove that bug and clean it a bit. I've also added the posibility to "freeze" the object except the X axis even if B is a child of A (and you are moving A)

The scale is store in the vectors of the matrix itsellf (v1, v2, v3) the length of the vector is the scale in that particular axis.

Have a look at matrix fundamentals

so if you want to set the scale back to 1, you have to just set all the vector lenght to 1. In other words, you have to normalized those vector, or in a matrix you just normalize the matrix itself.

If you want to retrieve or keep the scale, you can retrieve the scale of on object's matrix with GetScale and apply with Scale (same link)

Don't over think how matrix works, just focus on how you can use them.

.off is the displacement information
.v1 is the x axis information about the rotation (where the vector is pointing to) and the scale (how long the vector is, it's magnitude)
.v2 is the y axis
.v3 is the z axis.

the identity matrix (no displacement, no rotation, scale 1) can be created with `c4d.Matrix()`
With that if you only want to add the displacement information just add your information in .off
etc etc.

Just be careful that the axis v1, v2, v3 must be orthogonal

Cheers,
Manuel

• @m_magalhaes Hi Manuel, thank you, again, for your help with the code and further explanations.

I've been reading Matrix Fundamentals a lot during this process and still have a lot to learn.

I tried out the modified code and it works for position & rotation, but discovered some unexpected shearing behavior when animating the Target's scale with Option 4 when the objects are parent/child.

Project File

Am I doing something wrong or is this a bug?

Thank you.

• hi,

i finally asked the dev if they got a better idea than myself.

It's reproducible with our constrain tag, that's the combinaison of rotation and scale of the parent that apply to the child.

I'm afraid it's a bit of a limitation in our system and this particular case.

Let's see.

Cheers,
Manuel

• @m_magalhaes Hi Manuel, it feels like your idea is very close. Thank you for taking the extra steps.

• Sorry for barging in, but as the same Q was asked on two more forums, I stumbled over it.

I couldn't find the actual error in the code, but after reducing the whole thing to the crucial lines, I am fairly convinced that it is a bug. I created a completely new scene (R21) to exclude any strangenesses from the original file, and it's still easily reproductible:

The script here is very simple:

``````import c4d

def main():
obj = op.GetObject()
parent = obj.GetUp()
parentMat = parent.GetMg()
obj.SetMl(~parentMat)
``````

It does nothing but assign the child the inverted parent matrix as local matrix. Logically, this should make the child stay constant and in place, regardless of whatever changes you perform to the parent.

It works very well as long as you only rotate or translate the parent; as soon as you add some scaling, you get the result above. The child's matrix starts shearing, and the coordinate system is no longer orthogonal (which isn't even supported by C4D natively).

I can only conclude that the matrix inversion has a bug and is not handling scaled matrices correctly (as strange as it sounds - such a basic error should show up in every second scene...).

• I have been following this topic in all three (!) forums since beginning and I'm really looking forward to the outcome of this topic.

I'd call myself quite a Matrix mutant, so just ignore me, if my question is completely off topic or bogus in this context. My expectation would have been the same as @Cairyn's.
Yet, there has always been this last sentence on the Matrix fundamentals page, which reads pretty suspicious to me.

`[Local Matrix] = MatrixMove(op.GetFrozenPos()) * HPBToMatrix(op.GetFrozenRot()) * MatrixMove(op.GetRelPos()) * HPBToMatrix(op.GetRelRot()) * MatrixScale(op.GetFrozenScale) * MatrixScale(op.GetRelScale())`

Please note that the both scales are applied at the very beginning, so the local matrix is not the same as [Frozen Matrix] * [Relative Matrix]. This is necessary in order to guarantee that your local matrix always stays a rectangular system; distorted sy

I'm not questioning the correctness of this sentence. I'm just wondering if it may be related to this issue? And if one would maybe need to separate the scale from the equation and calculate it in correct order?

• @m_magalhaes Hi Manuel, I just wanted to check and see if the developers had any update on this issue? Thank you!

• hi,

sorry for the late reply, but other task and vacations came in : /
I don't have any solution for that particular case. (that's also why the same happen with our tag)

Cheers,
Manuel

• @m_magalhaes That's okay. Thank you for letting me know!