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
    1. Maxon Developers Forum
    2. AndreAnjos
    3. Best
    A
    • Profile
    • Following 0
    • Followers 0
    • Topics 18
    • Posts 85
    • Best 1
    • Controversial 0
    • Groups 0

    Best posts made by AndreAnjos

    • RE: Frame selected objects correctly in camera

      Hi all,

      Apologies for the delay, but only had time to revisit this issue this week.
      So I found the solution and thought about posting here for other people. It's probably not the best one, but it works for me and I'm happy with the final results.

      Like to thank Niklas, Scott and Riccardo for helping with this, as a lot of the information came from them, which I just adapted.
      So this is developed to render with Octane, but you can change to whatever render settings you need.

      """
      The script is a blend of techniques that I found to be working at the end.
      It starts by getting all of the polygon object in the scene, iterating through each object and soloing it in a layer.
      Creates the objects, camera, materials and render settings for the environment.
      Focus the object first before calculating if all of the object is in the scene.
      Because the camera has a target tag connected to a moving null that sits under each object is rendering, the position reaches a conclusion when object is inside the camera frame.
      I didn't want to create a new thread to run the script as I prefer the user not be using cinema and let it run. We can't afford to have Cinema crashing at the same time.
      """
      
      import c4d
      
      def get_op(op, name):
      
          while op:
              if op.GetName() == name:
      
                  return op
      
              get_op(op.GetDown(), name)
              op = op.GetNext()
              
      def get_mat(op, name):
      
          while op:
              if op.GetName() == name:
      
                  return op
      
              get_op(op.GetDown(), name)
              op = op.GetNext()
              
      def get_op_type(op, name, lst):
      
          while op:
              if op.GetTypeName() == name:
      
                  lst.append(op)
      
              get_op_type(op.GetDown(), name, lst)
              op = op.GetNext()
      
          return lst
              
      def get_vp(op, name):
      
          while op:
              if op.GetName() == name:
      
                  return op
      
              op = op.GetNext()
              
      def create_obj(op_type, name):
          
          op = c4d.BaseObject(op_type)
          op.SetName(name)
          doc.InsertObject(op)
          
          return op
      
      def create_render(doc):
          
          rd = c4d.documents.RenderData()
          doc.InsertRenderData(rd)
          doc.SetActiveRenderData(rd) 
          rd.SetName('Temp_BP')
          rd[c4d.RDATA_RENDERENGINE] = 1029525
          oct_render_vp = c4d.documents.BaseVideoPost(1029525)
          rd.InsertVideoPost(oct_render_vp)
          rd[c4d.RDATA_XRES] = 540
          rd[c4d.RDATA_YRES] = 540
          rd[c4d.RDATA_LOCKRATIO] = True
          rd[c4d.RDATA_FILMASPECT] = 1.0
          rd[c4d.RDATA_FRAMESEQUENCE] = 1
          rd[c4d.RDATA_FRAMERATE] = 24
      
          # Save
          rd[c4d.RDATA_GLOBALSAVE] = True
          rd[c4d.RDATA_SAVEIMAGE] = True
          rd[c4d.RDATA_FORMAT] = c4d.FILTER_PNG
          rd[c4d.RDATA_NAMEFORMAT] = 6
          rd[c4d.RDATA_FORMATDEPTH] = 1
          
          # Octane Renderer
          oct_render_vp[c4d.SET_PASSES_ENABLED] = False
          oct_render_vp[c4d.VP_UPDATE_MATERIALS_MODE] = False
          oct_render_vp[1013] = 0
          oct_render_vp[c4d.VP_BUFFER_TYPE] = 2
          
          oct_render_vp[c4d.VP_KERNEL_ENABLE] = True
          oct_render_vp[c4d.SET_DIRECT_MAXSAMPLES] = 1000
          oct_render_vp[c4d.SET_DIRECT_SPECDEPTH] = 3
          oct_render_vp[c4d.SET_DIRECT_AODIST] = 0.3
          oct_render_vp[c4d.SET_DIRECT_ALPHACHAN] = True
          oct_render_vp[c4d.SET_DIRECT_KEEPENV] = False
          oct_render_vp[c4d.SET_DIRECT_ADAPTIVE_SAMPLING] = True
          oct_render_vp[c4d.SET_DIRECT_ASAMP_EXP_EXPOSURE] = 1.0
          
          # Watermark
          watermark_vp = c4d.documents.BaseVideoPost(1025462)
          rd.InsertVideoPostLast(watermark_vp)
          watermark_vp[c4d.VP_WATERMARK_TEXT_ENABLE] = True
          watermark_vp[c4d.VP_WATERMARK_TEXT_SHOWLABELS] = False
          watermark_vp[c4d.VP_WATERMARK_TEXT_RENDERTIME] = False
          watermark_vp[c4d.VP_WATERMARK_TEXT_DATE] = False
          watermark_vp[c4d.VP_WATERMARK_TEXT_BG_OPACITY] = 1.0
          
          rd.Message(c4d.MSG_UPDATE)
          
          return (rd, watermark_vp)
      
      def TestPointInFrame(pt, frame):
          
          return pt.x > frame['cl'] and pt.x < frame['cr'] and pt.y > frame['ct'] and pt.y < frame['cb']  
          
      def CheckIfInView(cam, obj, doc):
          # Get the current BaseDraw  
          bd = doc.GetActiveBaseDraw()  
          safeFrame = bd.GetSafeFrame()  
              
          # Get the active object bouding box center and radius  
          
          box = [c4d.Vector() for x in xrange(8)]  
          points = [c4d.Vector() for x in xrange(8)]          
          
          
          rd = obj.GetRad()  
          mp = obj.GetMp()  
          
          # Build the active object bouding box  
          
          box[0] = c4d.Vector()  
          box[0].x = mp.x - rd.x  
          box[0].y = mp.y - rd.y  
          box[0].z = mp.z - rd.z  
          box[0] *= obj.GetMgn()  
          
          box[1] = c4d.Vector()  
          box[1].x = mp.x - rd.x  
          box[1].y = mp.y + rd.y  
          box[1].z = mp.y - rd.z  
          box[1] *= obj.GetMgn()  
          
          box[2] = c4d.Vector()  
          box[2].x = mp.x + rd.x  
          box[2].y = mp.y - rd.y  
          box[2].z = mp.y - rd.z  
          box[2] *= obj.GetMgn()  
          
          box[3] = c4d.Vector()  
          box[3].x = mp.x + rd.x  
          box[3].y = mp.y + rd.y  
          box[3].z = mp.y - rd.z  
          box[3] *= obj.GetMgn()  
          
          box[4] = c4d.Vector()  
          box[4].x = mp.x + rd.x  
          box[4].y = mp.y - rd.y  
          box[4].z = mp.z + rd.z  
          box[4] *= obj.GetMgn()  
          
          box[5] = c4d.Vector()  
          box[5].x = mp.x + rd.x  
          box[5].y = mp.y + rd.y  
          box[5].z = mp.y + rd.z  
          box[5] *= obj.GetMgn()  
          
          box[6] = c4d.Vector()  
          box[6].x = mp.x - rd.x  
          box[6].y = mp.y - rd.y
          box[6].z = mp.y + rd.z
          box[6] *= obj.GetMgn()  
          
          box[7] = c4d.Vector()  
          box[7].x = mp.x - rd.x
          box[7].y = mp.y + rd.y
          box[7].z = mp.y + rd.z
          box[7] *= obj.GetMgn()
          
          # Calculate bouding box coordinates in screen space  
          
          for i in xrange(len(box)):
            points[i] = bd.WS(box[i])  
          
          # Test if the current object is completely visible in the rendered safe frame  
          
          for i in xrange(len(points)):
            visible = TestPointInFrame(points[i], safeFrame)  
            if not visible:
                break  
              
          return visible
      
      def escaped_pressed(bc=None):
          if bc is None:
              bc = c4d.BaseContainer()
              c4d.gui.GetInputEvent(c4d.BFM_INPUT_KEYBOARD, bc)
          return bc[c4d.BFM_INPUT_CHANNEL] == c4d.KEY_ESC
      
      def main():
          
          doc = c4d.documents.GetActiveDocument()
          first_obj = doc.GetFirstObject()
          first_mat = doc.GetFirstMaterial()
          sku_layer = first_obj.GetLayerObject(doc)
          objs_lst = get_op_type(first_obj, 'Polygon', [])
          count_total = len(objs_lst)
          
          rs, water_vp = create_render(doc)
          
          cam = get_op(first_obj, 'Temp_Cam')
          bg = get_op(first_obj, 'BG')
          mat = get_mat(first_mat, 'BG_Mat')
          trg_null = get_mat(first_mat, 'Cam_Target')
          
          if cam == None:
              
              cam = create_obj(c4d.Ocamera, 'Temp_Cam')
              oct_cam_tag = cam.MakeTag(1029524)  # Octane Camera tag
              oct_cam_tag[c4d.OCTANECAMERA_ENABLE_IMAGER] = True
              oct_cam_tag[c4d.OCTANECAMERA_PREMALPHA] = True
              trg_tag = cam.MakeTag(c4d.Ttargetexpression)
              
              if trg_null == None:
                  
                  trg_null = create_obj(c4d.Onull, 'Cam_Target')
                  trg_tag[c4d.TARGETEXPRESSIONTAG_LINK] = trg_null
              
          if bg == None:
              
              bg = create_obj(c4d.Obackground, 'BG')
              tex_tag = bg.MakeTag(c4d.Ttexture)
              
              if mat == None:
                  
                  mat = c4d.BaseMaterial(1029501)
                  mat.SetName('BG_Mat')
                  shader = c4d.BaseList2D(1011100)
                  shader[c4d.SLA_GRADIENT_TYPE] = 2002  # Type 2D - Diagonal
                  grad = shader[c4d.SLA_GRADIENT_GRADIENT]
                  grad.FlushKnots()
                  k1 = grad.InsertKnot(col=c4d.Vector(0.5, 0.5, 0.5), pos=0.25, index = 0)
                  k2 = grad.InsertKnot(col=c4d.Vector(0.25, 0.25, 0.25), pos=0.75, index= 1)
                  shader[c4d.SLA_GRADIENT_GRADIENT] = grad
                  mat[c4d.OCT_MATERIAL_DIFFUSE_LINK] = shader
                  mat.InsertShader(shader)
                  mat.Message(c4d.MSG_UPDATE)  # Update the material changes  
                  mat.Update(True, True)  # Update the material's icon image  
                  doc.InsertMaterial(mat)
                  tex_tag.SetMaterial(mat)
              
          bd = doc.GetActiveBaseDraw()
          bd.SetSceneCamera(cam)
          
          root_layer = doc.GetLayerObjectRoot()
          child_layer = root_layer.GetDown()
          layer = None
          
          while child_layer:
              
              if child_layer.GetName() == 'Temp_Layer':
                  
                  layer = child_layer
                  break
                      
              child_layer = child_layer.GetNext()
          
          if not layer:
              
              layer = c4d.documents.LayerObject()
              layer.SetName('Temp_Layer')
              layer.InsertUnder(root_layer)
          
          cam.SetLayerObject(layer)
          bg.SetLayerObject(layer)
          hdri = get_op(first_obj, 'HDRI')
          hdri.SetLayerObject(layer)
          
          subd_lst = get_op_type(first_obj, 'Subdivision Surface', [])
          
          for subd in subd_lst:
          
              subd.SetLayerObject(layer)
      
          if not objs_lst:
              
              c4d.gui.MessageDialog('No polygon objects in the scene!')
              c4d.StatusSetText('No polygon objects in the scene!')
              return False
          
          for count, obj in enumerate(objs_lst[:10], start=1):
              
              rad_x = obj.GetRad().x * 2
              rad_y = obj.GetRad().y * 2
              rad_z = obj.GetRad().z * 2
              
              water_vp[c4d.VP_WATERMARK_TEXT_CUSTOM_TEXT] = 'Dimensions(cm): (H){0:.2f} x (W){1:.2f} x (D){2:.2f}'.format(rad_x, rad_y, rad_z)
              
              trg_null.Remove()
              trg_null.InsertUnder(obj)
              doc.SetActiveObject(obj)
              obj.SetLayerObject(layer)
              obj.SetRenderMode(c4d.MODE_ON)
              layer_data = layer.GetLayerData(doc)
              layer_data['solo'] = True
              layer.SetLayerData(doc,layer_data)
              doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET)
              c4d.CallCommand(12151)
              doc.SetActiveObject(None)
              cam.Message(c4d.MSG_UPDATE)
              
              scaleFactor = c4d.Vector(15, 15, cam.GetMg().off.z)   # <---- Change the vector values for camera position.
              scaleFactor = scaleFactor.__mul__(0.05)
              
              stopped = False
              c4d.StatusSetSpin()
          
              while not CheckIfInView(cam, obj, doc):
                  
                  camMg = cam.GetMg()  
                  camMgOff = camMg.off  
                  camMgOff += scaleFactor  
                  camMg.off = camMgOff  
                  cam.SetMg(camMg)
                  c4d.DrawViews(c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_FORCEFULLREDRAW)
                  
                  stopped = escaped_pressed()
                  if stopped:
                      break
                      
              render_set = doc.GetFirstRenderData()
              parent_name = obj.GetUp().GetName()
              obj_name = '{0}_{1}_{2}'.format(doc.GetDocumentName().split('.')[0], parent_name, obj.GetName())
              render_set[c4d.RDATA_PATH] = '../Renders/{0}'.format(obj_name)    # <----- Make sure to correct File Path
          
              rs = render_set.GetData()
              x_res = int(rs[c4d.RDATA_XRES])
              y_res = int(rs[c4d.RDATA_YRES])
          
              bmp = c4d.bitmaps.BaseBitmap()
              bmp.Init(x=x_res, y=y_res, depth=24)
              c4d.documents.RenderDocument(doc, rs, bmp, c4d.RENDERFLAGS_EXTERNAL)
              
              bd.Message(c4d.MSG_CHANGE)
              obj.SetRenderMode(c4d.MODE_UNDEF)
              obj.SetLayerObject(sku_layer)
              cam.SetAbsPos(c4d.Vector(0))
              
              c4d.StatusClear()
              print('{0} / {1} - {2} - Render Done!'.format(count, count_total, obj.GetName()))
              c4d.StatusSetText('{0} / {1} - {2} - Render Done!'.format(count, count_total, obj.GetName()))
          
          layer.Remove()     
          doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_CLEAR)
          cam.Remove()
          trg_null.Remove()
          bg.Remove()
          mat.Remove()
          doc.GetFirstRenderData().Remove()
          
          for subd in subd_lst:
      
              subd.SetLayerObject(sku_layer)
      
          c4d.EventAdd()
          c4d.gui.MessageDialog('Renders Done!')
          c4d.StatusSetText('Renders Done!')
        
      main()
      

      Hope this helps and please let me know if we can make this better ☺ . (Which I'm sure we can!)

      Thank you!

      Andre

      posted in Cinema 4D SDK
      A
      AndreAnjos