Shift the camera.
Adjusting the shift setting of the camera, such that the camera aligned 2d bounding box of object is centered.
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
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
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.
It appears by your angles and camera positions that you are after a
"perspective isometric" view
Setting up an isometric view
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)
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.