0
$\begingroup$

I am trying to randomly place an object in my CYCLES scene. The below function gets a random location within the camera's FoV, but there is a problem: if the object is too far away, it will not be visible when the scene is rendered... and if it too close, it will cover the whole scene...

My camera resolution is 500x500.

I would like to specify the minimum and maximum number of pixels my object can take up. This will ensure the object is not so small (e.g., 1 pixel) and not too big (e.g., 1000 pixels.

How can I do this? I thought that perhaps I could get the 3D bounding box of the object, project it onto 2D space, calculate the area of the bounding box in pixels, and if it was above or below some min/max threshold, generate a new location. However, I am too stupid to figure it out.

Any help?

def random_location_within_camera_fov(camera, frame, min_distance):
    # camera is a blender camera, frame is a normalized frame obtained from camera_normalized_frame(), and min_distance is an integer

    # Generate a random distance between the minimum distance and the maximum distance
    distance = np.random.uniform(min_distance, camera.object.data.clip_end)

    v = Vector([
        np.random.uniform(-1, 1) * frame[0].x,
        np.random.uniform(-1, 1) * frame[0].y,
        frame[0].z
    ])

    location = camera.object.matrix_world @ (distance * v)
    return location


def camera_normalized_frame(camera):
    render = bpy.context.scene.render
    aspect = (render.resolution_x * render.pixel_aspect_x) \
             / (render.resolution_y * render.pixel_aspect_y)
    view_frame = camera.object.data.view_frame()
    frame = [-f/view_frame[0].z for f in view_frame]
    if aspect > 1:
        mat = Matrix.Diagonal((1, 1/aspect, 1),)
    else:
        mat = Matrix.Diagonal((aspect, 1, 1), )
    for i in range(len(frame)):
        frame[i] = mat @ frame[i]
    return frame
$\endgroup$

0

You must log in to answer this question.

Browse other questions tagged .