0
$\begingroup$

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)


 
$\endgroup$
2

0

You must log in to answer this question.

Browse other questions tagged .