Region_2d_to_origin_3d- what is the point of "coord" if it always returns the same result?

So this is one of those things I just always assume worked a certain way, so it’s kind of blowing my mind to find out that reality is different than I had pictured. Long story short- the coord argument doesn’t do a damn thing.

region_2d_to_origin_3d always returns an origin at the same place- the viewport camera’s location, it doesn’t take screen position into consideration at all. region_2d_to_vector_3d is a different story- you need the screen coordinate to get a correct direction vector, but it doesn’t appear to be necessary at all for region_2d_to_origin_3d.

I had always pictured region_2d_to_origin_3d calculating a projected 3D vector at whatever position on the near clipping plane corresponded to the input coordinate, but that doesn’t appear to be the case based on my testing. I discovered this while trying to find the four corners of the viewport clipping plane. oh well, back to square one.

import bpy
from bpy_extras.view3d_utils import region_2d_to_origin_3d

# temp context stuff to run from the scripting workspace
area = bpy.context.screen.areas[5]
space_data = area.spaces[0]
rv3d = space_data.region_3d
region = area.regions[4]

print(f"region.width: {region.width}, region.height: {region.height}, x: {region.x}, y: {region.y}")

# all of these will be identical, regardless of what coord is set to:

for x in range(region.x, region.width, 100):
    for y in range(region.y, region.height, -100):
        print(f"{x}, {y}: {region_2d_to_origin_3d(region, rv3d, (x, y))}")

viewport_cam_location = rv3d.view_matrix.inverted().translation   
print(f"Anybody want to guess what the viewport camera's location is? Yep, {viewport_cam_location}")

Result:

region.width: 1124, region.height: 722, x: 0, y: 1265
0, 1265: <Vector (8.5016, -3.5268, 5.7063)>
0, 1165: <Vector (8.5016, -3.5268, 5.7063)>
0, 1065: <Vector (8.5016, -3.5268, 5.7063)>
0, 965: <Vector (8.5016, -3.5268, 5.7063)>
0, 865: <Vector (8.5016, -3.5268, 5.7063)>
0, 765: <Vector (8.5016, -3.5268, 5.7063)>
100, 1265: <Vector (8.5016, -3.5268, 5.7063)>
100, 1165: <Vector (8.5016, -3.5268, 5.7063)>
100, 1065: <Vector (8.5016, -3.5268, 5.7063)>
100, 965: <Vector (8.5016, -3.5268, 5.7063)>
100, 865: <Vector (8.5016, -3.5268, 5.7063)>
100, 765: <Vector (8.5016, -3.5268, 5.7063)>
200, 1265: <Vector (8.5016, -3.5268, 5.7063)>
200, 1165: <Vector (8.5016, -3.5268, 5.7063)>
200, 1065: <Vector (8.5016, -3.5268, 5.7063)>
200, 965: <Vector (8.5016, -3.5268, 5.7063)>
200, 865: <Vector (8.5016, -3.5268, 5.7063)>
200, 765: <Vector (8.5016, -3.5268, 5.7063)>
300, 1265: <Vector (8.5016, -3.5268, 5.7063)>
300, 1165: <Vector (8.5016, -3.5268, 5.7063)>
300, 1065: <Vector (8.5016, -3.5268, 5.7063)>
300, 965: <Vector (8.5016, -3.5268, 5.7063)>
300, 865: <Vector (8.5016, -3.5268, 5.7063)>
300, 765: <Vector (8.5016, -3.5268, 5.7063)>
400, 1265: <Vector (8.5016, -3.5268, 5.7063)>
400, 1165: <Vector (8.5016, -3.5268, 5.7063)>
400, 1065: <Vector (8.5016, -3.5268, 5.7063)>
400, 965: <Vector (8.5016, -3.5268, 5.7063)>
400, 865: <Vector (8.5016, -3.5268, 5.7063)>
400, 765: <Vector (8.5016, -3.5268, 5.7063)>
500, 1265: <Vector (8.5016, -3.5268, 5.7063)>
500, 1165: <Vector (8.5016, -3.5268, 5.7063)>
500, 1065: <Vector (8.5016, -3.5268, 5.7063)>
500, 965: <Vector (8.5016, -3.5268, 5.7063)>
500, 865: <Vector (8.5016, -3.5268, 5.7063)>
500, 765: <Vector (8.5016, -3.5268, 5.7063)>
600, 1265: <Vector (8.5016, -3.5268, 5.7063)>
600, 1165: <Vector (8.5016, -3.5268, 5.7063)>
600, 1065: <Vector (8.5016, -3.5268, 5.7063)>
600, 965: <Vector (8.5016, -3.5268, 5.7063)>
600, 865: <Vector (8.5016, -3.5268, 5.7063)>
600, 765: <Vector (8.5016, -3.5268, 5.7063)>
700, 1265: <Vector (8.5016, -3.5268, 5.7063)>
700, 1165: <Vector (8.5016, -3.5268, 5.7063)>
700, 1065: <Vector (8.5016, -3.5268, 5.7063)>
700, 965: <Vector (8.5016, -3.5268, 5.7063)>
700, 865: <Vector (8.5016, -3.5268, 5.7063)>
700, 765: <Vector (8.5016, -3.5268, 5.7063)>
800, 1265: <Vector (8.5016, -3.5268, 5.7063)>
800, 1165: <Vector (8.5016, -3.5268, 5.7063)>
800, 1065: <Vector (8.5016, -3.5268, 5.7063)>
800, 965: <Vector (8.5016, -3.5268, 5.7063)>
800, 865: <Vector (8.5016, -3.5268, 5.7063)>
800, 765: <Vector (8.5016, -3.5268, 5.7063)>
900, 1265: <Vector (8.5016, -3.5268, 5.7063)>
900, 1165: <Vector (8.5016, -3.5268, 5.7063)>
900, 1065: <Vector (8.5016, -3.5268, 5.7063)>
900, 965: <Vector (8.5016, -3.5268, 5.7063)>
900, 865: <Vector (8.5016, -3.5268, 5.7063)>
900, 765: <Vector (8.5016, -3.5268, 5.7063)>
1000, 1265: <Vector (8.5016, -3.5268, 5.7063)>
1000, 1165: <Vector (8.5016, -3.5268, 5.7063)>
1000, 1065: <Vector (8.5016, -3.5268, 5.7063)>
1000, 965: <Vector (8.5016, -3.5268, 5.7063)>
1000, 865: <Vector (8.5016, -3.5268, 5.7063)>
1000, 765: <Vector (8.5016, -3.5268, 5.7063)>
1100, 1265: <Vector (8.5016, -3.5268, 5.7063)>
1100, 1165: <Vector (8.5016, -3.5268, 5.7063)>
1100, 1065: <Vector (8.5016, -3.5268, 5.7063)>
1100, 965: <Vector (8.5016, -3.5268, 5.7063)>
1100, 865: <Vector (8.5016, -3.5268, 5.7063)>
1100, 765: <Vector (8.5016, -3.5268, 5.7063)>
Anybody want to guess what the viewport camera's location is? Yep, <Vector (8.5016, -3.5268, 5.7063)>
1 Like

And FYI- for anyone who was under the same impression as I was and actually want the location in 3d space that corresponds to the near clip plane, use region_2d_to_vector_3d to get the direction vector and then multiply it by the near clip plane’s length.