Want to create a DR render helper



  • On 07/11/2016 at 17:15, xxxxxxxx wrote:

    I have a desire to use Distributed Rendering of an image sequence using the existing Team Render setup.

    I attempted to setup something using Automator on OS X, but it is a little sporadic in success.

    What I'm trying to do:

    Have a python script (or plug) that reads the c4d.RDATA_FRAMEFROM and c4d.RDATA_FRAMETO.

    I'd then want to have it place the current time to the start frame, and kick off a Team Render for only that frame. When that frame is finished, it should increment up a step and repeat the process until all the frames in the frame range have been rendered.

    This will allow me to do image sequence renders using Team Render's great Distributed Render buckets.

    My script is getting hung up on the c4d.RDATA_FRAMEFROM

    That specific part of my code is:

    doc = c4d.documents.GetActiveDocument();
    rd = doc.GetActiveRenderData();
    startFrame = rd[c4d.RDATA_FRAMEFROM];

    print "START FRAME: %s" % startFrame;

    When I execut it I get this:

    START FRAME: <c4d.BaseTime object at 0x124b25120> (and that hex code changes each time I run it)

    What I need is a frame integer.

    Or perhaps one of you awesome python guys can point me in a smarter direction altogether?

    Thanks in advance for any help you can provide

    Cheers



  • On 07/11/2016 at 18:16, xxxxxxxx wrote:

    Get:

        fps = doc.GetFps()  
      rd = doc.GetActiveRenderData()  
      start = rd[c4d.RDATA_FRAMEFROM].GetFrame(fps)  
      print start
    

    Set:

        fps = doc.GetFps()  
      rd = doc.GetActiveRenderData()  
      frame = 5  #<---Change as desired  
      start = rd[c4d.RDATA_FRAMEFROM]= c4d.BaseTime(frame, fps)
    

    -ScottA



  • On 08/11/2016 at 07:00, xxxxxxxx wrote:

    Ah ok. Thanks!



  • On 08/11/2016 at 09:32, xxxxxxxx wrote:

    Hi,

    thanks, to Scott for providing the perfect solution.
    Just want to add some additional information here (even though Scott's snippets explain it already) :
    The data stored under ID RDATA_FRAMEFROM is of type BaseTime. Our C++ documentation provides some more information on this in the BaseTime manual.



  • On 08/11/2016 at 10:46, xxxxxxxx wrote:

    Thank you Andreas! I'm very much new at this, but I know the basics.

    I seem to be struggling with errors involving document versus basetime, etc.

    And I'm confused why there is NetRenderService.StopRendering, but not StartRendering.

    I probably expect it to be too simple.

    I could really use some help getting the basics of this working properly.   I don't want it to run outside of C4D. I just want to be able to basically control picture viewer rendering with an open document, with the goal being:

    Using Team Render to picture viewer to do bucket rendering on an image sequence (animation) by tricking it into rendering successive single image renders.

    Thanks for your helpful nudges. I'll continue to work at it!



  • On 08/11/2016 at 10:51, xxxxxxxx wrote:

    Maybe I should ask a more directed question:

    Can I achieve what I'm trying to achieve through python?



  • On 08/11/2016 at 10:59, xxxxxxxx wrote:

    I have it all working so far, except the actual call to render the active document using teamrender to picture viewer



  • On 08/11/2016 at 11:21, xxxxxxxx wrote:

    I'm using RENDERFLAGS_EXTERNAL, and it is working...but how do I specify to do "Team Render to Picture Viewer"



  • On 08/11/2016 at 12:07, xxxxxxxx wrote:

    I'm still using R13 so I don't have TR to test this myself.
    What happens if you use: RENDERFLAGS_NET

    -ScottA



  • On 08/11/2016 at 12:43, xxxxxxxx wrote:

    Thanks for you help!

    Hmmm....well that didn't throw an error. However, in the Team Render Machines window, the status of the clients does not change.

    Also, I decided to move my iterative code into a function that could be called and checked as we go, and I'm getting a scope error. I'm guessing I need to declare my variables in a more global way?

    Here's all my code thus far:

    import c4d
    import os

    from c4d import bitmaps, documents, gui

    def main() :
        # Get Basic Vairables

    doc = c4d.documents.GetActiveDocument();
        fps = doc.GetFps();
        rd = doc.GetActiveRenderData().GetData();
        xres = int(rd[c4d.RDATA_XRES]);
        yres = int(rd[c4d.RDATA_YRES]);
        bmp = bitmaps.BaseBitmap();
        bmp.Init(x=xres, y=yres, depth=24);
        startFrame = rd[c4d.RDATA_FRAMEFROM].GetFrame(fps);
        endFrame = rd[c4d.RDATA_FRAMETO].GetFrame(fps);
        thisFrame = startFrame;
        
        #set current frame for render
        def setRenderFrame() :
            rd[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(thisFrame,fps);
            rd[c4d.RDATA_FRAMETO] = c4d.BaseTime(thisFrame, fps);
        
       
        def doRender() :
            res = documents.RenderDocument(doc,rd, bmp, c4d.RENDERFLAGS_NET);
            if res==c4d.RENDERRESULT_OK:
                bitmaps.ShowBitmap(bmp);
                thisFrame +=1;
                if thisFrame > endFrame:
                   return
                setRenderFrame();
                doRender();
           
           
        doRender();
        
        c4d.EventAdd();
        
    if __name__=='__main__':
        main();



  • On 08/11/2016 at 12:45, xxxxxxxx wrote:

    The error:

    Traceback (most recent call last) :
    File "'scriptmanager'", line 44, in <module>
    File "'scriptmanager'", line 39, in main
    File "'scriptmanager'", line 32, in doRender
    UnboundLocalError: local variable 'thisFrame' referenced before assignment



  • On 08/11/2016 at 13:33, xxxxxxxx wrote:

    I can't help you with the Team Render stuff. But I can show you how to write your code so it runs.
    Note the changes.
    When posting code. Please use this type of forum code: "["code"]" your code here "["/code"]"
    Without the quotes.

    import c4d  
    import os  
    from c4d import bitmaps, documents, gui  
      
    def setRenderFrame(rd, thisFrame, endFrame) :  
      fps = doc.GetFps()  
      rd[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(thisFrame,fps)  
      rd[c4d.RDATA_FRAMETO] = c4d.BaseTime(endFrame, fps)   
      
    def doRender(doc, rd, bmp, thisFrame, endFrame) :  
      res = documents.RenderDocument(doc, rd, bmp, c4d.RENDERFLAGS_EXTERNAL)  
      if res==c4d.RENDERRESULT_OK:  
          bitmaps.ShowBitmap(bmp)  
          thisFrame +=1  
          if thisFrame > endFrame: return  
          setRenderFrame(rd, thisFrame, endFrame)  
      
    def main() :      
      
      doc = c4d.documents.GetActiveDocument()  
      fps = doc.GetFps()  
      rd = doc.GetActiveRenderData().GetData()  
      xres = int(rd[c4d.RDATA_XRES])  
      yres = int(rd[c4d.RDATA_YRES])  
      bmp = bitmaps.BaseBitmap()  
      bmp.Init(x=xres, y=yres, depth=24)  
      startFrame = rd[c4d.RDATA_FRAMEFROM].GetFrame(fps)  
      endFrame = rd[c4d.RDATA_FRAMETO].GetFrame(fps)  
      thisFrame = startFrame     
        
      for i in xrange(startFrame, endFrame - startFrame) :  
          doRender(doc, rd, bmp, thisFrame, endFrame)  
        
      c4d.EventAdd()  
        
    if __name__=='__main__':  
      main()
    

    Someone else who has TR will need to help you with that part.

    -ScottA



  • On 08/11/2016 at 14:03, xxxxxxxx wrote:

    You are so helpful. Thank you for taking the time.

    I've run your version of the script and I'm getting the following NameError:

    Traceback (most recent call last) :
    File "'scriptmanager'", line 36, in <module>
    File "'scriptmanager'", line 31, in main
    File "'scriptmanager'", line 11, in doRender
    NameError: global name 'setRenderFrame' is not defined

    Looks like it's trying to parse the definition of setRenderFrame() before it is defined.

    I've never been great at wrapping my brain around scope issues like this. ha.

    Thanks for all your help thus far.



  • On 08/11/2016 at 14:23, xxxxxxxx wrote:

    OK I've tweaked things a little and the iteration is working within the variables...however, it is rendering the same frame over and over, and for some reason now it is not naming them appropriately. It keeps saving the same file over and over without iterating the filename, and doesn't appear to actually be stepping through the timeline either.

    import c4d   
    import os   
    from c4d import bitmaps, documents, gui   
      
      
      
    def main() :       
      
        doc = c4d.documents.GetActiveDocument()   
        fps = doc.GetFps()   
        rd = doc.GetActiveRenderData().GetData()   
        xres = int(rd[c4d.RDATA_XRES])   
        yres = int(rd[c4d.RDATA_YRES])   
        bmp = bitmaps.BaseBitmap()   
        bmp.Init(x=xres, y=yres, depth=16)   
        startFrame = rd[c4d.RDATA_FRAMEFROM].GetFrame(fps)   
        endFrame = rd[c4d.RDATA_FRAMETO].GetFrame(fps)   
        thisFrame = startFrame   
        print "thisFrame: %s" % thisFrame   
        print "endFrame: %s" % endFrame   
           
        #set current frame for render   
      
              
        def doRender(doc, rd, bmp, thisFrame, endFrame) :   
            rd[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(thisFrame,fps)   
            rd[c4d.RDATA_FRAMETO] = c4d.BaseTime(thisFrame, fps)   
            res = documents.RenderDocument(doc, rd, bmp, c4d.RENDERFLAGS_NET)   
            if res==c4d.RENDERRESULT_OK:   
                bitmaps.ShowBitmap(bmp)   
                thisFrame +=1   
                if thisFrame > endFrame: return   
                print "thisFrame: %s" % thisFrame   
                doRender(doc, rd, bmp, thisFrame, endFrame)   
      
        doRender(doc, rd, bmp, thisFrame, endFrame)   
           
        c4d.EventAdd()   
           
    if __name__=='__main__':   
        main()
    


  • On 08/11/2016 at 14:56, xxxxxxxx wrote:

    Doh! I missed that one. Sorry about that. I changed it.
    Those custom methods that you are creating using "def" don't go inside of the def main() : code block.
    They should be placed before, or after, the main code block. Then you call them as needed.
    Also. A script runs once then stops.
    So if you want to execute code more than once. You'll need to use a loop where the frame value increments every time the loop iterates.

    -ScottA

    Edit-
    After changing the code. I'm getting the feeling that you're still not going to get the results you are looking for. So take a look at this code example. It might help answer your questions better than trying to edit your code.
    Feel free to edit it to fit your needs.

    #This script rotates an object by a set amount. Then renders it to the path set in the render settings  
    #NOTE: The frame Range render setting in "Output" should be set to "Current Frame"  
    #The script will change the file name each time a new image is rendered to save the multiple images  
      
    import c4d, math  
    from c4d import bitmaps, documents, utils  
      
    ROTANGLE = 30.0  
    ROTVEC = c4d.Vector(utils.Rad(ROTANGLE), 0, 0)  
      
    def main() :  
      
      if op:  
          maxstep = int(math.floor(360.0 / ROTANGLE))  
          rd = doc.GetActiveRenderData().GetData()    #Gets the render settings  
          xres = int(rd[c4d.RDATA_XRES])              #Gets the X size value from the render settings  
          yres = int(rd[c4d.RDATA_YRES])              #Gets the Y size value from the render settings  
          fn = rd[c4d.RDATA_PATH]                     #Gets the file path from the render settings  
      
          bmp = bitmaps.BaseBitmap()                  #Create an instance of the bitmap class  
          bmp.Init(x=xres, y=yres, depth=24)          #Initialize it using the render settings  
      
          for i in xrange(maxstep) :  
              c4d.StatusSetSpin()  
              c4d.StatusSetText('Rendering image {0} of {1}.'.format(i, maxstep))  
      
              rd[c4d.RDATA_PATH] = '{0}_{1}'.format(fn, i)  #Adds a _SomeNumber to the end of the file path  
              filename = str(rd[c4d.RDATA_PATH])  
              result = documents.RenderDocument(doc, rd, bmp, c4d.RENDERFLAGS_EXTERNAL)  
              bmp.Save(filename + ".png", c4d.FILTER_PNG, c4d.BaseContainer(), c4d.SAVEBIT_ALPHA)  
      
              if result != c4d.RENDERRESULT_OK: break  #Error handling  
              else: bitmaps.ShowBitmap(bmp)  
      
              op.SetMg(op.GetMg() * utils.HPBToMatrix(ROTVEC))  #Rotate the active object by it's matrix  
      
      c4d.StatusClear()  
      c4d.EventAdd()  
        
    if __name__=='__main__':  
      main()
    

    -ScottA



  • On 08/11/2016 at 18:08, xxxxxxxx wrote:

    Good stuff. Thanks.

    I'll chip away at it some more.



  • On 08/11/2016 at 18:28, xxxxxxxx wrote:

    NP.
    Just be aware that your custom methods are a bit strange. I fixed them so that they would work by pulling them out of the main code block. But the setRenderFrame() method really doesn't make much sense to be used that way.
    I recommend not using any external methods like This. Or maybe just use one for all of the rendering code.
    Using custom methods and dealing with their parameters just adds more complexity to the code.
    That's just a suggestion though. Do whatever you want.

    That's all the help I can be with this. I can't help with the Team Render stuff.

    GoodLuck,
    -ScottA


Log in to reply