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

    Developing .obj sequence exporter for selected objects

    Cinema 4D SDK
    python
    5
    12
    3.7k
    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.
    • P
      Polyflow
      last edited by a_block

      Hello i am new here.
      I am developing obj files sequence exporter .
      Now it properly export regular objects such as moving cube itc but skinned meshes stuck in one pose over all frames.
      I found not so elegant solution - Bake it as Alembic before export skinned mesh . Any options to export skinning meshes wihtout prebaking? Or how bake objects by script?

      import c4d
      import os
      import subprocess
      from c4d import gui
      
      
      #USAGE:
      #1) SET TIMELINE START-END
      #2) SELECT OBJECTS TO EXPORT
      #3) EXECUTE SCRIPT
      #4) SELECT FILENAME. FRAME NUMBER WILL BE AUTOMATICALLY ADDED TO .OBJ FILE NAMES
      
      
      def main():
          c4d.StopAllThreads()
          doc = c4d.documents.GetActiveDocument()
          fps = doc.GetFps()
          fromTime = doc.GetMinTime().GetFrame(fps)
          toTime = doc.GetMaxTime().GetFrame(fps)
          animLength = toTime - fromTime + 1
          filePath = c4d.storage.SaveDialog()
          filePath, objName = os.path.split(filePath)
          objName = objName + "_"
          filePath = filePath + "\\"
      
      
          for f in range(0,animLength):
      
              c4d.EventAdd(c4d.EVENT_FORCEREDRAW)
              c4d.DrawViews(c4d.DRAWFLAGS_FORCEFULLREDRAW)
              c4d.StatusSetText("Exporting " + str(f) + " of " + str(animLength))
              c4d.StatusSetBar(100.0*f/animLength)
      
              objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
      
              # Get a fresh, temporary document with only the selected objects
              docTemp = c4d.documents.IsolateObjects(doc, objs)
              docTemp.SetTime(c4d.BaseTime(fromTime,fps) + c4d.BaseTime(f,fps))
              if docTemp == None:
                  return
      
              # Set project scale
              unitScale = c4d.UnitScaleData()
              unitScale.SetUnitScale(1.0, c4d.DOCUMENT_UNIT_M)
      
              bc = c4d.BaseContainer()
              bc[c4d.DOCUMENT_DOCUNIT] = unitScale
              docTemp.SetDocumentData(c4d. DOCUMENTSETTINGS_DOCUMENT, bc)
      
      
              fileName = filePath+objName+str(f)+".obj"
              savingresult = c4d.documents.SaveDocument(docTemp,fileName,c4d.SAVEDOCUMENTFLAGS_0,c4d.FORMAT_OBJ2EXPORT)
              c4d.documents.KillDocument(docTemp)
      
          c4d.StatusClear()
          gui.MessageDialog( 'Exporting to'+filePath+' done' )
      
      
      if __name__=='__main__':
          main()
      
      
      1 Reply Last reply Reply Quote 0
      • a_blockA
        a_block
        last edited by

        Hello @Polyflow,

        welcome to the Plugin Café ☺

        Setting time via SetTime() basically just sets the time value in the document. But C4D also needs to evaluate the scene at that moment in time. This is done by calling ExecutePasses().

        DrawViews() can indeed do the same (and more) for you, but in your case it should not be needed, ExecutePasses() should be fine. See for example this thread for some discussion on this topic: python plugin for every frame

        So, in your code, you probably also need to "execute" the temporary document.

        There's some more information on this in our C++ SDK manuals. I know, we are talking Python here, but maybe it's interesting anyway: BaseDocument manual - Time

        Cheers,
        Andreas

        1 Reply Last reply Reply Quote 2
        • mikeudinM
          mikeudin
          last edited by

          May be Polygonize can help you.

          Make a clone of the document and turn all objects into polygon based objects.

          Checkout my python tutorials, plugins, scripts, xpresso presets and more
          https://mikeudin.net

          P 1 Reply Last reply Reply Quote 1
          • a_blockA
            a_block
            last edited by

            I'm afraid I need to apologize, my answer was actually by some discussion we had internally and I was too confused to read properly again. Sorry. Maybe @mikeudin's answer can already help. We'll look into this tomorrow again.

            1 Reply Last reply Reply Quote 0
            • a_blockA
              a_block
              last edited by

              Hello @Polyflow,

              we thought a bit more about your request. Unfortunately I had no time, yet, to do some tests here.
              In general we think, my last answer should at least be part of a solution of the problem.

              In regards to "polygonizing" or "baking", this should actually be just a matter of correctly retrieving the cache of an object in the executed document. Please take a look at GetDeformCache() and GetCache(). Again also the C++ docs have some more info on this: BaseDocument manual - Cache.

              Cheers,
              Andreas

              1 Reply Last reply Reply Quote 1
              • P
                Polyflow @mikeudin
                last edited by

                @mikeudin
                Polygonize not works for me.

                By the way - I'm amazed at the responsiveness of your community.

                1 Reply Last reply Reply Quote 0
                • P
                  Polyflow
                  last edited by

                  Now i am trying to Bake an object before export using Current State To Object but this test piece of code not do anything

                  res = utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                                                  list = [op],
                                                  mode = c4d.MODELINGCOMMANDMODE_ALL,
                                                  doc = doc)
                      c4d.EventAdd()
                  1 Reply Last reply Reply Quote 0
                  • M
                    mp5gosu
                    last edited by mp5gosu

                    Hi @Polyflow,
                    did you try the example here? Also, please keep an extra eye on the note that's written below there.
                    You have to first clone your object via GetClone() and pass this as to your object list.
                    For example, I'm using this code in one of my plugins at work (there's a lot of error-handling stuff missing though):

                    # current state to object
                    def csto(op):
                        if op is None:
                            return False
                    
                        doc = op.GetDocument()
                    
                        if doc is None:
                            return False
                    
                        pred = op.GetPred()
                        parent = op.GetUp()
                    
                        settings = c4d.BaseContainer()
                        settings.SetBool(c4d.MDATA_CURRENTSTATETOOBJECT_INHERITANCE, True)
                        newOp = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                                                              mode=c4d.MODELINGCOMMANDMODE_ALL,
                                                              list=[op.GetClone()],
                                                              doc=doc,
                                                              bc=settings)
                    
                        if newOp:
                            doc.AddUndo(c4d.UNDOTYPE_NEW, newOp[0])
                            doc.InsertObject(newOp[0], parent, pred)
                            c4d.EventAdd()
                            return True
                    
                        return False
                    

                    and

                    for polygonizing the document:

                    # Polygonize document, respecting instances in the right order, returns new document
                    def polygonize(doc):
                        if doc is None:
                            return None
                    
                        op = doc.GetFirstObject()
                        oldObjects = []
                    
                        while op:
                            if op.IsInstanceOf(c4d.Oinstance):
                                # check and convert instances
                                oldObjects.append(op)
                                csto(op)
                    
                            op = GetNextObject(op)
                    
                        for op in oldObjects:
                            doc.AddUndo(c4d.UNDOTYPE_DELETE, op)
                            op.Remove()
                    
                        return doc.Polygonize()
                    

                    You have to resolve the instances before using this code, though.
                    Hope, this helps you a bit.

                    P 1 Reply Last reply Reply Quote 2
                    • P
                      Polyflow @mp5gosu
                      last edited by

                      @mp5gosu i am unsuccessfully trying code from documentation.

                      I’m the developer of Vertex Animation Tools for Unity, I can’t say that I'm new to tool development, but this API makes me feel stupid. I saw the Polygonyze function, but I don’t see its result. I'm really trying to understand the C4D API in reasonable term but I can't. Exporting the obj sequence from c4d is a trivial function that people have been looking for for years, and now I understand why.
                      Can Maxons engineers helps to write this script (finally)?

                      1 Reply Last reply Reply Quote 0
                      • mikeudinM
                        mikeudin
                        last edited by

                        To see the results of Poligonize method you have to insert resulting document.

                        Checkout my python tutorials, plugins, scripts, xpresso presets and more
                        https://mikeudin.net

                        1 Reply Last reply Reply Quote 0
                        • a_blockA
                          a_block
                          last edited by

                          @Polyflow: MAXON's SDK Team can only help and assist you in achieving your goal. Writing complete scripts and plugins is not within our mandate.

                          With that said, what about my answer regarding caches? Can you give us some more details on the issues you have with this approach?

                          Cheers,
                          Andreas

                          1 Reply Last reply Reply Quote 0
                          • B
                            bentraje
                            last edited by

                            Probably not that helpful but there is an existing script for the C4D OBJ Sequence Exporter
                            https://richh.co/c4d-native-obj-sequence-export-no-plugins/

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