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

    Render to Picture Viewer and RenderDocument woes

    PYTHON Development
    0
    16
    1.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.
    • H
      Helper
      last edited by

      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.

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

        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://developers.maxon.net/forum/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

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

          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

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

            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()

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

              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

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

                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

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

                  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

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

                    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

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

                      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

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

                        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

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

                          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

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

                            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?

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

                              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

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

                                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

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

                                  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

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

                                    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

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