Jump to content

Center object in viewport


stepahneFont

Recommended Posts

Hello,

Thank you for your answer. In fact I know the shortcut to do this.
Rather, my question is how to insert this command "c4d.CallCommand (12151)" without using CallCommand?
Because I'm modifying a script but I understood that I couldn't use "CallCommand" in the script ... unless I'm wrong?

Link to comment

Hi @stepahneFont, hi @Mike A,

 

I think the op is looking for a programmatic solution and not a short cut @Mike A, but I might be wrong about this.

 

About the question - doing that is not impossible but I might be more complicated than anticipated by you. In principal Cinema 4D does not expose its "Frame Selected Objects" functionality in its Python SDK aside from the CallCommand AFAIK (I am assuming that you are on Python). So you would have to do that on your own, which is basically just some math. Replicating one to one what "Frame Selected Objects" does, can however be tricky, due to all the special cases that are associated with a camera object - projection modes, zoom, etc. Also the framing part can be a bit more involved, so when you want to place the camera in such way that the target object fills the frame. 

 

Aligning the camera view direction with the object is however not so hard, you can see an example at the end. This is however not what "Frame Selected Objects" does, its logic is more sophisticated and it tries to preserve to current camera orientation. But since you did only mention centering, this might actually be what you want to do.

 

Cheers,

Ferdinand

 

"""Orients the camera of the active viewport towards the selected object.
"""

import c4d

def main():
    """
    """
    # op is predefined in a script as the currently selected object. doc is
    # the currently active document.
    if op is None:
        raise RuntimeError("Please select an object.")

    # Get the active BaseDraw, i.e., editor view.
    bd = doc.GetActiveBaseDraw()
    if bd is None:
        raise RuntimeError("Could not access active view.") 
    # Get the attached camera.
    camera = bd.GetSceneCamera(doc)
    if camera is None:
        raise RuntimeError("Could not access active view camera.") 

    # Construct a frame/transform for our camera looking at the object.
    
    # The v3/k/z axis of the frame is just the unit vector from the camera 
    # to the object. 
    z = ~(op.GetMg().off - camera.GetMg().off)
    # Now we just make up the rest for it, for that we need an up vector that
    # is not (anti) parallel to z (because the cross product is the zero vector
    # for parallel vectors).
    up = c4d.Vector(0, 1, 0)
    up = up if (1. - abs(z * up)) >= .001 else c4d.Vector(0.001, 1, 0)

    # Build the rest of the frame.
    x = ~(up % z)
    y = ~(z % x)
    # And create a matrix/transform out of it.
    mg = c4d.Matrix(off=camera.GetMg().off, v1=x, v2=y, v3=z)

    # Set the new matrix for the camera object and create an undo for it.
    doc.StartUndo()
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, camera)
    camera.SetMg(mg)
    doc.EndUndo()

    c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()

 

Link to comment

Hi Zipit,

Whaouuu ...
It seems very interesting but unfortunately too complicated for me.

In fact I would like to add an object and then frame this object in the viewport (without adding a camera). The "o" shortcut does this but I can't seem to find the same in Python except with "CallCommand".
If I understand correctly, is that not possible?

 

Thank you

 

import c4d

obj = c4d.BaseObject(c4d.Ocube) 
obj.SetRelPos(c4d.Vector(0))   
doc.InsertObject(obj)   
c4d.CallCommand(12151) 
c4d.EventAdd() 

 

Link to comment

Hi  @stepahneFont,

 

using `c4d.CallCommand` is perfectly possible in any Python code run by Cinema 4D. You however never select your cube object, which in turn makes the job for the "Frame Selected Objects" function, i.e., c4d.CallCommand(12151), rather hard 😉 Try something like this:

 

"""Runs the Frame Selected Objects CallCommand.
"""

import c4d

def main():
    """
    """
    obj = c4d.BaseObject(c4d.Ocube)
    doc.InsertObject(obj) 
    # Since we want to rely on a active object with our CallCommand, i.e., 
    # frame it, we have to make it actually any active one. Use 
    # c4d.SELECTION_ADD if you want to add that object to the current 
    # selection instead of creating a new one.
    doc.SetActiveObject(obj, c4d.SELECTION_NEW)
    # After that we can run the CallCommand on that modified scene.
    c4d.CallCommand(12151) # Frame Selected Objects
 
if __name__=='__main__':
    main()

 

Cheers,

Ferdinand

Link to comment
  • 3 weeks later...

I think the way to frame selected objects, is to calculate a bounding box around all of the objects and then make sure that all eight points of the bounding box are visible on the screen, perhaps preserving the camera orientation to mimic the built in functionality of "Frame Selected." 

 

Of course this may be easier said than done and as already mentioned, camera type, zoom/perspective distortyion, etc., will need to be figured in, but it's the first step to solving the problem, in my opinion (i.e., to simplify it down to fitting the corners of a box on the screen). Attached are some pics to demonstrate.

 

The first image shows C4D's frame selected default behavior, with all objects aside from the bounding box I created, selected. After framing, I selected my bounding box in order to make its borders more visible, which is why it shows as selected (i.e., it was not selected for framing).

 

The second image is using C4D itself to frame the bounding box I made around all objects by hand, only (i.e., only the bounding box is selected).

 

As you can see, the method of using a bounding box to help frame is not perfect. A tighter crop is possible, as shown in image 1, if one takes into account the empty space near the box's corners. On the other hand, it does come close, is far easier to implement, and ensures that nothing gets cut off.

 

Cinema itself is not perfect, in the sense that it doesn't center the scene (containing all selected objects), as you can see in both images 1 and 2.

 

frame-selected-actual.png

frame-selected-bounding-box.png

Link to comment
×
×
  • Create New...

Copyright Core 4D © 2023 Powered by Invision Community