Render to Picture Viewer and RenderDocument woes



  • On 03/11/2014 at 17:20, xxxxxxxx wrote:

    c4d.CallCommand(12099) # Render to Picture Viewer

    I would like to re-create the command above. However, this

    doc = documents.GetActiveDocument ()
    rd = doc.GetActiveRenderData ()
    rdata = rd.GetData ()
    xres = int ( rdata[ c4d.RDATA_XRES ] )
    yres = int ( rdata[ c4d.RDATA_YRES ] )
    bmp = bitmaps.BaseBitmap ()
    bmp.Init ( x = xres, y = yres )
    res = c4d.documents.RenderDocument( doc, rdata, bmp, renderflags = c4d.RENDERFLAGS_EXTERNAL, th = None )
    if res == c4d.RENDERRESULT_OK:
            bitmaps.ShowBitmap ( bmp )

    will lock up Cinema until the render finishes. I have tried the other options with the render flags, and can't seem to get more than a frame to render ( or save for that matter ). I have noticed with the c4d.RENDERFLAGS_EXTERNAL flag, it will render out the sequence, but it will look strange in the picture viewer ( also, no multipass files are shown ).

    So I've decided to just use the CallCommand in the beginning of the script, then have the rest of the code run after that. At least it will render correctly. However, that CallCommand must run in a separate thread because the rest of my code will execute before the render even starts.

    I would like:
    Step 1: render
    Step 2: run remaining code.

    I've looked into c4d.CheckIsRunning ( c4d.CHECKISRUNNING_EXTERNALRENDERING )
    and that doesn't seem to do anything with the CallCommand. It will return True, execute the rest of the code, then run the CallCommand.

    I've scoured the internet looking for similar posts and have not run into any.

    Sigh, I am at a loss. Maybe I'm missing something obvious or maybe I just don't understand.
    Any help would be appreciated.



  • On 04/11/2014 at 01:00, xxxxxxxx wrote:

    Hi,

    the callcommand should run in the main thread, but your other tasks (remaining code) can run in a separate user thread.
    Therefore you need to let wait, until your rendering is finished.
    You can use c4d.CheckIsRunning ( c4d.CHECKISRUNNING_EXTERNALRENDERING ).
    Start your call command, check if it is running, if this is true start a new thread.
    within this thread make a while loop where you again check if the render is running.
    When you while loop is finished you can run the rest of your code inside the userthread.

    Additionally you may have a look at this post.
    There was the same problem with the bake texture command.
    at crossroadtraffic
    https://plugincafe.maxon.net/topic/8218/10711_hidden-tag--operation-complete--solved

    If this wont help you let me know, than I´ll post  a snippet.

    Best wishes
    Martin



  • On 04/11/2014 at 07:48, xxxxxxxx wrote:

    I think that CallCommand() renders to a temp document. Which is why you can keep working on your current scene.
    If you write this code by hand. Try using a temp doc (in memory) as the rendering document instead of your active document.
    Be sure to target the temp doc in your code rather than using GetActiveDocument().
    Most people make that mistake.

    -ScottA



  • On 04/11/2014 at 14:22, xxxxxxxx wrote:

    Alrighty!
    Thank you guys for your help. I was able to get it working with the CallCommand() and running the rest of the script in a separate thread.
    I'll post a truncated version of the working code, just in case someone else runs into this issue.

    import c4d, thread, time

    def someFunction ( renderCheck, time ) :
        while renderCheck == True:
            time.sleep( 5 ) # waits 5 seconds before running rest of loop
            renderCheck = c4d.CheckIsRunning ( c4d.CHECKISRUNNING_EXTERNALRENDERING )
            print 'Checking if render is still rendering'    # still part of the while loop
        print 'Render is done'    # outside of the while loop

    def main () :
        c4d.CallCommand (12099) # calls the renderer
            renderCheck = c4d.CheckIsRunning ( c4d.CHECKISRUNNING_EXTERNALRENDERING )
            if renderCheck == True:
                thread.start_new ( someFunction, ( renderCheck, time ) )

    if __name__=='__main__':
        main()



  • On 04/11/2014 at 14:49, xxxxxxxx wrote:

    Hi Herbie,

    great, that it is working for you!
    Your code look like the suggestion, but there is no need to pass the rendercheck to your User Thread function.
    A simpler version:

      
    import c4d  
      
    import os,time, thread  
      
      
    def isRendering(time,os) :  
      
      print(time.ctime())  
      
      while c4d.CheckIsRunning ( c4d.CHECKISRUNNING_EXTERNALRENDERING ) :  
          print("render in progress...")  
      
          time.sleep(4)  
        
      print(time.ctime())  
      print("render complete.")   
      
      
    def main() :  
      
        
      c4d.CallCommand(12099)  
        
      if c4d.CheckIsRunning ( c4d.CHECKISRUNNING_EXTERNALRENDERING ) :  
          thread.start_new(isRendering,(time,os))  
      
    if __name__=='__main__':  
      main()  
      
    

    @scott
    I´m also really interested in your suggestion!
    I thought that the c4d.documents.RenderDocument command will render from a temp doc anyway?
    Except you set RENDERFLAG_NODOCUMENTCLONE.
    The problem is, that if you start the rendering from the main thread with c4d.documents.RenderDocument
    the main thread is blocked and busy, too.
    If you start it from a userthread, it´ll render in the background and you can edit your scene.
    But if it comes to the bitmaps.ShowBitmap(bitmap) part, you´ll get this Error message.
    RuntimeError: illegal operation, invalid cross-thread call.
    It seems to me, that ShowBitmap must be called from the main thread?

    If you or anybody else has an explanation or a working example to share, I´ll be very glad!
    Best wishes
    Martin



  • On 04/11/2014 at 16:16, xxxxxxxx wrote:

    I'm not having any trouble running code in the script manager. Or editing the scene while the renderer is running without using a custom thread.
    The only thing that happens is that the timeline scrubber and the ShowBitmap() output freezes in the PV window. But the renderer is still rendering the scene.

    Is that what you're talking about?
    Can you post an example of starting the render from a thread?

    -ScottA



  • On 04/11/2014 at 16:34, xxxxxxxx wrote:

    That sounds promissing ! Could you please show a working example?

    This is what I´m trying with a userthread:

      
    import c4d  
    from c4d import gui,bitmaps  
    from c4d.threading import C4DThread  
      
      
      
    class UserThread(C4DThread) :  
        
      def Main(self) :  
            
          doc = c4d.documents.GetActiveDocument ()  
          doc2 = doc.GetClone()  
          rd = doc2.GetActiveRenderData ()  
          rdata = rd.GetData ()  
          xres = int ( rdata[ c4d.RDATA_XRES ] )  
          yres = int ( rdata[ c4d.RDATA_YRES ] )  
        
          bmp = bitmaps.BaseBitmap ()  
          bmp.Init ( x = xres, y = yres )  
        
          print c4d.threading.GeGetCurrentThreadCount()  
          print c4d.threading.GeGetCurrentThread()  
          thr = c4d.threading.GeGetCurrentThread()  
          res = c4d.documents.RenderDocument( doc2, rdata, bmp, renderflags = c4d.RENDERFLAGS_EXTERNAL, th = thr )  
          print res  
          if res == c4d.RENDERRESULT_OK:  
              print res  
              bitmaps.ShowBitmap ( bmp )  
      
            
          pass  
      
      
    thread = UserThread()  
    thread.Start()  
    def main() :  
      
      print "the main"  
      
      
      
      
    if __name__=='__main__':  
      main()  
      
      
    

    Thanks in advance
    Martin



  • On 04/11/2014 at 18:08, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    That sounds promissing ! Could you please show a working example?

    What I'm saying is that I don't use custom threads when rendering and working at the same time.
    They don't seem to be necessary.

    When c4d.CallCommand (12099) is executed. I can still run scripts and work in the scene while it's rendering. There should be no problem doing both at the same time.
    The only down side is that the scrubber and the image preview are frozen when doing that.
    Rendering seems to be fully threaded and automatically handled by C4D.
    However, things like the scrubber and the preview image don't.

    The only code example I have is for C++. But it doesn't use threads or the RenderDocument() function.
    Both of those things seem to be problematic when trying to render while working on the scene at the same time. Which is why I asked to see your code.
    I haven't had much luck with using custom threads while rendering.

    -ScottA



  • On 05/11/2014 at 03:09, xxxxxxxx wrote:

    Thanks Scott, if you like, you can send me a pm with the c++ code?

    The call command handles all the threading operations and nothing is blocked and you can run your script, for sure. (not even the scrubber)

    Herbie was asking for running his code after the rendering, I guess.

    Originally posted by xxxxxxxx

    So I've decided to just use the CallCommand in the beginning of the script, then have the rest of the code run after that.

    And I was asking for manage it without using a call command with the RenderDocument() function.
    But yea, you can get grafic driver errors and other fancy stuff, with trying that one in a Userthread.

    On the other hand, if you try it in the main function of your script everything is blocked.

    Could anyone please confirm that it is not possible in python to re-create the c4d.CallCommand (12099)?

    Thanks in advance
    Martin



  • On 05/11/2014 at 07:59, xxxxxxxx wrote:

    Sure. I can post it here.
    It's very small.

    //This is how to render the scene to a temporary document while working on the scene  
    //Instead of loading a new document. You create a clone of it  
      
      Filename name = doc->GetDocumentName();    //Gets the name & extension  of the document without the path  
      Filename path = doc->GetDocumentPath();    //Gets the file's path, minus the file's name and extension  
      String fullPath = path.GetString() + "\\" + name.GetString();   //Combine them to get the full file path  
      
      //Save the scene before we open it back up and render it  
      //This lets us change the scene and get accurate rendering results  
      SaveDocument(doc, fullPath, SAVEDOCUMENTFLAGS_0, FORMAT_C4DEXPORT);  
      
      //Open the scene   
      BaseDocument *docCopy = LoadDocument(fullPath, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS, NULL);  
      
      //Insert the scene into the CINEMA editor list of documents  
      InsertBaseDocument(docCopy);  
      SetActiveDocument(docCopy);  
      CallCommand(12099);        //Render to picture viewer  
      KillDocument(docCopy);
    

    -ScottA



  • On 06/11/2014 at 05:25, xxxxxxxx wrote:

    Thanks Scott!

    I thought you might have a c++ kernel level threading example, which shows what´s behind the callcommand 😄,
    Anyway, in this case and in python I´m fine with the callcommand.

    Best wishes
    Martin



  • On 07/11/2014 at 04:35, xxxxxxxx wrote:

    Hi
    _<_t_>_
    English »
    | < id="SL_lng_to">< value="af">Afrikaans< value="sq">Albanian< value="ar">Arabic< value="hy">Armenian< value="az">Azerbaijani< value="eu">Basque< value="bn">Bengali< value="be">Belarusian< value="bg">Bulgarian< value="ca">Catalan< value="zh-CN">Chinese (Simp)< value="zh-TW">Chinese (Trad)< value="hr">Croatian< value="cs">Czech< value="da">Danish< value="nl">Dutch< value="en">English< value="eo">Esperanto< value="et">Estonian< value="tl">Filipino< value="fi">Finnish< value="fr">French< value="gl">Galician< value="ka">Georgian< value="de">German< value="el">Greek< value="gu">Gujarati< value="ht">Haitian Creole< value="iw">Hebrew< value="hi">Hindi< value="hu">Hungarian< value="is">Icelandic< value="id">Indonesian< value="ga">Irish< value="it">Italian< value="ja">Japanese< value="kn">Kannada< value="ko">Korean< value="lo">Lao< value="la">Latin< value="lv">Latvian< value="lt">Lithuanian< value="mk">Macedonian< value="ms">Malay< value="mt">Maltese< value="no">Norwegian< value="fa">Persian< value="pl">Polish< value="pt">Portuguese< value="ro">Romanian< value="ru">Russian< value="sr">Serbian< value="sk">Slovak< value="sl">Slovenian< ed="" value="es">Spanish< value="sw">Swahili< value="sv">Swedish< value="ta">Tamil< value="te">Telugu< value="th">Thai< value="tr">Turkish< value="uk">Ukrainian< value="ur">Urdu< value="vi">Vietnamese< value="cy">Welsh< value="yi">Yiddish|  |
    |
    |
    |
    | |
    <_<_t_>_
    Options : History : Help : Feedback
    Text-to-speech function is limited to 100 characters
    I ask the question here not to start a new topic.
    I need begin rendering immediately after the start of C4D project.
    I can't use c4d.CallCommand (12099) or bitmaps commands because in this case need to move the slider on the timeline. How to run a render immediately after opening the file?



  • On 07/11/2014 at 05:41, xxxxxxxx wrote:

    Hi,

    I actually can´t see a reason, why this code should not run properly and why the callcommand should freeze your timeline.
    Could you please give it a try and report if something goes wrong?

    EDIT
    sorry forgot the scenefilters, fixed.

      
    import c4d,os  
      
      
    def main() :  
      
      filename = c4d.storage.LoadDialog(c4d.FILESELECTTYPE_SCENES)  
      if not filename or not os.path.isfile(filename) :  
          return  
       
      doc = c4d.documents.LoadDocument(filename, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS | c4d.SCENEFILTER_DIALOGSALLOWED | c4d.SCENEFILTER_PROGRESSALLOWED | c4d.SCENEFILTER_NONEWMARKERS | c4d.SCENEFILTER_SAVECACHES)  
      
      c4d.documents.InsertBaseDocument(doc)  
      c4d.documents.SetActiveDocument(doc)  
      c4d.EventAdd()  
      c4d.CallCommand (12099)   
      
    if __name__=='__main__':  
      main()  
      
    

    Best wishes
    Martin



  • On 07/11/2014 at 07:28, xxxxxxxx wrote:

    The Picture Viewer window has it's own timeline.
    And if you are changing your scene while rendering. The timeline in that PV window does indeed freeze. And so does the image history images. And so does the preview window image.
    Basically. Everything in the PV freezes.

    However. The rendering is still running in the background. And as soon as you stop changing the scene. All of the rendered images will be dumped from memory into the PV. And the PV timeline will unfreeze and jump to the same frame as the frame being rendered.

    This is what I meant when I said that the rendering sems to be threaded, and handled automatically by C4D. But things like ShowBitmap() are not.

    It might be possible to get each bitmap that is rendered by using a GeDialog plugin and a custom thread. Combined with SpecialEventAdd() to send out a signal to it's CoreMessage() method. Then ask for the bitmap in the CoreMessage() method.
    This is the workaround mentioned in the C++ docs under: Important Threading Information

    -ScottA



  • On 07/11/2014 at 12:35, xxxxxxxx wrote:

    Thanks again Scott!
    for clarification this time
    and the hint with the c++ docs, interesting.

    Best wishes
    Martin



  • On 12/11/2014 at 00:27, xxxxxxxx wrote:

    Thanks for answers!
    _<_t_>_
    English »
    | < id="SL_lng_to">< value="af">Afrikaans< value="sq">Albanian< value="ar">Arabic< value="hy">Armenian< value="az">Azerbaijani< value="eu">Basque< value="bn">Bengali< value="be">Belarusian< value="bg">Bulgarian< value="ca">Catalan< value="zh-CN">Chinese (Simp)< value="zh-TW">Chinese (Trad)< value="hr">Croatian< value="cs">Czech< value="da">Danish< value="nl">Dutch< value="en">English< value="eo">Esperanto< value="et">Estonian< value="tl">Filipino< value="fi">Finnish< value="fr">French< value="gl">Galician< value="ka">Georgian< value="de">German< value="el">Greek< value="gu">Gujarati< value="ht">Haitian Creole< value="iw">Hebrew< value="hi">Hindi< value="hu">Hungarian< value="is">Icelandic< value="id">Indonesian< value="ga">Irish< value="it">Italian< value="ja">Japanese< value="kn">Kannada< value="ko">Korean< value="lo">Lao< value="la">Latin< value="lv">Latvian< value="lt">Lithuanian< value="mk">Macedonian< value="ms">Malay< value="mt">Maltese< value="no">Norwegian< value="fa">Persian< value="pl">Polish< value="pt">Portuguese< value="ro">Romanian< value="ru">Russian< value="sr">Serbian< value="sk">Slovak< value="sl">Slovenian< ed="" value="es">Spanish< value="sw">Swahili< value="sv">Swedish< value="ta">Tamil< value="te">Telugu< value="th">Thai< value="tr">Turkish< value="uk">Ukrainian< value="ur">Urdu< value="vi">Vietnamese< value="cy">Welsh< value="yi">Yiddish|  |
    |
    |
    |
    | |
    <_<_t_>_
    Options : History : Help : Feedback
    Text-to-speech function is limited to 100 characters


Log in to reply