0
$\begingroup$

I am trying to make a script that will determine the exact coordinates of an object's bounding box in the render. (I later want to limit the rendered space to that area.)

So far I managed to get the coordinates from the object's bound_box And I managed to take the scale and location into account but I failed with the rotation.

My problem is that I have the coordinates of my bounding box but I don't know how to make them follow the rotation, like the bounding box in the viewport does. When I run the script with a cube it works fine, but when the cube is being rotated the coordinates that are being printed out do not change.

import bpy
import bpy_extras
import mathutils

scene = bpy.context.scene
obj = bpy.context.object
co = bpy.context.scene.cursor_location

scale = bpy.data.objects['cube'].scale

bounding_box_vertices = []
for i in range(8):
    bounding_box_vertices.append(i)
    bounding_box_vertices[i]=[1, 2, 3]

#the Coordinates from bound_box are saved to bounding_box_vertices[[],[]]
for i in range(8):
    for j in range(3):
        bounding_box_vertices[i][j]=bpy.data.objects['cube'].bound_box[i][j]*bpy.data.objects['cube'].scale[0] + bpy.data.objects['cube'].location[j]

def rendered_coords(x):
    co = mathutils.Vector((bounding_box_vertices[x][0], bounding_box_vertices[x][1], bounding_box_vertices[x][2]))
    co_2d = bpy_extras.object_utils.world_to_camera_view(scene, obj, co)

    render_scale = scene.render.resolution_percentage / 100
    render_size = (int(scene.render.resolution_x * render_scale), int(scene.render.resolution_y * render_scale))
    #print("Pixel Coords:", (
    return([round(co_2d.x * render_size[0]), round(co_2d.y * render_size[1])])
     # ))

#prints ou the 8 X and Y coordinates that the bounding box would have on the render (even though its invisible of course)
for i in range(8):
    final_coords = rendered_coords(i)
    print(final_coords[0])
    print(final_coords[1])
$\endgroup$
  • $\begingroup$ @R.M They are talking about coordinates in the render, hence the 'rendering' tag is relevant here. $\endgroup$ – Ray Mairlot Sep 15 '18 at 15:24
1
$\begingroup$

The bounding box coordinates of obj.bound_box are in local space. To convert them to world space – assuming you're interested in the world space coordinates and don't just want to consider rotation – you'll have to multiply the world matrix with the coordinates as mentioned in this answer by CoDEmanX.

import bpy
from mathutils import Vector

obj = bpy.context.object  # or bpy.data.objects['cube']
bb_vertices = [Vector(v) for v in obj.bound_box]
mat = obj.matrix_world
world_bb_vertices = [mat * v for v in bb_vertices]

From there you can continue with world_to_camera_view. From your code it's not clear what your obj is, but just to clarify: This function takes the Camera object and not the object with the bounding box. The bounding box coordinates are only considered for the third parameter. Similarly, you will need the mat world matrix of the object with the bounding box.

import bpy
from bpy_extras.object_utils import world_to_camera_view
from mathutils import Vector

scene = bpy.context.scene
obj = bpy.context.object  # or bpy.data.objects['cube']
bb_vertices = [Vector(v) for v in obj.bound_box]
mat = obj.matrix_world
world_bb_vertices = [mat * v for v in bb_vertices]

co_2d = [world_to_camera_view(scene, scene.camera, v) for v in world_bb_vertices]  # from 0 to 1

render_scale = scene.render.resolution_percentage / 100
render_size = list(int(res) * render_scale for res in [scene.render.resolution_x, scene.render.resolution_y])
pixel_coords = [(c.x * render_size[0], c.y * render_size[1]) for c in co_2d]  # in pixels

for p in pixel_coords:
    print('{p[0]:.0f}, {p[1]:.0f}'.format(p=p))
$\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.