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

    Tile rendering questions

    Scheduled Pinned Locked Moved PYTHON Development
    2 Posts 0 Posters 326 Views 1 Watching
    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.
    • H Offline
      Helper
      last edited by

      On 10/09/2016 at 07:43, xxxxxxxx wrote:

      Dear C4D users,

      For our plugin we like to intergrade tile rendering for our farm. All jobs are sent to the command line of cinema 4d. At the moment we can only render single (full) frames. So for example, when you have 10 frame on animation every server will render out a single image.

      But what we like to add is that servers can work together to create the final image. (tile rendering) For that we need to tell cinema only to render a part of the image. And later on we stitch them together. 
      With team render this is possible, but how to do this with the command line or python/c++ code.

      Every tip or suggestion is welcome!

      Thanks!

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 12/09/2016 at 07:40, xxxxxxxx wrote:

        Hi,

        while it is not possible to add command line options that alter the behavior of built-in functionality (like in your case the rendering process), there are quite a few options. Which fits best, depends of course highly on your situation and the plugin you already seem to have.

        a) If your plugin is running on the server side (i.e. being responsible for distributing the data to the render nodes) you could modify the render settings before sending the scene to a node. For a hint on how to do this, see my Python example code below.

        b) Somewhat the compromise of a) and c), you could write a plugin to run on the render nodes. This plugin would add a new command line option (see either C++ Plugin Functions Manual or Plugin Messages in Python docs (a bit down the page)), which loads the scene (that will later be rendered by C4D), modifies the render settings, saves the scene again. Further down the line C4D would then take over and render.

        c) I once did an example for a Dev Kitchen, which partly already does what you are asking for. It adds a command line option for tiled rendering.
        The downside: You will need to take over the rendering part, e.g. saving to the correct format...
        Note the quotation marks enclosing the entire command line option, needed by this example:
        See here:

        # Dev Kitchen 2015 - Python Commandline #5 - Rendering Tiles
        import sys, os, ntpath, math
        import c4d
        from c4d import bitmaps, documents
          
        # Renders a tile of the current camera
        # Syntax: cinema4d.exe "-rendertiled numtiles tileidx file"
        # with numtiles the number of tiles in x and y direction (numtiles=2 => 4 tiles total)
        # and tileidx either all or between 0 and (numtiles*numtiles)-1
        def CommandRenderTiled(arg) :
          # Parse arguments
          argComponents = arg.split(' ')
          numTiles = int(argComponents[1])
          fNumTiles = float(numTiles)
          if argComponents[2] == "all":
            tileIdxMin = 0
            tileIdxMax = (numTiles * numTiles)
          else:
            tileIdxMin = int(argComponents[2])
            tileIdxMax = tileIdxMin + 1
          fname = argComponents[3]
          
          # Load the scene without inserting into C4D's document list
          doc = documents.LoadDocument(fname, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS)
          if doc is None:
            print "Failed to load file: %s" % fname
            return
          
          bd = doc.GetRenderBaseDraw()
          if bd is None:
            return
          
          # Get the active camera
          cam = bd.GetSceneCamera(doc)
          if cam is None:
            cam = bd.GetEditorCamera(doc)
            if cam is None:
              return
          
          # Get the active render settings and
          rd = doc.GetActiveRenderData()
          filepath, filename = ntpath.split(rd[c4d.RDATA_PATH])
          
          for tileIdx in range(tileIdxMin, tileIdxMax) :
            # Prefix the output filename with tile index
            outputPath = filepath + "/" + str(tileIdx) + "_" + filename
            rd[c4d.RDATA_PATH] = outputPath
          
            # Delete previous render
            if ntpath.isfile(outputPath) is True:
              os.remove(outputPath)
          
            # Create a new camera and configure it for tiled render
            camOffset = c4d.BaseObject(c4d.Ocamera)
            camOffset.SetMg(cam.GetMg())
            camOffset[c4d.CAMERA_PROJECTION] = cam[c4d.CAMERA_PROJECTION]
            camOffset[c4d.CAMERAOBJECT_APERTURE] = cam[c4d.CAMERAOBJECT_APERTURE]
            camOffset[c4d.CAMERAOBJECT_SHOW] = cam[c4d.CAMERAOBJECT_SHOW]
            camOffset[c4d.CAMERA_FOCUS] = cam[c4d.CAMERA_FOCUS] * fNumTiles
            camOffset[c4d.CAMERA_ZOOM] = cam[c4d.CAMERA_ZOOM] * fNumTiles
          
            biasX = math.fmod(float(tileIdx), fNumTiles) - (fNumTiles - 1.0) * 0.5
            biasY = float(tileIdx / numTiles) - (fNumTiles - 1.0) * 0.5
          
            camOffset[c4d.CAMERAOBJECT_FILM_OFFSET_X] = fNumTiles * cam[c4d.CAMERAOBJECT_FILM_OFFSET_X] + biasX
            camOffset[c4d.CAMERAOBJECT_FILM_OFFSET_Y] = fNumTiles * cam[c4d.CAMERAOBJECT_FILM_OFFSET_Y] + biasY
          
            # Insert the new camera into the scene and set it for rendering
            doc.InsertObject(camOffset)
            bd.SetSceneCamera(camOffset)
          
            # Initialize a bitmap with the result size (must match output size of render settings)
            bmp = bitmaps.BaseBitmap()
            bmp.Init(x=rd[c4d.RDATA_XRES], y=rd[c4d.RDATA_YRES], depth=24)
          
            # Render the file (and assure saving of rendered image)
            documents.RenderDocument(doc, rd.GetData(), bmp, c4d.RENDERFLAGS_EXTERNAL)
            if rd[c4d.RDATA_SAVEIMAGE] is False: # if saving is enabled in render settings it will be saved automatically
              if bmp.Save(outputPath, c4d.FILTER_TIF, None, c4d.SAVEBIT_0) is not IMAGERESULT_OK:
                print "An error occurred, when saving the image %s" % outputPath
          
          
        def ParseCommandline(argv) :
          for arg in argv:
            if arg.find("-rendertiled") == 0:
              CommandRenderTiled(arg)
          
          
        def PluginMessage(id, data) :
          if id == c4d.C4DPL_COMMANDLINEARGS:
            # Extend command line parsing, here
            # This is the last plugin message on Cinema 4D's start process
            ParseCommandline(sys.argv)
          return True
        
        1 Reply Last reply Reply Quote 0
        • First post
          Last post