Overriding Hierarchies?



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/06/2012 at 12:59, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   12 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Can someone tell me what's going on behind the scenes when the Ctrl key is held down. Allowing the user to move the object independent of it's parents or children?
    How exactly is this magic trick accomplished?

    I'm assuming that it's done by matrix manipulations?
    But since there can be many different  parent/s<->child/children & Grandparent/s<->grandchild/ grandchildren. The number of things to check for seems rather staggering to me. And I think I might be over complicating it.

    This seems like a very common task that anyone doing CG related coding should have in their tool box. And something I had expected to be tutorialized a lot on the internet.
    Yet I'm having trouble finding any tutorials on it.

    Thanks,
    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 05/06/2012 at 16:36, xxxxxxxx wrote:

    OK.
    So I've figured out how to reproduce the way a parent object behaves independently from it's children when the Ctrl key is pressed. But by using a tag and a boolean UserData option instead of the Ctrl key.

    I'll post it in Python. Because it's easier to share it this way than C++:

    #Freeze Children  
    #This code goes in a python tag on the parent object in the hierarchy  
    #When the user clicks the boolean UserData option. It uses the stored children's positions from an array  
    #Then it applies those positions to their matrices so they don't move when the parent moves around  
      
    import c4d  
    mylist = []  
    def main() :  
      
      global mylist  
      
      obj = op.GetObject()  
      objmtx = obj.GetMl()  
      child = obj.GetDown()  
      
      while child:                      #Populate the list with positions  
          childmtx = child.GetMg()  
          pos = childmtx.off  
          mylist.append(pos)           
          child = child.GetNext()  
      
      child = obj.GetDown()  
      counter = 0  
      if op[c4d.ID_USERDATA, 1]== True:  #If the boolean UserData option on the tag is enabled  
          while child:                   #Use the list to set the positions  
              childmtx = child.GetMg()  
              if len(mylist) > counter: childmtx.off = mylist[counter]  
              child.SetMg(childmtx)  
              counter = counter +1  
              child = child.GetNext()
    

    While this works just fine.
    I would really like to know how this compares to the way it's being done by Maxon and the Ctrl key.
    For example. Does Maxon use an array like I did? Or did they do it some other way that is completely different?

    While it's nice that I was able to "invent" this completely on my own from my own imagination. I don't like inventing things on my own until I've learned the industry standard method first.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 06/06/2012 at 08:40, xxxxxxxx wrote:

    Basically you need to cycle through the top level children and change their local matrix by bringing them into the parent's old global space and then matrix multiplication with the inverse new matrix of the parent.

    here an example with comments. hope this helps:

      
    Bool MenuTest::Execute(BaseDocument *doc)  
    {  
      BaseObject *op = NULL;  
      op = doc->GetActiveObject();  
      if (!op) return FALSE;  
      
      Matrix mg_old = op->GetMg(); //save the parent's old matrix  
        
      Matrix mg_new; //this is the parent's new matrix - set it to your liking  
      
      op->SetMg(mg_new); //change the parent's amtrix to the new matrix  
      op->Message(MSG_UPDATE);  
      
      mg_new != mg_new; //invert new matrix - needed later  
      
      //cycle through children  
      for (op = op->GetDown(); op; op = op->GetNext())  
      {  
          Matrix ml_child = op->GetMl(); //get child's local matrix  
      
          //bring it into the child's old global space by multiplying  
          //with the parent's old global matrix  
          Matrix mg_old_child = mg_old * ml_child;  
      
          //set the child's new local matrix by multiplying  
          //with the parent's inverted new global matrix  
          op->SetMl(mg_new * mg_old_child);  
          op->Message(MSG_UPDATE);  
      }  
      
      EventAdd();  
      
      return TRUE;  
    }  
    

    cheers,
    Matthias



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 06/06/2012 at 09:39, xxxxxxxx wrote:

    Thanks Matthias.🍺

    In my head I was always ignoring the parent's original matrix as being not relevant anymore. Because I've set it to a new matrix.
    But your example shows me that I still needed to use it later on.

    I guess that's a good lesson for me to not think of past converted code as nothing but collateral damage.

    -ScottA


Log in to reply