3
$\begingroup$

So, Im trying to constrain a camera to view an object perfectly in the center...

Ive set a constraint on my camera so that it uses "track to" to point at the center of my shape.

However, I noticed that even when I use an exact measurement on my cameras position to give it a perfect 45 degree diagonal angle towards my object (x5, y-5, z5 for example), its still not aligned perfectly

As you can see in the image below, the object isnt fully in the center, even though its at a perfect position and its being constrained to the object position

enter image description here

Is there a way to constrain it and align it perfectly to the center of the object even while using perspective view (So I can move the object and have it perfectly centered relative to the camera's picture)

Or this unrealistic?

Essentially, I want it to perfectly fit in the center of the camera, no matter where I move it.

enter image description here

$\endgroup$
2
  • 3
    $\begingroup$ You'll have to clarify what you mean by "perfectly in the center". You say "As you can see in the image below, the object isnt fully in the center" but it looks centered to me. $\endgroup$ – PGmath Mar 10 at 13:56
  • $\begingroup$ He's not talking about the center of the object, but the overall outline of the object - so that in his image the space above the top corner is the same width as the space below the bottom corner. $\endgroup$ – Gordon Brinkmann Mar 10 at 14:30
6
$\begingroup$

Shift the camera.

Adjusting the shift setting of the camera, such that the camera aligned 2d bounding box of object is centered.

enter image description here Result of running on default scene, then transforming and re running, there is no constraint pointing camera to origin of object, if so there would be less shift depending on origin point

  1. Firstly as mentioned in question am assuming you have the camera set up and pointing to the object of interest.

    A couple of useful links in regard to this.

    Add camera at random position through Python

    Script to render one object from different angles

  2. Have added an optional option to create an object that shows the 2d bounding box of object of interest lying on the plane defined by the origin point of object, and with a normal matching the camera direction. Uses the code from

    Getting edges of the camera's view on the scene XY plane

    set create_bbox2d = True to False (or delete code) to remove completely.

  3. It appears by your angles and camera positions that you are after a "perspective isometric" view Setting up an isometric view

  4. To shift the camera requires using the aspect ratio from render settings

    Set Render/Camera resolution to Render Border coordinates

Putting it together as a script. Select the object of interest, with a camera set as scene camera and run script.

import bpy
from mathutils import Vector
from mathutils.geometry import intersect_line_plane as ilp
from bpy_extras.object_utils import world_to_camera_view as w2cv
import bmesh
import numpy as np

create_bbox2d = True

context = bpy.context
scene = context.scene
ob = context.object
me = ob.data
cam = scene.camera
mw = cam.matrix_world
o = mw.translation

plane_no = mw.to_3x3().col[2]
plane_co = ob.matrix_world.translation

camdata = cam.data
bm = bmesh.new()
bm.from_mesh(me)
bm.transform(ob.matrix_world)
u, v = np.array([w2cv(scene, cam, v.co).xy 
        for v in bm.verts]).T

tr, br, bl, tl = [
mw @ f for f in camdata.view_frame(scene=scene)]
# offset vectors from bl.
# eg middle would be bl + 0.5 * (x + y) 
x = tr - tl
y = tr - br
# roll around in CCW direction

bbox2d = (
        (u.min(), v.min()),
        (u.max(), v.min()), 
        (u.max(), v.max()),       
        (u.min(), v.max()),
        )
        
if create_bbox2d:
    coords = []
    for image_coord in map(Vector, bbox2d):
        cx, cy = image_coord
        # vector pointing from cam origin thru image point (PERSP)
        vec = (bl + (cx * x + cy * y)) - o

        pt = ilp(o, o +  vec, plane_co, plane_no, True)
        if pt:
            coords.append(pt)
      
    if coords:
        name = f"{cam.name}_ViewPlane"
        me = bpy.data.meshes.new(name)
        faces = [range(len(coords))] if len(coords) > 2 else []
        me.from_pydata(coords, [], faces)
        ob = bpy.data.objects.new(name, me)
        context.collection.objects.link(ob)
        ob.display_type = 'WIRE'
# shift the camera
aspect = (
        scene.render.resolution_x / 
        scene.render.resolution_y
        )

# UV origin shift
(u.min(), v.min() / aspect)
# UV shift 

#v /= aspect
# move to UV (0, 0)
cam.data.shift_x += u.min()
cam.data.shift_y += v.min() / aspect

cam.data.shift_x -= (1 - u.max() + u.min()) / 2
cam.data.shift_y -= (1 - v.max() + v.min()) / (2 * aspect)

enter image description here Quad view after making gif above, all the notice all "frames" (last one active) are in the same plane, normal to cameras direction To animate this would use a frame change handler.

$\endgroup$
2
$\begingroup$

I don’t believe that’s possible since its ‘viewing centre’ will change depending on the object’s orientation, distance and geometry - as well as the camera’s orientation and settings (eg, focal length). This is too variable and dependent on the viewpoint.

Your current setup is using the object’s origin as the “anchor” for the lock and that is the best you can do with constraints.

The only other option would be to render the view larger than you require and then trim it down in post-processing. eg, you could have a script that determines the bounds of the object in the view and then crop the image to be consistently spaced.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.