1
$\begingroup$

How to get the mouse coordinates in 3space relative to the local coordinates of the active object?

This code gives the position of the mouse relative to the world coordinates, and I need to get exactly local

view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
loc = view3d_utils.region_2d_to_location_3d(region, rv3d, coord, view_vector)
$\endgroup$

1 Answer 1

4
$\begingroup$

You can obtain the mouse coordinates from a modal operator and use the current event information.

enter image description here

Here I used one of the script templates 'operator modal draw' with little modification in order to use and translate the mouse position.

Your question's relative parts of the code are commented below (please comment if you need more information):

import bpy
import bgl
import blf

from bpy_extras import view3d_utils


def draw_callback_px(self, context):
    font_id = 0
    blf.position(font_id, 15, 100, 0)
    blf.size(font_id, 12, 72)
    blf.draw(font_id, "Mouse position: " + str(self.mouse_pos[0]) + "/" + str(self.mouse_pos[1]) )
    blf.position(font_id, 15, 115, 0)
    blf.draw(font_id, "3D position from " + self.object.name + ": " + str(self.loc[0]) + "/" + str(self.loc[1]) + "/" + str(self.loc[2])  )

class ModalDrawOperator(bpy.types.Operator):
    """Draw a line with the mouse"""
    bl_idname = "view3d.modal_operator"
    bl_label = "Simple Modal View3D Operator"

    def modal(self, context, event):
        context.area.tag_redraw()

        if event.type == 'MOUSEMOVE':

            #Get the mouse position thanks to the event            
            self.mouse_pos = [event.mouse_region_x, event.mouse_region_y]

            #Contextual active object, 2D and 3D regions
            self.object = bpy.context.object
            region = bpy.context.region
            region3D = bpy.context.space_data.region_3d

            #The direction indicated by the mouse position from the current view
            view_vector = view3d_utils.region_2d_to_vector_3d(region, region3D, self.mouse_pos)
            #The 3D location in this direction
            self.loc = view3d_utils.region_2d_to_location_3d(region, region3D, self.mouse_pos, view_vector)
            #The 3D location converted in object local coordinates
            self.loc = self.object.matrix_world.inverted() * self.loc

        elif event.type in {'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        if context.area.type == 'VIEW_3D':
            args = (self, context)
            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')

            #Keeps mouse position current 3D location and current object for the draw callback
            #(not needed to make it self attribute if you don't want to use the callback)
            self.mouse_pos = [0,0]
            self.loc = [0,0,0]
            self.object = None

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "View3D not found, cannot run operator")
            return {'CANCELLED'}


def register():
    bpy.utils.register_class(ModalDrawOperator)


def unregister():
    bpy.utils.unregister_class(ModalDrawOperator)

if __name__ == "__main__":
    register()
$\endgroup$
1
  • $\begingroup$ I tried to do it for 2 days! Thank you so much! $\endgroup$ Commented Mar 27, 2017 at 8:29

You must log in to answer this question.

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