Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    Getting a polygonal version of an animated mesh

    Cinema 4D SDK
    2
    3
    696
    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.
    • R
      rui_mac
      last edited by m_adam

      O need to get a polygonal version of any object wthat is animated (with keyframes or deformers).
      My code, so far, is:

              curr_time = c4d.BaseTime(frame_start,doc_fps) + c4d.BaseTime(x,doc_fps)
              doc.AnimateObject(op,curr_time, c4d.ANIMATEFLAGS_NONE)
              doc.SetTime(curr_time)
      
              c4d.EventAdd(c4d.EVENT_FORCEREDRAW)
              c4d.DrawViews(c4d.DRAWFLAGS_FORCEFULLREDRAW)
      
              bc = c4d.BaseContainer()
              bc[c4d.MDATA_CURRENTSTATETOOBJECT_INHERITANCE] = True
              bc[c4d.MDATA_CURRENTSTATETOOBJECT_KEEPANIMATION] = True
              bc[c4d.MDATA_CURRENTSTATETOOBJECT_NOGENERATE] = False
              bc[c4d.MDATA_CURRENTSTATETOOBJECT_LOD] = 1.0
              bc[c4d.MDATA_CURRENTSTATETOOBJECT_BUILDFLAGS] = c4d.BUILDFLAGS_NONE
      
              clone_op = op.GetClone(flags=c4d.COPYFLAGS_NONE)
      
              res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                                              list=[clone_op],
                                              mode=c4d.MODELINGCOMMANDMODE_ALL,
                                              bc=bc,
                                              doc=doc,
                                              flags=c4d.MODELINGCOMMANDFLAGS_NONE)
      

      But the resulting object(s) inside the res list, seem to only result in the non-animated object.
      How can I get the animated/deformed mesh?

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by m_adam

        Hi @rui_mac please make sure to post in the correct category, for anything related to Cinema 4D please post into the CINEMA 4D DEVELOPMENT category (I've moved your topic)
        Also, make sure to use the tagging system.

        In regards to your code, few things to say.
        First, there is no loop over time (so you never change the time of the current document)
        Moreover, when you clone the object, the returned object is not inserted into any document so even if you copy an object with these animation data they are lost since there is no document to define the time.

        Finally, a more suited approach is to use BaseObject.GetDeformCache which store the deformed state of an object.
        Find an example here, I also attached a scene, select the cloner run the script it will create a Null based on the position of each clone

        """
        Copyright: MAXON Computer GmbH
        Author: Maxime Adam
        
        Description:
            - Animates a BaseDocument from frame 5 to 20.
            - Retrieves all the deformed mesh from the selected object
            - Creates a Null for each frame at the position of point 88 of all deformed mesh
        
        Class/method highlighted:
            - BaseObject.GetDeformCache()
            - c4d.BaseTime()
            - BaseDocument.SetTime()
            - BaseDocument.ExecutePasses()
        
        Compatible:
            - Win / Mac
            - R16, R17, R18, R19, R20
        """
        import c4d
        
        
        def DeformedPolygonCacheIterator(op):
            """
            A Python Generator to iterate over all PolygonCache of passed BaseObject
            :param op: The BaseObject to retrieves all PolygonObject cache.
            """
            if not isinstance(op, c4d.BaseObject):
                raise TypeError("Expected a BaseObject or derived class got {0}".format(op.__class__.__name__))
        
            # Try to retrieves the deformed cache of the object
            temp = op.GetDeformCache()
            if temp is not None:
                # If there is a deformed cache we iterate over him, a deformed cache can also contain deformed cache
                # e.g. in case of a nested deformer
                for obj in DeformedPolygonCacheIterator(temp):
                    yield obj
        
            # Try to retrieves the cache of the Object
            temp = op.GetCache()
            if temp is not None:
                # If there is a cache iterates over its, a cache can also contain deformed cache
                # e.g. an instance, have a cache of its linked object but if this object is deformed, then you have a deformed cache as well
                for obj in DeformedPolygonCacheIterator(temp):
                    yield obj
        
            # If op is not a generator / modifier
            if not op.GetBit(c4d.BIT_CONTROLOBJECT):
                # If op is a PolygonObject we return it
                if op.IsInstanceOf(c4d.Opolygon):
                    yield op
        
            # Then finally iterates over the child of the current object to retrieves all objects
            # e.g. in a cloner set to Instance mode, all clones is a new object.
            temp = op.GetDown()
            while temp:
                for obj in DeformedPolygonCacheIterator(temp):
                    yield obj
                temp = temp.GetNext()
        
        
        def main():
            # Saves current time
            ctime = doc.GetTime()
        
            # Retrieves BaseTime of frame 5, 20
            start = 5
            end = 20
        
            # Marks the state of the document as the initial step of our undo process
            doc.StartUndo()
        
            # Loops through the frames
            for frame in xrange(start, end + 1):
                # Changes the time of the document
                doc.SetTime(c4d.BaseTime(frame, doc.GetFps()))
        
                # Executes the document, so animation, dynamics, expression are calculated and cached are build accordingly
                buildflag = c4d.BUILDFLAGS_NONE if c4d.GetC4DVersion() > 20000 else c4d.BUILDFLAGS_0
                doc.ExecutePasses(None, True, True, True, buildflag)
        
                # For each cache objects of our current selected object
                for obj in DeformedPolygonCacheIterator(op):
        
                    # Calculates the position of the point 88 in world space
                    pos = obj.GetPoint(88) * obj.GetMg()
        
                    # Creates a null for each frame and each cache
                    null = c4d.BaseObject(c4d.Onull)
                    null.SetName(str(frame))
        
                    # Inserts the objects into the documents
                    doc.AddUndo(c4d.UNDOTYPE_NEW, null)
                    doc.InsertObject(null)
        
                    # Defines the position of the null with the position of the point from the deformed mesh
                    null.SetAbsPos(pos)
        
            # Sets the time back to the original time.
            doc.SetTime(ctime)
        
            # Executes the document, so animation, dynamics, expression are calculated and cached are build accordingly
            buildflag = c4d.BUILDFLAGS_NONE if c4d.GetC4DVersion() > 20000 else c4d.BUILDFLAGS_0
            doc.ExecutePasses(None, True, True, True, buildflag)
        
            # Marks the state of the document as the final step of our undo process
            doc.EndUndo()
        
            # Updates Cinema 4D
            c4d.EventAdd(c4d.EVENT_ANIMATE)
        
        
        if __name__ == "__main__":
            main()
        

        test_scene.c4d

        If you have any question, please let me know.
        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • R
          rui_mac
          last edited by

          Well, I do have a loop but I just pasted the code that would, hopefully, perform the calculation.
          And I did tried the GetDeformCache approach, but my mistake was, in fact the cloning of the object.
          Thank you so much for the code, Adam.

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