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

    EventAdd() doesn't update C4D

    PYTHON Development
    0
    25
    17.4k
    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 08/02/2013 at 06:19, xxxxxxxx wrote:

      You can also just automate the process of putting them under a null-object, run what the script
      currently does on the null-object (but with taking its children into account) and unpack the null-object
      again. Still better then redrawing the editor for each pass.

      If you don't want that workaround, you could also manage to offset the objects aiming for seperately,
      but this would be more code to write and less perfomant (because of Pythons slow iterations).

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

        On 08/02/2013 at 08:30, xxxxxxxx wrote:

        Originally posted by xxxxxxxx

        @Scott: You said, that scripts should not be used for this and that I should use a plugin instead. I'm quite open to that but I'm not really sure what the significant changes regarding your code will be. Can I use a complete new (and simpler) approach when using PlugIns? If so, what will it look like? I'm sorry if you had this question already answered, but I still have problems with that.

        A plugin or pytag is just the usual choice for this kind of thing. Because they can execute their code several times. Not just once.
        It's often an advantage to have this ability so you can compare things->move them->compare them again.

        Most people would probably use a plugin or a pytag for this task you're doing. And take advantage of that running several times thing to do a task like multiple comparisons and moves.
        But Niklas found a way to do this using a script that's just a s good as using a plugin or a pytag.
        Normally this kind of task isn't done with a script due to it's run once nature.
        But people who are clever (like Niklas) can often figure out a way to get around that problem.

        -ScottA

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

          On 12/02/2013 at 02:13, xxxxxxxx wrote:

          Hey guys!

          Thanks for your replies!
          I did some calculations the last days and it took me quite a while, because I got really confused about that many coordinate systems and matrices and vectors...
          Anyways, I managed to get a working code which did the repositioning of my camera in one calculation, without Redrawing or moving objects. It works pretty fine as long as the camera aims directly to the midpoint of the object (need to add an offset to the midpoint to the calculation) and the object is in front of the camera (not necessarily completly). So there is room for improvements 😉

            
          '''  
          Created on 12.02.2013  
          '''  
          import c4d  
          from c4d import documents  
          import math  
            
          def GetNewCameraPosition(cam, obj, doc) :  
            bd = doc.GetActiveBaseDraw()  
            safeFrame = bd.GetSafeFrame()  
            
            #Get the active object bounding box center and radius, including midpoint as last point  
            box = [c4d.Vector() for x in xrange(9)]  
            points = [c4d.Vector() for x in xrange(9)]  
            rd = obj.GetRad()  
            mp = obj.GetMp()  
            
            #Build the active object bounding box  
            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].x = mp.x - rd.x  
            box[1].y = mp.y + rd.y  
            box[1].z = mp.z - rd.z  
            box[1] *= obj.GetMgn()  
            
            box[2].x = mp.x + rd.x  
            box[2].y = mp.y - rd.y  
            box[2].z = mp.z - rd.z  
            box[2] *= obj.GetMgn()  
            
            box[3].x = mp.x + rd.x  
            box[3].y = mp.y + rd.y  
            box[3].z = mp.z - rd.z  
            box[3] *= obj.GetMgn()  
            
            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].x = mp.x + rd.x  
            box[5].y = mp.y + rd.y  
            box[5].z = mp.z + rd.z  
            box[5] *= obj.GetMgn()  
            
            box[6].x = mp.x - rd.x  
            box[6].y = mp.y - rd.y  
            box[6].z = mp.z + rd.z  
            box[6] *= obj.GetMgn()  
            
            box[7].x = mp.x - rd.x  
            box[7].y = mp.y + rd.y  
            box[7].z = mp.z + rd.z  
            box[7] *= obj.GetMgn()  
              
            box[8].x = mp.x  
            box[8].y = mp.y  
            box[8].z = mp.z  
            box[8] *= obj.GetMgn()  
              
            #convert bounding box points to Screenspace  
            for i in xrange(len(box)) :  
                points[i] = bd.WS(box[i])  
                          
            #looking for extreme points  
            minXIndex = maxXIndex = minYIndex = maxYIndex = minZIndex = maxZIndex = 0  
            minX = maxX = points[minXIndex][0]  
            minY = maxY = points[minYIndex][1]  
            minZ = maxZ = points[minZIndex][2]      
            for i in xrange(1, len(points) - 1) : #-1: Midpoint can never be an extreme point  
                if points[i][0] < minX:  
                    minX = points[i][0]  
                    minXIndex = i  
                if points[i][0] > maxX:  
                    maxX = points[i][0]  
                    maxXIndex = i  
                if points[i][1] < minY:  
                    minY = points[i][1]  
                    minYIndex = i  
                if points[i][1] > maxY:  
                    maxY = points[i][1]  
                    maxYIndex = i  
                if points[i][2] < minZ:  
                    minZ = points[i][2]  
                    minZIndex = i  
                if points[i][2] > maxZ:  
                    maxZ = points[i][2]  
                    maxZIndex = i  
              
            #if a pair of indices is equal than a calculation can't be done  
            if (minXIndex == maxXIndex) or (minYIndex == maxYIndex) or (minZIndex == maxZIndex) :  
                print 'At least one pair of indices are equal: minX {0}, maxX {1}, minY {2}, maxY {3}, minZ {4}, maxZ {5}\nAborting function'.format(minXIndex, maxXIndex, minYIndex, maxYIndex, minZIndex, maxZIndex)  
                return cam.GetMg().off  
              
            #calculate offset from midpoint to nearest extreme point in z direction in sight of cam    
            if points[minXIndex][2] <= points[maxXIndex][2]:  
                offsetX = math.fabs(points[8][2] - points[minXIndex][2])  
            else:  
                offsetX = math.fabs(points[8][2] - points[maxXIndex][2])  
              
            if points[minYIndex][2] <= points[maxYIndex][2]:  
                offsetY = math.fabs(points[8][2] - points[minYIndex][2])  
            else:  
                offsetY = math.fabs(points[8][2] - points[maxYIndex][2])  
              
            #calculate necessary distance between camera and extreme point  
            fd_x = ((box[maxXIndex] - box[minXIndex]).GetLength() / 2.0) / math.tan(cam[c4d.CAMERAOBJECT_FOV] / 2)  
            fd_y = ((box[maxYIndex] - box[minYIndex]).GetLength() / 2.0) / math.tan(cam[c4d.CAMERAOBJECT_FOV_VERTICAL] / 2)  
            
            #add the corresponding offset   
            fd_x += offsetX  
            fd_y += offsetY  
              
            #check if calculation went wrong (camera distance can't be negative),   
            # set the focus distance to distance to midpoint of bounding box    
            if fd_x > fd_y:  
                if fd_x <= 0:  
                    print 'fd_x smaller than 0'  
                    return cam.GetMg().off  
                cam[c4d.CAMERAOBJECT_TARGETDISTANCE] = fd_x  
            else:  
                if fd_y <= 0:  
                    print 'fd_y smaller than 0'  
                    return cam.GetMg().off  
                cam[c4d.CAMERAOBJECT_TARGETDISTANCE] = fd_y  
                  
            #calculate the new camera position  
            camMg = cam.GetMg()  
            camMgOff = obj.GetMg().off      
            camMgOff += camMg.v3.__neg__() * cam[c4d.CAMERAOBJECT_TARGETDISTANCE] #repositioning in negative z-axis   
                  
            return camMgOff  
              
            
          def main() :     
            doc = documents.GetActiveDocument()  
            cam = doc.SearchObject('Cam')  
            cube = doc.SearchObject('Cube')  
            
            camMg = cam.GetMg()  
            camMg.off = GetNewCameraPosition(cam, cube, doc)  
            cam.SetMg(camMg)  
              
            c4d.EventAdd()  
            
          if __name__ == '__main__':  
            main()
          

          Any recommandations on this code would be appreciated!

          Greetings Nachtmahr

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

            On 25/06/2015 at 05:46, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            You can also just automate the process of putting them under a null-object, run what the script
            currently does on the null-object (but with taking its children into account) and unpack the null-object
            again. Still better then redrawing the editor for each pass.
            ...

            How do i do that ?

            I am itterating through all objects at the moment and the result is the camera moves away way too far. (some cubes dimenson 200m camera moves to 246666m)

            I need to have my Null-Object with lots of objects inside to be full inside the rendersave frame. Is it posible to get a boundingbox from a Null-Object with its children taken into acount without iterationg through several thousand objects ?

            thanks in advance.

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

              On 27/06/2015 at 10:21, xxxxxxxx wrote:

              So I managed to add Niklas aabb Boundingbox Routine to your script but I am still getting weird results.

              sometimes nothing happens, passes = 0 even when something is not in view,
              sometimes it works kind of but the object is way to small in the midle,
              sometimes it runs forever in a loop

              can we get this as neat and tidy and better working than this "H"-Key in C4D?

              kind regrads mogh

              # Added Niklas Rosenstein AABB Utility to get the boundingbox of a Null-Object with its Children   
              # please note that you have to install it   
              # http://pythonhosted.org/c4dtools/   
              # https://github.com/NiklasRosenstein/c4dtools <- download from here   
                
              import c4d   
              from c4d import utils   
              import c4dtools.misc.aabb as aabb   
                
              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(obj, bd) :   
              def CheckIfInView(obj, rd, mp, bd) :          
                  safeFrame = bd.GetSafeFrame()   
                     
                  #Get the active object bounding box center and radius   
                  box = [c4d.Vector() for x in xrange(8)]   
                  #rd = obj.GetRad()   
                  #mp = obj.GetMp()   
                     
                  #print box, rd, mp   
                    
                  #Build the active object bouding box   
                  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].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].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].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].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].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].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].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   
                  points = [bd.WS(p) for p in box]   
                
                  #Test if the current object is completely visible in the rendered safe frame   
                  for i in xrange(len(points)) :   
                      if not TestPointInFrame(points[i], safeFrame) :   
                          return False   
                
                  return True   
                
              def MoveObjectRel(op, axis, offset) :   
                  axis = axis.GetNormalized()   
                  axis.off = op.GetRelPos()   
                  op.SetRelPos(axis * offset)   
                
              def EscapePressed(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() :   
                  c4d.CallCommand(13957) # Konsole löschen   
                  if not op:   
                      c4d.gui.MessageDialog("please select an object")   
                      return   
                
                  bd = doc.GetActiveBaseDraw()   
                  cam = bd.GetSceneCamera(doc)   
                  if op is cam:   
                      return MessageDialog("can not apply on the cam")   
                
                  campos = cam.GetAbsPos()   
                  pos = op.GetAbsPos()   
                  axis = cam.GetMg()   
                  offset = c4d.Vector(0, 0, 10)   
                
                  # Create an undo-state for the camera because we will offset it.   
                  doc.AddUndo(c4d.UNDOTYPE_CHANGE, cam)   
                  c4d.StatusSetSpin()   
                
                  passes = 0   
                  oppasses = 0   
                  stopped = False   
                     
                   # Added Niklas Rosenstein AABB Utility to get the boundingbox of a Null-Object with its Children   
                   # please note that you have to install it   
                   # http://pythonhosted.org/c4dtools/   
                   # https://github.com/NiklasRosenstein/c4dtools <- download from here   
                      
                  box = aabb.AABB()   
                  box.expand_object(op, recursive=True)   
                  print "AABB Values:"   
                  print "Size: ", box.size   
                  print "Midpoint: ", box.midpoint   
                     
                  mp = box.midpoint   
                  rd = box.size   
                     
                  #while not CheckIfInView(op, bd) :   
                  while not CheckIfInView(op, rd, mp, bd) : # pass aabb values to check routine   
                      stopped = EscapePressed()   
                      if stopped: break   
                        
                      MoveObjectRel(op, axis, offset)   
                      oppasses += 1   
                     
                  print "Check in view passes: ", oppasses   
                     
                  delta = op.GetAbsPos() - pos   
                  op.SetAbsPos(pos)   
                
                  if not stopped:   
                      campos -= delta   
                  cam.SetAbsPos(campos)   
                
                  c4d.StatusClear()   
                  c4d.EventAdd()   
                
              main()
              
              1 Reply Last reply Reply Quote 0
              • First post
                Last post