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

    Crash when running plugin on complex scene

    Scheduled Pinned Locked Moved PYTHON Development
    3 Posts 0 Posters 323 Views
    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 21/05/2016 at 10:25, xxxxxxxx wrote:

      Hello everybody,

      I made a preview plugin, which is basically a GeDialog with an UserArea.
      To render the document or the preview, I use a C4DThread. 
      It is working perfect when I have a simple scene (e.g only a cube, some lights)
      But as soon as I try to use my plugin with a bigger scene, more mesh etc. 
      Cinema 4D just crashes. There is a popup that says: "Application Error!" and then a path to the bugreport.
      My problem now is, 1. I don't know why Cinema is crashing and second I don't reall understand the Bugreport.

      This is the complete code that I use.

      import c4d
      from c4d import gui, plugins, utils, bitmaps, storage
      from c4d.threading import C4DThread
      import os
        
      PLUGIN_ID = 1037431
        
        
      b_calculate = 1000
      quality = 1010
      scale = 1020
      antislider = 10016
      Render_Image = bitmaps.BaseBitmap()
        
      calculating = False
      dis_width = 0
      dis_height = 0
      ww = 0
      hh = 0
      new_rd = None
      redraw = False
        
      class RenderDisplay(gui.GeUserArea) :
        
          def GetMinSize(self) :
              self.width = 250
              self.height = 250
              return (self.width, self.height)
          
          def __init__(self, bmp) :
              global dis_width
              global dis_height
              
              super(RenderDisplay, self).__init__()
              self.bmp = Render_Image
              dis_width = self.GetWidth()/100
              dis_height = self.GetHeight()/100
              
          def DrawMsg(self, x1, y1, x2, y2, msg_ref) :
              self.OffScreenOn()
              self.SetClippingRegion(x1, y1, x2, y2)
                
              Color = self.GetColorRGB(c4d.COLOR_BG)
              back_color = c4d.Vector(Color['r'] / 255.0, Color['g'] / 255.0, Color['b'] / 255.0)
                
              self.DrawSetPen(back_color)
              self.DrawRectangle(x1, y1, x2, y2)
                
              if self.bmp:
                  ww = self.bmp.GetBw()
                  hh = self.bmp.GetBh()
                  if ww > 0 and hh > 0:
                      self.DrawBitmap(self.bmp, 0, 0, self.GetWidth(), self.GetHeight(), 0, 0, ww, hh, c4d.BMP_NORMAL)
                      self.Redraw(True)
        
      class Render_Thread(c4d.threading.C4DThread) :
          def Main(self) :
              thread = self.Get()
              doc=c4d.documents.GetActiveDocument()
              Render_Image.Init(int(ww),int(hh),24)
              rend = c4d.documents.RenderDocument(doc ,new_rd, Render_Image, c4d.RENDERFLAGS_EXTERNAL|c4d.RENDERFLAGS_NODOCUMENTCLONE, thread)
              
      class DiffRender(c4d.gui.GeDialog) :
          thumbnail = RenderDisplay(None)
          thread = Render_Thread()
           
          def CreateLayout(self) :
              self.SetTitle("Owl View V2.3")
                
              self.AddUserArea(100000, c4d.BFH_CENTER | c4d.BFV_CENTER | c4d.BFH_SCALEFIT |c4d.BFV_SCALEFIT, 3, 3)
              self.AttachUserArea(self.thumbnail, 100000)
                
              self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT, title="", rows=4, cols=4,)
             
              self.AddEditSlider(id=quality, flags=c4d.BFH_SCALEFIT, initw=50, inith=12)
              self.AddStaticText(id=scale, flags=c4d.BFH_SCALEFIT | c4d.BFH_CENTER | c4d.BFV_CENTER, initw=120, inith=12, name="--- x ---")
              self.antislider = self.AddSlider(antislider, c4d.BFH_SCALEFIT, 1, 3)
              self.AddButton(b_calculate, c4d.BFH_SCALEFIT | c4d.BFH_CENTER | c4d.BFV_CENTER, initw=0, inith=0, name="Render")
              self.GroupEnd()
              return True
        
          def InitValues(self) :
              self.SetPercent(quality, 1, min=0.0, max=100.0, step=1.0, tristate=False)
                
              doc = c4d.documents.GetActiveDocument()
              rd = doc.GetActiveRenderData()
                
              ww = rd[c4d.RDATA_XRES_VIRTUAL]
              hh = rd[c4d.RDATA_YRES_VIRTUAL]
        
              qual = self.GetReal(quality)
              self.SetString(id=scale, value="( " + str(int(ww * qual)) + " x " + str(int(hh * qual)) + " )")
              
              calculating = True
              return True
        
          def Command(self, id, msg) :
              global calculating
              global anti
              global new_rd
              global ww
              global hh
              
              
              doc = c4d.documents.GetActiveDocument()
              
              self.qualsli = self.GetReal(quality)
              self.SetReal(quality, self.qualsli, min=0.01, max=1.0, step=0.01, format=c4d.FORMAT_PERCENT, min2=0.01, max2=1.0,  tristate=False)
              
              self.antsli = self.GetReal(antislider)
              self.SetReal(antislider, self.antsli, min=0.0, max=2.0, step=1.0, min2=0.0, max2=2.0, tristate=False)
              
          
              
              if id == quality:
                  rd = doc.GetActiveRenderData()
                  ww = rd[c4d.RDATA_XRES_VIRTUAL]
                  hh = rd[c4d.RDATA_YRES_VIRTUAL]
                  qual = self.GetReal(quality)
                  self.SetString(id=scale, value="( " + str(int(ww * qual)) + " x " + str(int(hh * qual)) + " )")
                  
                  
              if id == b_calculate:
                  calculating = True
                  self.thread.Start(mode=c4d.THREADMODE_ASYNC, priority=c4d.THREADPRIORITY_NORMAL)
                  anti = long(self.antsli)
                  rd=doc.GetActiveRenderData()
                  o_ww=rd[c4d.RDATA_XRES]
                  o_hh=rd[c4d.RDATA_YRES]
                  ww=int(o_ww*self.GetReal(quality))
                  hh=int(o_hh*self.GetReal(quality))
                  new_rd=doc.GetActiveRenderData().GetData()
                  new_rd[c4d.RDATA_XRES]=ww
                  new_rd[c4d.RDATA_YRES]=hh
                  if anti == 0:
                      new_rd[c4d.RDATA_ANTIALIASING] = 0
                      
                  if anti == 1: 
                      new_rd[c4d.RDATA_ANTIALIASING] = 1
                      
                  if anti == 2:
                      new_rd[c4d.RDATA_ANTIALIASING] = 2
                  
              return True
          
      class SimpleCC_CMD(c4d.plugins.CommandData) :
          dialog = None
          def Execute(self, doc) :
                if self.dialog is None:
                   self.dialog = DiffRender()
                return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaulth=270, defaultw=195)
        
          def RestoreLayout(self, sec_ref) :
                if self.dialog is None:
                   self.dialog = DiffRender()
                return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
        
      if __name__ == "__main__":
            bmp = bitmaps.BaseBitmap()
            dir, f = os.path.split(__file__)
            fn = os.path.join(dir, "res", "icon.tif")
            bmp.InitWith(fn)
            c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID, str="Owl View", help="A simple plugin to preview your scene", info=0, dat=SimpleCC_CMD(), icon=bmp)
      

      This code works similar to Nitromans Magic Preview, with the squares that shows you the render process, but since I implemented this feature, I get the crashes.

      Hopefully someone can help me 🙂

      greetings, 
      neon

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

        On 23/05/2016 at 08:44, xxxxxxxx wrote:

        Hi neon,

        it looks like you have some severe threading issue. At least when I tried it here in a debugger, I found some evidence of trashed memory.
        I hope you don't mind, we can't debug this for you.

        Some stuff you are doing definitely looks fishy. Not saying any one is the reason for your problem, nor do I think my list is complete. This is just the stuff, that occurred to me immediately:

        You store global RenderData in new_rd. You modify this after you have started the thread, which is using it. Most likely a bad idea and in best case your thread is only working on inconsistent RenderData.

        Similar with the BaseBitmap you are rendering into. One thread renders into the bitmap, while another reads it in order to display it in the dialog. I would have said, this might work out, if you only changed the bitmap, but you are re-initializing the BaseBitmap from your thread, which has some chance of relocating the image in memory...

        I'm also not sure it's a good idea to call Redraw() from DrawMsg(). I'd rather do it the other way round and trigger the redraw from your render thread, like it's done int the Py-MemoryViewer example.

        I know, this is probably not the answer you have waited for, but perhaps it still helps.

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

          On 23/05/2016 at 10:05, xxxxxxxx wrote:

          Hello Andreas,

          Thanks for your reply!

          Your reply did help me alot, I changed some things like the Redraw call and the RenderData (I really feel kinda dumb about that, should have seen this myself).
          And It is not crashing anylonger. I have not started in debugging my code for memory leaks, but as far as I can tell, it doesn't seem to have big issues.

          But I am very greatfull for your help and your time you invested! 
          I am now trying to debug it myself and see if I can do something about the trashed memory you mentioned (if there is still any, changed almost all my code ^^)

          greetings, 
          neon

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