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 05/02/2013 at 01:03, xxxxxxxx wrote:

      Hi Nachtmar,
      I found this very useful, maybe it will help you too. I was fighting with positions etc. until I dound this:
      http://www.nerdingoff.com/2012/02/c4d-python-matrix-basics-helper.html
       
      -Ingvar

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

        On 05/02/2013 at 09:52, xxxxxxxx wrote:

        You may not want it to be incremental. But that's how your code is set up.🙂
        Your code has a while loop in it that moves the camera if the object is not within the safeFrame view.

        The code that Yannick provided requires this kind of workflow to use it:
        -Check if object is fully in frame
        -if not: Move the object or the camera by some small amount
        -Check again if object is fully in frame
        -Repeat until object is fully in frame

        The incremental moving of the object or camera and then checking it again the scene view requires this to be done in a python tag or plugin. Where the code can run multiple times.
        It's not something you can normally do in the Script Manager script.

        This is a much more common way of placing objects in front of a camera using a script. And it's a lot less code to write:

        import c4d  
        from c4d import utils  
        def main() :  
          
          obj   = doc.GetActiveObject()             #The object to move  
          if obj is None: return False  
            
          box = obj.GetRad()                        #The object's bounding box radius  
          
          bd  = doc.GetActiveBaseDraw()  
          
          cam = bd.GetSceneCamera(doc)  
          camMtx = cam.GetMg()  
          
          #Something to compare the camera to the object..Use whatever camera property you want  
          focus = cam[c4d.CAMERAOBJECT_TARGETDISTANCE]  
          
          #This is what's commonly called a "translation matrix"      
          offset = c4d.utils.MatrixMove(c4d.Vector(0, 0, box.z + focus/7.5))  
          
          newmtx = camMtx * offset  
            
          obj.SetMg(newmtx)                         #Move the object to same place as the camera  
          
          obj.Message(c4d.MSG_UPDATE)               #Update the change made to the object  
          c4d.EventAdd()                            #Update C4D that something changed in the scene  
          
        if __name__=='__main__':  
          main()
        

        -ScottA

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

          On 06/02/2013 at 01:42, xxxxxxxx wrote:

          Thanks for your replies!
          @ingvair: I'll have a deeper look into this, thank you!

          @ScottA: Thanks for the code, but I believe that I'm still misunderstood. I'll try it this way if you don't mind:

          1. I never wanted to do the code incrementaly, I want to do this with one single calculation
          2. You move the object, I want to move my camera (away from the object)
          3. you turn the object to the camera, I want to keep the angle between camera and object
          4. basically I want the same effect as when I press 'H' on the keyboard, but in a controlled way, so that the selected object is completely in the rendered frame but with its maximal size.

          Here's a picture for more explanation:
          https://sharedspace.uhlmann.de/download2.php?fileid=oqy02MUHr6

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

            On 06/02/2013 at 03:20, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            Thanks for your replies!
            @ingvair: I'll have a deeper look into this, thank you!

            @ScottA: Thanks for the code, but I believe that I'm still misunderstood. I'll try it this way if you don't mind:

            1. I never wanted to do the code incrementaly, I want to do this with one single calculation
            2. You move the object, I want to move my camera (away from the object)
            3. you turn the object to the camera, I want to keep the angle between camera and object
            4. basically I want the same effect as when I press 'H' on the keyboard, but in a controlled way, so that the selected object is completely in the rendered frame but with its maximal size.

            Here's a picture for more explanation:
            https://sharedspace.uhlmann.de/download2.php?fileid=oqy02MUHr6

            Without wanting to sound rude, but you still do not understand. As I wrote already earlier you
            have to offset your basedaraw matrix, and I think Scott suggested something similar. You are in 
            some kind of special scenario, you want to calculate view related data. The base view class 
            depends on your camera matrix. Your approach was something like this :

            1. calculate data
            2. check result
            3. update the whole scene
            4. on false : goto 1
            5. on true : exit

            This is an incremental approach. Which is not generally bad, but in combination with updating the
            GUI (moving the camera  to update the base data for the base view) it leads to several problems.

            As I wrote earlier, simply use c4d.BaseView.SetMatrix() it has been made for this exact scenario,
            to offset a baseview.

            ps : i am littledevil 🙂

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

              On 06/02/2013 at 03:28, xxxxxxxx wrote:

              @Scott: Putting the code into a tag would be necessary when the camera should
              be moved or just be influenced over time (animated), but not when the camera should
              be moved for workflow reasons (like Nachtmahr said the 'H' command)

              -Niklas

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

                On 06/02/2013 at 04:38, xxxxxxxx wrote:

                Originally posted by xxxxxxxx

                Without wanting to sound rude, but you still do not understand.

                You don't sound rude, I can't deny that I still don't understand this 😉 But I'm eager to learn so I'll ask as long as I get the problem solved :]

                Originally posted by xxxxxxxx

                As I wrote earlier, simply use c4d.BaseView.SetMatrix() it has been made for this exact scenario, to offset a baseview.

                I'm sure you mean c4d.BaseView.SetBaseMatrix() because your method doesn't exist. I don'r understand what this method does. The documentation says "Sets the base matrix." - well... I already guessed that... The note says "The base matrix is multiplied with the camera matrix so that it is possible to have e.g. a frontal view into another direction than +Z."
                Ok, so it is multiplied with my camera matrix. I tried it in changing the BaseMatrix via the console

                  
                bd = doc.GetActiveBaseDraw()  
                bm = bd.GetBaseMatrix()  
                vec = c4d.Vector(0.1, 0, 0)  
                bm.off = vec  
                bd.SetBaseMatrix(bm)  
                

                I expected to see a change in view (because it is multiplied with my camera matrix as mentioned above) or something like that or at least in a rendering, but nothing happens.
                So I'm sorry, I still don't understand what this matrix does or how I have to use it. If you can give me a short example I'd be very glad!

                Thanks in advance
                Nachtmahr

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

                  On 06/02/2013 at 05:44, xxxxxxxx wrote:

                  Nachtmar,
                   
                  have a look at this:
                  http://chicagoc4d.com/C4DPythonSDK/misc/matrixfundamental.html#matrix-fundamental
                   
                  and did you look at the link I sent you in my prevoius post?
                  I struggled with similar things a few days ago. This helped me.
                   
                  -Ingvar

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

                    On 06/02/2013 at 13:22, xxxxxxxx wrote:

                    I feel like I'm not being clear enough about why you can't (normally) do this kind of thing with a script.
                    You are comparing an object's points to a camera's position. Which means that you have to physically have these objects in the scene to do the comparison. It can't be done virtually in memory where the user doesn't see this happening unless the whole thing is done in a separate document.

                    This kind of thing is much easier to do in a python tag. Because you can re-run the entire code just by using EventAdd() until the condition you're testing for becomes true.
                    You don't have this option in a script. It runs once then you're done.
                    There is no such thing as: Test the objects->Move one of the objects->Test the objects again etc. until you get the desired result.
                    You can't do that in a script.

                    However. That said you can force a script to do this kind of thing.
                    But it's a lot of extra work. And it requires a lot of adding and removing objects.
                    Which might not be considered a good practice.

                    This script will position the camera so the cube is within the safeFrame view.
                    And it does it in one click:

                    import c4d  
                      
                    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        
                                        
                    Zvalue = 0  
                    def main() :  
                      global Zvalue  
                        
                      cube = c4d.BaseObject(c4d.Ocube)  
                      cube.SetName('Cube')  
                      doc.InsertObject(cube)  
                      cube.SetBit(c4d.BIT_ACTIVE)  
                      c4d.CallCommand(12236) # Make Editable  
                        
                      cam = c4d.CameraObject()  
                      cam.SetName('Cam')  
                      camMg = cam.GetMg()  
                      camMg.off = c4d.Vector(0,0,-200)  
                      cam.SetMg(camMg)  
                      doc.InsertObject(cam)  
                        
                      stage = c4d.BaseObject(c4d.Ostage)  
                      doc.InsertObject(stage)  
                      
                      count = 0  
                      while count< 150:   #<--------------- Force the loop to stop after a set amount for safety  
                          tempcam = c4d.BaseObject(c4d.Ocamera)  
                          doc.InsertObject(tempcam)  
                          pos = tempcam.GetAbsPos()  
                          tempcam.SetAbsPos(c4d.Vector(0, 0, Zvalue - 3))  
                          tempcam.Message(c4d.MSG_UPDATE)  
                          pos = tempcam.GetAbsPos()  
                          Zvalue = pos.z  
                          stage[c4d.STAGEOBJECT_CLINK] = tempcam  
                          c4d.DrawViews(c4d.DRAWFLAGS_ONLY_ACTIVE_VIEW|c4d.DRAWFLAGS_NO_THREAD|c4d.DRAWFLAGS_NO_REDUCTION|c4d.DRAWFLAGS_STATICBREAK)  
                          if CheckIfInView(cam, cube, doc) :break  
                          tempcam.Remove()              
                          #print Zvalue        
                          count +=1  
                            
                            
                      #Set the original camera to the position the last cloned camera version was    
                      cam.SetAbsPos(c4d.Vector(0,0, Zvalue))      
                                
                      c4d.EventAdd()  
                      
                    if __name__ == '__main__':  
                      main()
                    

                    Quite a mouthful of code for such a seemingly simple task ain't it. 😉

                    -ScottA

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

                      On 06/02/2013 at 15:05, xxxxxxxx wrote:

                      Hi,

                      it is also possible without calling DrawViews() by moving the object itself, taking the delta from
                      its original position, move the camera by this delta and reset the object.

                      import c4d
                        
                      def TestPointInFrame(pt, frame) :
                          return pt.x > frame['cl'] and pt.x < frame['cr'] and \n           pt.y > frame['ct'] and pt.y < frame['cb']
                        
                      def CheckIfInView(obj, 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()
                        
                          #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() :
                          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
                          stopped = False
                          while not CheckIfInView(op, bd) :
                              stopped = EscapePressed()
                              if stopped: break
                        
                              MoveObjectRel(op, axis, offset)
                              passes += 1
                        
                          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
                      • H
                        Helper
                        last edited by

                        On 08/02/2013 at 05:34, xxxxxxxx wrote:

                        Thank you for your wonderful codes! I experimented the last two days with them and still have a few questions about them.

                        @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.

                        @Niklas: You move the object, not the camera. In future the scene I'll use this script/plugin on will have about 18.000 objects. I couldn't test it yet, but i suppose that this will be a serious performance issue.
                        And you use this line of code "op.SetRelPos(axis * offset)" to set the new offset of the object. If I'm not completely wrong vector math dictates to add the two vectors to get the resulting vector, not to multiply them. Obviously your solution works, so can you please tell me, why you multiply these two vectors instead of adding them? I'm really confused about this fact...

                        I really appreciate all your input and you all are helping me a lot! I'm really looking forward for your further answers. Thanks in advance!

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

                          On 08/02/2013 at 05:46, xxxxxxxx wrote:

                          Hi Nachtmahr,

                          I am moving the object, because moving the camera would require to redraw the editor in order for
                          BaseDraw.WS() to work correctly. The result is exactly the same. Compare Scotts and mine
                          example. You can watch the editor slowly moving away from the object in Scotts code, mine works
                          almost instantly. Do you really think it is more performant to redraw the editor on each pass?

                          axis is not a vector, it is a matrix. I'm moving the object away from the camera to simulate a
                          "zooming out". After the object is far away enough to fit into the editor view, I reset it to its
                          original position and move the camera about the anmount the object was moved in negative
                          direction.

                          > >> In future the scene I'll use this script/plugin on will have about 18.000 objects.

                          Separately or all at once (so they all fit into the view at once)? Make CheckInView() traverse the
                          hierarchy recursively to check if all objects in the scene are in the frame. You should put all
                          objects under a Null-Object then (to make the simulation of "zooming out" work) assuming you
                          keep sticking to my solution.

                          -Niklas

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

                            On 08/02/2013 at 06:15, xxxxxxxx wrote:

                            Originally posted by xxxxxxxx

                            Separately or all at once (so they all fit into the view at once)?

                            It's a machine imported from a CAD-Tool for rendering. In most cases I have to render seperate parts of the whole machine, so the focusing will affect multiple thousands of objects, but not all of them.

                            Originally posted by xxxxxxxx

                            You should put all objects under a Null-Object then (to make the simulation of "zooming out" work)

                            I think this won't be possible, because the inner structure of the imported data has to be kept. And if I move the parts under a Null-object I have to seperate them to their old places after the focusing is done. This sounds a bit of overkill to me.

                            1 Reply Last reply Reply Quote 0
                            • 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