3D View - Как отобразить данные камеры в кадре камеры?
Есть ли способ использовать параметры отображения, такие как «информация об объекте» или «имя вида» (в настройках области просмотра), для отображения другой информации, например, фокусного расстояния активной камеры и ее положения. И есть ли способ переместить эту информацию куда-нибудь в 3D-окно? Как в этом примере:
Итак, я нашел сценарий, который позволяет мне отображать фокус в 3D-окне.
import bpy
import blf
dns = bpy.app.driver_namespace
dc = dns.get("dc")
dc.remove_handle()
class DrawingClass:
def __init__(self, context, prop):
self.prop = prop
self.handle = bpy.types.SpaceView3D.draw_handler_add(
self.draw_text_callback,(context,),
'WINDOW', 'POST_PIXEL')
def draw_text_callback(self, context):
font_id = 0 # XXX, need to find out how best to get this.
# draw some text
blf.position(font_id, 15, 350, 0)
blf.size(font_id, 20, 72)
blf.draw(font_id, "%s %s" % (context.scene.name, self.prop))
def remove_handle(self):
bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')
context = bpy.context
dns = bpy.app.driver_namespace
dns["dc"] = DrawingClass(context, bpy.context.object.data.lens)
Первые 3 строки позволяют мне стереть предыдущий дисплей. Как я могу запретить scipte читать первые 3 строки при первом запуске скрипта? А пока скрипт считывает фокус и записывает его. Как сделать так, чтобы сценарий читался каждый раз при смене фокуса?
Ответы
AFAIK это невозможно по умолчанию, и я предполагаю, что не существует надстройки, которая могла бы отображать любую информацию в кадре камеры.
Однако вы можете нарисовать текст с помощью модуля python bgl и создать свое собственное дополнение. Следующий пример кода основан на нашем знаменитом шаблоне Operator Modal Draw, который поставляется с блендером, расширенный ответами из Координаты углов границы обзора камеры и Многострочный текст в blf (с многоцветной опцией), чтобы заставить мяч катиться:
hud.py
import bpy
import blf
import bgl
# -> BASED ON: https://blender.stackexchange.com/a/14746/31447
def view3d_find(context):
# returns first 3d view, normally we get from context
for area in context.window.screen.areas:
if area.type == 'VIEW_3D':
v3d = area.spaces[0]
rv3d = v3d.region_3d
for region in area.regions:
if region.type == 'WINDOW':
return region, rv3d
return None, None
def view3d_camera_border(context):
obj = context.scene.camera
cam = obj.data
frame = cam.view_frame(scene=context.scene)
# move from object-space into world-space
frame = [obj.matrix_world @ v for v in frame]
# move into pixelspace
from bpy_extras.view3d_utils import location_3d_to_region_2d
region, rv3d = view3d_find(context)
frame_px = [location_3d_to_region_2d(region, rv3d, v) for v in frame]
return frame_px
# -> BASED ON: https://blender.stackexchange.com/a/31799/31447
def draw_string(x, y, packed_strings):
font_id = 0
blf.size(font_id, 18, 72)
x_offset = 0
y_offset = 0
line_height = (blf.dimensions(font_id, "M")[1] * 1.45)
for command in packed_strings:
if len(command) == 2:
pstr, pcol = command
blf.color(font_id, pcol[0], pcol[1], pcol[2], pcol[3]) # #bgl.glColor4f(pcol)
text_width, text_height = blf.dimensions(font_id, pstr)
blf.position(font_id, (x + x_offset), (y + y_offset), 0)
blf.draw(font_id, pstr)
x_offset += text_width
else:
x_offset = 0
y_offset -= line_height
def draw_callback_px(self, context):
WHITE = (1, 1, 1, .7)
CR = "Carriage Return"
x, y = view3d_camera_border(context)[3]
cam_ob = context.scene.camera
if cam_ob is not None:
ps = [
("{} {}mm".format(cam_ob.name, cam_ob.data.lens), WHITE),
CR,
CR,
("T: {:.2f}, {:.2f}, {:.2f}".format(
cam_ob.location.x,
cam_ob.location.y,
cam_ob.location.z), WHITE),
CR,
("R: {:.2f}, {:.2f}, {:.2f}".format(
cam_ob.rotation_euler.x,
cam_ob.rotation_euler.y,
cam_ob.rotation_euler.z), WHITE),
]
draw_string(x+10, y-20, ps)
# restore opengl defaults
bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_BLEND)
# -> MODAL OPERATOR TEMPLATE
class ModalDrawOperator(bpy.types.Operator):
"""Draw a line with the mouse"""
bl_idname = "view3d.modal_operator"
bl_label = "Simple Modal View3D Operator"
@classmethod
def poll(cls, context):
return context.area.type == 'VIEW_3D'
def modal(self, context, event):
context.area.tag_redraw()
if event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'PASS_THROUGH'}
def invoke(self, context, event):
if context.space_data.region_3d.view_perspective == 'CAMERA':
# the arguments we pass the the callback
args = (self, context)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "Switch into Camera View")
return {'CANCELLED'}
def register():
bpy.utils.register_class(ModalDrawOperator)
def unregister():
bpy.utils.unregister_class(ModalDrawOperator)
if __name__ == "__main__":
register()
Скопируйте и вставьте скрипт в текстовый редактор, запустите его, перейдите к 3D View, нажмите F3и введите «Simple Operator ...» для выполнения. Если вы хотите преобразовать его в надстройку, просто добавьте словарь python с именем «bl_info» вверху надстройки:https://wiki.blender.org/wiki/Process/Addons/Guidelines/metainfo
Чтобы заставить его работать для версий 2.7x, вам придется заменить 2 строки из-за изменений в Matrix Multiplication и того, как установить цвет текста с помощью blf.color в более новых версиях:
# draw_string()
- blf.color(font_id, pcol[0], pcol[1], pcol[2], pcol[3]) # Blender 2.8x
+ bgl.glColor4f(*pcol) # Blender 2.7x
# view3d_camera_border()
- frame = [obj.matrix_world @ v for v in frame] # Blender 2.8x
+ frame = [obj.matrix_world * v for v in frame] # Blender 2.7x