I am trying to build a program to optimise the position of a camera such that the object in question fills the render. The bounding box is inadequate for renders from 45 degree angles, for instance.
I am attempting to achieve this by projecting the vertices to their 2D representation from the camera perspective and finding the convex hull. This I can compare to the area of the viewport.
However, the program outputs the same vertices regardless of my transformation matrix. I am new to Blender and therefore am a bit lost.
Can someone suggest what might be wrong here? I am using Blender 3.4.1.
import numpy as np
from scipy.spatial import ConvexHull
def CalcHullArea(obj, location, distance):
scene = bpy.context.scene
camera = scene.camera
m_0 = np.asarray(camera.matrix_world.copy())
camera.location = location(distance)
camera.update_tag()
bpy.context.view_layer.update()
m_1 = np.asarray(camera.matrix_world.copy())
## Check m_0 and m_1 are different.
assert (!np.allclose(m_0, m_1))
# Get the world matrix of the object
world_matrix = obj.matrix_world
# Get the inverse of the camera matrix
camera_matrix = camera.matrix_world.inverted()
# Get the projection matrix of the camera
projection_matrix = camera.calc_matrix_camera(
bpy.context.evaluated_depsgraph_get(),
x=scene.render.resolution_x,
y=scene.render.resolution_y
)
# Combine the world space matrix, camera inverse matrix, and projection matrix
combined_matrix = projection_matrix @ camera_matrix @ world_matrix
# Project the vertices of the object to 2D screen space
verts_2D = np.array([np.array((vert.co @ combined_matrix))[:2] for vert in obj.data.vertices])
# Compute the convex hull of the 2D screen space vertices
hull = ConvexHull(verts_2D)
# Calculate the area of the convex hull
area = hull.volume
return area
# Example usage
obj = bpy.context.active_object
center = obj.location
location = lambda d: (center[0], center[1], center[2]+d)
A_0 = CalcHullArea(obj, location, 0)
A_1 = CalcHullArea(obj, location, 100)
print(A_0, A_1)