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