Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Copy mesh from one object to another with Python

    Cinema 4D SDK
    3
    9
    1.8k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • K
      karpique
      last edited by

      Hi! I'm looking for quick way to copy all points, edges and polygons data from one poly object to another with Python tag.

      Right now i'm using this loops:

          for i in range(0, pointCount):
              targetObj.SetPoint(i, sourceObj.GetPoint(i))
      
          for i in range(0, polygonCount):
              poly = sourceObj.GetPolygon(i)
              if poly.IsTriangle():
                  targetObj.SetPolygon(i, c4d.CPolygon(poly.a, poly.b, poly.c))
              else:
                  targetObj.SetPolygon(i, c4d.CPolygon(poly.a, poly.b, poly.c, poly.d))
      

      It's missing hidden edges for Ngons feature but already really slow on 10k+ polygons. Is there way to do it faster?

      I'm looking into Edit->Copy & Edit->Paste commands but its really hacky way since its tag, not a single execution script.
      Also C4DAtom.CopyTo() looks promising but I have no idea what flag I should pass to copy only mesh, not every object property

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @karpique
        last edited by ferdinand

        Hello @karpique,

        Thank you for reaching out to us. There are two things you could optimize out in your code. Frist, the loop around targetObj.SetPoint, since there is PointObject.SetAllPoints, taking a list of points and being much faster. Secondly, you could also optimize away the branching in your code with poly.IsTriangle(), since both tris and quads are being handled as quads by Cinema 4D (a tri is a handled as a CPolygon where c == d). So, you could just write:

        for i in range(0, polygonCount):
            poly = sourceObj.GetPolygon(i)
            targetObj.SetPolygon(i, c4d.CPolygon(poly.a, poly.b, poly.c, poly.d))
        

        Unlike for points, there is unfortunately no method in Python to write CPolygon in bulk with, making writing polygons in Python quite slow. As you mentioned, you could also use C4DAtom.CopyTo, but there is no clean way to "copy only (the) mesh", since geometry information is being stored in tags and not the node itself. This will also copy n-gons:

        """Example for copying polygons and n-gons from one node to another.
        
        Run this with a polygon object selected in the script manger.
        """
        
        import c4d
        
        def main():
            """
            """
            # Create a Opolygon node of matching size
            res = c4d.PolygonObject(op.GetPointCount(), op.GetPolygonCount())
            # We first have to insert that new node into a document, this could also
            # be a temporary document.
            doc.InsertObject(res)
            c4d.EventAdd()
            # Then we just copy over stuff from the source. We cannot use the 
            # COPYFLAGS_NO_BRANCHES flag, as this will prevent copying tag data,
            # which is also being used to store point and polygon information.
            flags = c4d.COPYFLAGS_NO_ANIMATION | c4d.COPYFLAGS_NO_HIERARCHY | c4d.COPYFLAGS_NO_BITS
            op.CopyTo(res, flags)
            
        
        if __name__=='__main__':
            main()
        

        There are some other routes you could take, like. c4d.utils.SendModelingCommand and joining your mesh to copy with an empty mesh or handling it in a more hands-on-fashion by copying over the Tpoint and Tpolygon tags manually, and thereby avoid copying unwanted tag information.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        K 1 Reply Last reply Reply Quote 0
        • K
          karpique @ferdinand
          last edited by

          @ferdinand thanks for qiuck answer and quality info! I went with copying Tpoint and Tpolygn tags, but now stuck with translating hidden Ngon edges — can you point the right way to do that?

          I feel like it sholud be some functions from c4d.PolygonObject class but stuck in here:

          bs = c4d.BaseSelect()
          bs.SetAll([0] * polyObj.GetPolygonCount() * 4)
          ng = c4d.utils.Neighbor()
          ng.Init(polyObj)
          #doesnt work as expected, hidden ngon edges are not showing up
          polyObj.SetSelectedEdges(ng, bs, c4d.EDGESELECTIONTYPE_HIDDEN) 
          
          1 Reply Last reply Reply Quote 0
          • X
            x_nerve
            last edited by x_nerve

            Hi:

            Do you want to make a complete copy of another polygon object from scratch using Python tags?Including n-gon edges.

            You hide edges incorrectly, it's still not an n-gon edge, it's just an edge selection.I have the full Python tag code, which is fast, but I won't post it here.However, this Python tag only runs in R23 and up.Since Python cannot directly create polygons with n-gon edges, it can only be done with the Model Elimination command in versions R23 and above.

            Your Python code isn't optimal, so it's not fast.The fastest way to do this is to use C++, which can create polygons with n-gon edges directly and at tens of times the speed of Python tags.Also, Python tags create n-gon polygons that don't have the same edge indexes as the n-gon polygons that copy objects, which is one of Python's flaws.

            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand
              last edited by ferdinand

              Hello @karpique,

              the Ngon interface is not being exposed to Python, which makes handling them always a bit harder there. You will have to either copy the PolygonObject itself, like shown by me above, which will handle Ngons properly. Or you have to use PolygonObject.GetNGonTranslationMap to manually recrate the Ngons on the new PolygonObject. Due to the absence of the Ngon interface in Python, you would have to do this with c4d.utils.SendModelingCommand and the symbol MCOMMAND_MELT. Due to this being rather cumbersome, I showed the more general solution in my previous posting. If you want to clean up an object with that more general solution, you could iterate over all tags and remove any tag that is not of type Tphong, Tpoint, or Tpolygon (you might want to include other tag types, depending on what your goals are).

              Cheers,
              Ferdinand

              MAXON SDK Specialist
              developers.maxon.net

              K 2 Replies Last reply Reply Quote 0
              • K
                karpique @ferdinand
                last edited by

                This post is deleted!
                1 Reply Last reply Reply Quote 0
                • K
                  karpique @ferdinand
                  last edited by karpique

                  @ferdinand thanks! I have one more question: after replacing Tpoint and Tpolygon tags object seems to keep it's old bounding box parameters and disappear from viewport accordigly to them. Is there a way to update this property?

                  1 Reply Last reply Reply Quote 0
                  • ferdinandF
                    ferdinand
                    last edited by

                    Hi @karpique,

                    hard to say from the outside without any code to see what you are doing, but my educated guess would be that

                    myObjectWithFaultyBòundingBox.Message(c4d.MSG_UPDATE)
                    c4d.EventAdd()
                    

                    will solve your porblem.

                    Cheers,
                    Ferdinand

                    MAXON SDK Specialist
                    developers.maxon.net

                    1 Reply Last reply Reply Quote 1
                    • K
                      karpique
                      last edited by

                      @ferdinand I get Ngon translation map and applied MCOMMAND_MELT but stuck again — as I understand SendModellingCommand only returns new object with melted ngons, but my goal is to correct object that already exists in scene...

                      Is there any other ways of setting up Ngon translation map with python?

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post