Object Target Expression in Python

Hi Friends,
I try to build the Object Target Expression in Python.
So far I have this and it works but with a little issue.
I have a flipping problem and I don't know how to build the up-vector in, so that it works perfectly.

import c4d
cam = op.GetObject()
target = op[c4d.ID_USERDATA,1]
def main():    
    cObj = cam.GetMg().off  
    tObj = target.GetMg().off
    upV =  c4d.Vector(0, 1, 0)

    m = c4d.Matrix()

    m.off = cObj   
    m.v1 = (tObj-cObj).Cross(cObj-upV).GetNormalized() 
    m.v3 = (tObj-cObj).GetNormalized() 
    m.v2 = (tObj-cObj).Cross(m.v1).GetNormalized()


Hi Tudor,

looking at your code I think there's a wrong assumption about the up-vector and how consequently it is used in the definition of the transformation matrix.

The correct approach should look like:

import c4d

cam = op.GetObject()    
target = cam[c4d.ID_USERDATA, 1]

def main():    
    # get "from" and "to vectors
    fromVec = cam.GetMg().off
    toVec = target.GetMg().off
    # use a temporary Up-vector
    tmpVec = c4d.Vector(0, 1, 0)
    # calculate the forward-vector
    fVec = (toVec - fromVec).GetNormalized()
    # calculate the right-vector
    rVec = tmpVec.Cross(fVec)
    # recalculate the proper up-vector
    uVec = fVec.Cross(rVec)
    # fill-up the transformation matrix
    m = c4d.Matrix()
    m.off = fromVec
    m.v1 = rVec
    m.v2 = uVec
    m.v3 = fVec
    # set the camera transformation

Last but not least, please set tags accordingly to your topic and use the Q&A functionality.

Best, Riccardo

Hi Riccardo,
thank you for your help.
After I put GetNormalized() in your line rVec and uVec it works.
But now I get a flipping problem if the cam-Obj is direct over (or under) the target-Obj.
The same happened by the Target-Tag. The Target-Tag has a option to stabilize the system with an up-Vector.
Could I calculate this up-Vector to my matrix to stabilize it too? Or maybe there is a other approach?

Hi Tudor, thanks for following up.

The issue you notice takes place when the temporary up-vector is aligned with the forward-vector: under this scenario the rVec is ambiguous and the whole system results unstable. The solution to the issue is represented by Quaternions or, alternatively you can try to mitigate the effect by putting in place some "work-around" like:

    uVec = fVec.Cross(rVec).GetNormalized()

    # try to mitigate Gimbal-lock
    if (fVec + tmpVec).z < 0:
        uVec.x = -uVec.x

    if abs(rVec.x - 1.0) < 0.001:
        rVec.x = -rVec.x

    # fill-up the transformation matrix

Best, Riccardo

edit: @ferdinand

The approach shown here can be problematic. You instead should choose an up-vector which is not parallel or anti-parallel to the input vector. See Gimbal Lock Safe Target Expression for an example.

thanks again.
I really do not understand it yet but it works.
There are some strange camera behaviors in the viewport but the system still stable.
I have tried also the Quaternions-solution, but I don't know really now the syntax work.
Do you have an idea?

Hi Tudor, with regard to using quaternions, I suggest to search around the web for it: there are hundreds of sites talking extensively about.
I warmly suggest to have a look here where Gimbal lock is presented and some notes are spent on how to avoid it.

Best, Riccardo

Does anyone have a suggestion how to work with Quaternions in my case to avoid the gimbal lock? I realy dont find any examples or approaches to this. Other APIs have different methods for this like SetFromToRotation, SetLookRotation, lookAt ....
Maybe its possible to extend the Python Library with other classes? Don‘t have any idea and not very advanced in this.


unfortunately we can't help developing algorithms. So, what has been said here and in the Quaternion Rotation thread, is probably all we can contribute from MAXON's side.

Maybe somebody from our community is willing to step into this and help out?