1
$\begingroup$

How can I get the distance between specific points in the 3D View and the virtual camera of my viewport?

Using the distance, I could select the closest or furthest (farthest) vertex/object from my perspective view.


Answering my own question, although I still don't know the difference between perspective_matrix, window_matrix and view_matrix. I also would prefer more explanation on why we don't need to use the inverted matrix.)
This question came up while creating this answer.

$\endgroup$

1 Answer 1

3
$\begingroup$

demo
Snapping an empty to the closest vertex of a cube. "Closest" meaning closest to the viewer.

First, loop through the areas or obtain a SpaceView3D by other means. The type of this area returns VIEW_3D. It's first space will be a VIEW_3D space. This space has a region_3d property, which has a perspective_matrix property.

The perspective_matrix appears to be the perspective view transform matrix. Mutliple a 3D Vector by the matrix, to get its position relativ to the camera.

Here is a working sample.

import bpy

# function returning the closest vertex of 
# param 'ob' is an object in the scene with vertices
def get_closest_vertex_position(scene, ob):
    # get an area of type VIEW_3D
    areas = [a for a in bpy.context.screen.areas if a.type == 'VIEW_3D']
    if not len(areas):
        return

    region3d = areas[0].spaces[0].region_3d

    # get the view matrix
    view_mat_inv = region3d.view_matrix

    if region3d.is_perspective:
        vertices = [[v, (view_mat_inv*v.co).length] for v in ob.data.vertices]
    else:
        vertices = [[v, -(view_mat_inv*v.co).z] for v in ob.data.vertices]

    # use a lamda expression to get closest vertex
    return min(vertices, key = lambda x: x[1])[0].co
$\endgroup$
7
  • 2
    $\begingroup$ Cool. Suggest doing this via a modal operator, a timer, or in a draw callback on the 3dview space rather than with a scene_update_pre . (depsgraph_update_pre on 2.8) handler. If for instance have two windows open with different scenes will confuse the result above. $\endgroup$
    – batFINGER
    Commented Jul 15, 2019 at 12:31
  • 1
    $\begingroup$ @bat Yes, definitely. This was merely a side product of this answer. I used the modal operator there. I'll just remove the last line, so future readers won't get tempted.^^ $\endgroup$
    – Leander
    Commented Jul 15, 2019 at 12:45
  • $\begingroup$ Did you mean to type view_matrix in the descriptive paragraphs? $\endgroup$
    – Robin Betts
    Commented Jul 15, 2019 at 13:05
  • $\begingroup$ @Robin Actually, no. As stated in the question, I'm still confused about perspective_matrix, window_matrix and view_matrix. The code works view perspective_matrix, although I don't know why. If you could clarify, that would be great. $\endgroup$
    – Leander
    Commented Jul 15, 2019 at 13:12
  • 1
    $\begingroup$ Following (as far as I can see) exactly the conventions described here, viewing down -Z, view_matrix is the xform from world space to viewpoint space (the inverse of the world xform of the viewpoint).. what window_matrix is depends on whether your view is orthogonal or perspective, and in either case gives the xform from the current window-shaped frustum to a canonical view volume, a cube -1 to 1 in X,Y and Z, viewpoint at 0. The perspective_matrix gives the 1st xform followed by the 2nd. $\endgroup$
    – Robin Betts
    Commented Jul 16, 2019 at 15:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .