# Creating vertices at mouse position is very off

I am trying to create a vertice at my mouse position with python. This is my code to get the location:

       region = bpy.context.region
space = bpy.context.space_data.region_3d
x, y = event.mouse_region_x, event.mouse_region_x
loc = bpy_extras.view3d_utils.region_2d_to_location_3d(region, space, (x, y), (0,0,0))


. This is what happens:

Add vert on left mouse click

Further to this answer added code to add vertex on left mouse click. (Using method explained here) Added a list to class to hold the newly added vertices, as suggested via this question.

Things to note:

Vertex coordinates are local coordinates, whereas the calculated 3d cursor position is a global coordinate. To convert global to local the global vector is multiplied by the objects matrix world inverted.

A class property for the matrix world inverted, similar to setting cls.bm for bmesh to avoid inverting the matrix each time.

When writing operators or panels, very rarely (if ever) do you need to access context via bpy.context. If context is an argument use it. I often use context = bpy.context atop of test scripts as a convenient way to later copy / paste into code where context is defined.

import bpy
import bmesh
from bpy_extras.view3d_utils import region_2d_to_location_3d

bmeshes = {}

class Modal(bpy.types.Operator):
bl_idname = "object.modal"
bl_label = "Modal Op"
bl_description = "Other thingy"
bl_options = {"REGISTER"}

bm = None

@classmethod
def poll(cls, context):
return context.object and context.object.type == 'MESH'

@classmethod
def bmesh(cls, context):
me = context.edit_object.data
cls.bm = bmesh.from_edit_mesh(me)

def invoke(self, context, event):
bpy.ops.object.mode_set(mode='EDIT')
self.bmesh(context)
return {"RUNNING_MODAL"}

v = self.bm.verts.new(loc)

return v

def modal(self, context, event):
# no longer in edit mode
if context.mode != 'EDIT_MESH':
self.bm.free()
self.bm = None
return {'CANCELLED'}
ob = context.edit_object
me = ob.data
if self.bm is None or not self.bm.is_valid:
# in edit mode so try make a new bmesh
self.bmesh(context)
if event.type == "LEFTMOUSE" and event.value == "PRESS":

x, y = event.mouse_region_x, event.mouse_region_y
region = context.region
rv3d = context.space_data.region_3d

loc = region_2d_to_location_3d(region, rv3d, (x, y), (0, 0, 0))

v.select = True

if event.type in {"RIGHTMOUSE", "ESC"}:
self.bm.verts.index_update()
bmesh.update_edit_mesh(me)
return {"CANCELLED"}

if event.type in ["WHEELUPMOUSE","WHEELDOWNMOUSE","MIDDLEMOUSE","LEFTMOUSE"]:
return{"PASS_THROUGH"}

return {"RUNNING_MODAL"}

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

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

if __name__ == "__main__":
register()
`

Btw. If you put minimal working code into your question it would be a lot easier to work out where your particular mistake is.