0

Is it possible to make a driver that will be keep mesh scale "static" on screen? If I zoom in/out, the mesh scale stays visually the same as before or close to it. Start point for the object is 3d cursor position.

I think I found solution, thx to Howard Trickey's addon 'Inset Straight Skeleton'. It give me a value depend on how far or close am I to the 3d cursor in 3d view.

import bpy
from math import sqrt

context = bpy.context

def calc_pixel_size(context, co): # returns size in blender units of a pixel at 3d coord co # see C code in ED_view3d_pixel_size and ED_view3d_update_viewmat m = context.region_data.perspective_matrix v1 = m[0].to_3d() v2 = m[1].to_3d() ll = min(v1.length_squared, v2.length_squared) len_pz = 2.0 / sqrt(ll) len_sz = max(context.region.width, context.region.height) rv3dpixsize = len_pz / len_sz proj = m[3][0] * co[0] + m[3][1] * co[1] + m[3][2] * co[2] + m[3][3] ups = context.preferences.system.pixel_size #print("Pixel size:", proj * rv3dpixsize * ups) return proj * rv3dpixsize * ups

center = bpy.context.scene.cursor.location center_pixel_size = calc_pixel_size(context, center) print(center_pixel_size)

APEC
  • 570
  • 3
  • 12
  • Is this what you're after? – Robin Betts Feb 06 '23 at 09:59
  • 1
    kind of. There the length calculates between object origin and camera, and depend on it calculates scale. But in my case I need to calculate, as I understand pixel size, from 3d cursor in 3d view. Found how, I believe. I'll update post now. – APEC Feb 06 '23 at 10:17
  • 1
    Hi, thanks for the post. While answering your own question is possible and even encouraged, it should be done respecting the site structure. Could you break this up into two posts, so the solution is written as separate answer in the proper section below? Maybe add a short description of the steps accompanied by a few images illustrating the workflow and final results. See How do I write a good answer? – Duarte Farrajota Ramos Feb 06 '23 at 10:35
  • 1
    To make it solved, I think, we need figure out how to add driver to scale object with this value. So basically, how to add this value if I run the script modal and got value nonstop to update scale in real time... – APEC Feb 06 '23 at 10:38

1 Answers1

1

I did not find a better solution than to run the calculation through a modal. enter image description here

import bpy
from math import sqrt

def calc_pixel_size(co): # returns size in blender units of a pixel at 3d coord co # see C code in ED_view3d_pixel_size and ED_view3d_update_viewmat try: m = bpy.context.region_data.perspective_matrix except: # in some cases region_data did not work view3d = bpy.context.space_data view_matrix = view3d.region_3d.view_matrix m = view3d.region_3d.perspective_matrix

v1 = m[0].to_3d()
v2 = m[1].to_3d()
ll = min(v1.length_squared, v2.length_squared)
len_pz = 2.0 / sqrt(ll)
len_sz = max(bpy.context.region.width, bpy.context.region.height)
rv3dpixsize = len_pz / len_sz
proj = m[3][0] * co[0] + m[3][1] * co[1] + m[3][2] * co[2] + m[3][3]
ups = bpy.context.preferences.system.pixel_size

return proj * rv3dpixsize * ups

class ModalObjectScale(bpy.types.Operator): """Tooltip""" bl_idname = "view3d.modal_object_scale" bl_label = "Modal object scale in 3D_View"

def modal(self, context, event):
    obj =  bpy.data.objects['Cube']
    obj_center = obj.location

    center_pixel_size = calc_pixel_size(obj_center)*100
    print("========================")
    print(center_pixel_size)

    obj.scale[0] = center_pixel_size
    obj.scale[1] = center_pixel_size
    obj.scale[2] = center_pixel_size

    if event.type in {'RIGHTMOUSE', 'ESC'}:
        print('CANCELLED')
        return {'CANCELLED'}

    return {'PASS_THROUGH'}

def invoke(self, context, event):
    if context.area.type == 'VIEW_3D':
        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(ModalObjectScale)

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

if name == "main": register()

APEC
  • 570
  • 3
  • 12