Jump to content
Sign in to follow this  
blastframe

[Python Tag] Making on Object Follow Another in Just One Dimension

Recommended Posts

Hello! I want to have one object follow another object in just one dimension (e.g. position.x), maintaining their offset, even if the follower is a child of the leader. This needs to be done in a Python Tag (so no Constraints). I asked this question on the SDK forums and got to this point with Manuel at MAXON (Follow.zip). Before hitting play, you store the initial offset with a User Data button on the Python Tag. There’s some strange wobbling happening and I’m a little stuck. Any help would be tremendous, thank you!

hpIk7nE.gif

import c4d
from c4d import utils

storedData = 123456 # baseContainer
offsetInitializedID = 1000 # Bool
offsetID = 1001 #Vector
matrixLockID = 1002 #Matrix

def WriteOffset(obj, vec, init = True):
    # write the offset in the BaseContainer
    global storedData
    data = obj.GetDataInstance()
    if data is None:
        print "None"
        return False
    bc = data.GetContainer(storedData)
    if bc is None:
        print "No BC"
        bc = c4d.BaseContainer()
    bc.SetBool(offsetInitializedID, init)
    bc.SetVector(offsetID, vec)
    data.SetContainer(storedData, bc)
    for cid,val in bc:
        print cid,val
    return True

def ReadOffset(obj):
    global storedData
    data = obj.GetDataInstance()
    if data is None:
        return False, c4d.Vector(0)
    bc = data.GetContainer(storedData)
    return  bc.GetBool(offsetInitializedID), bc.GetVector(offsetID), bc.GetMatrix(matrixLockID)

def ClearOffset(obj):
    global storedData
    data = obj.GetDataInstance()
    if data is None:
        return False
    bc = data.GetContainer(storedData)
    if bc is None:
        bc = c4d.BaseContainer()
    del data[storedData]
    for cid,val in bc:
        print cid,val
    for cid,val in data:
        print cid,val
    return True

def message(id, data):
    if id == c4d.MSG_DESCRIPTION_COMMAND:
        if data['id'].GetDepth() > 1 and data['id'][1].id == 2:
            # get the target's matrix
            target = op[c4d.ID_USERDATA,1]
            obj = op.GetObject()
            if target is None or obj is None:
                return
            #Get the object's matrix'
            tmg = target.GetMg()
            objmg = obj.GetMg()
            diffMatrix = objmg -  tmg
            offset = diffMatrix.off
            if not WriteOffset(obj, offset):
                raise ValueError ("couldn't write value in the basecontaier")
        if data['id'].GetDepth() > 1 and data['id'][1].id == 3:
            obj = op.GetObject()
            if not ClearOffset(obj):
                raise ValueError ("couldn't clear value in the basecontaier")

def GetGlobalScale(m):
    return c4d.Vector(  m.v1.GetLength(),
                        m.v2.GetLength(),
                        m.v3.GetLength())

def main():

    followX = op[c4d.ID_USERDATA,6]

    # Retrieve the object

    # option 0 all param
    # option 1 only rotation
    # option 2 only offset
    # option 3 only X axis
    # option 4 even if B is child of A only X
    option  = 4

    obj = op.GetObject()
    objMg = obj.GetMg()

    offsetActive, offset, oldMatrix = ReadOffset(obj)

    if offsetActive:
        target = op[c4d.ID_USERDATA,1]
        tmg = target.GetMg()

        if option  == 0:
            # Get the global coordinate of the offset.
            tmg.off = tmg * offset

        elif option == 1:
            # Only add the offset to the target's matrix
            tmg.off = objMg.off

        elif option == 2:
            # Build the new matrix based on the object's matrix and the global coordinate of the offset
            objMg.off = tmg * offset
            tmg = objMg

        elif option == 3:
            objMg.off = c4d.Vector(tmg.off.x +  offset.x, objMg.off.y, objMg.off.z)
            tmg = objMg

        elif option == 4:
            oldMatrix.off = c4d.Vector(tmg.off.x + offset.x, oldMatrix.off.y, oldMatrix.off.z)
            tmg = oldMatrix

        # remove the scale by normalizing the
        tmg.Normalize()
        if (followX):
            obj.SetMg(tmg)

 

Share this post


Link to post
Admin

Sorry, no time to dive into script itself but seems your matrix is skewed. If you are looking to create rolling object you can find such setup in my file pit

 

https://www.c4dcafe.com/ipb/forums/topic/104962-hrvojes-free-file-pit/?do=findComment&comment=699553

 

 

Share this post


Link to post
  • Topic Author
  • Author of the topic Posted
    6 hours ago, Hrvoje said:

    Sorry, no time to dive into script itself but seems your matrix is skewed. If you are looking to create rolling object you can find such setup in my file pit

     

    https://www.c4dcafe.com/ipb/forums/topic/104962-hrvojes-free-file-pit/?do=findComment&comment=699553

     

     

     

    Hi, that's a cool setup, but I'm not trying to create a roll. I want one object to follow the other in just one dimension, even if it's a child. The matrix is being skewed by the code, but I don't think it is skewed beforehand.

    Share this post


    Link to post

    (As this is discussed on PluginCafé, I'll just mention that I believe it's a bug in the Python matrix inversion. I just posted a screenshot there; it's easily reproductible.)

    Share this post


    Link to post

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Reply to this topic...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    Sign in to follow this  

    • Recently Browsing   0 members

      No registered users viewing this page.

    ×
    ×
    • Create New...

    FORUMS INFO:

    Dear members, we are aware of few more bugs that are still present withing the theme.We just wanted to let you know that we are working to fix them as soon as possible.
     

    NEW MEMBERS:

    Please be aware that we are manually approving all new registrations, due to spam prevention. Please be patient in case you cannot login right away, we will approve you within 12h or less if we decide you are not potential spammer. 

     

    Thanks for understanding! :cowboypistol: