3d보기 — 카메라 프레임에 카메라 데이터를 표시하는 방법은 무엇입니까?

Aug 17 2020

"개체 정보"또는 "뷰 이름"(뷰포트의 기본 설정에 있음)과 같은 표시 옵션을 사용하여 활성 카메라의 렌즈 초점 및 위치와 같은 기타 정보를 표시하는 방법이 있습니까? 그리고이 정보를 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 줄을 읽지 못하게하려면 어떻게해야합니까? 지금은 스크립트가 초점을 한 번 읽고 씁니다. 초점이 변경 될 때마다 스크립트를 읽는 방법은 무엇입니까?

답변

3 brockmann Aug 20 2020 at 00:55

AFAIK는 기본적으로 불가능하며 카메라 프레임에 모든 종류의 정보를 표시 할 수있는 기존 애드온이 없다고 생각합니다.

그러나 파이썬의 bgl 모듈을 사용하여 텍스트를 그리고 자신 만의 부가 기능을 만들 수 있습니다. 다음 예제 코드는 블렌더와 함께 제공되는 유명한 Operator Modal Draw 템플릿을 기반으로 하며 , 볼 롤링을 얻기 위해 카메라 뷰 테두리 모서리의 좌표 와 blf의 Multi-line Text (멀티 컬러 옵션 포함) 의 답변으로 확장됩니다 .

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보기로 이동 한 다음 F3"Simple Operator ..."를 눌러 실행합니다. 애드온으로 변환하고 싶다면 애드온 상단에 "bl_info"라는 파이썬 사전을 추가하면됩니다 :https://wiki.blender.org/wiki/Process/Addons/Guidelines/metainfo


2.7x 버전에서 작동하도록하려면 Matrix Multiplication의 변경 사항 과 최신 버전에서 blf.color 를 사용하여 텍스트 색상을 설정하는 방법 으로 인해 2 줄을 바꿔야 합니다.

# 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