มุมมอง 3 มิติ - จะแสดงข้อมูลกล้องในกรอบกล้องได้อย่างไร?

Aug 17 2020

มีวิธีใช้ตัวเลือกการแสดงเช่น "ข้อมูลวัตถุ" หรือ "ชื่อมุมมอง" (ในการตั้งค่าของวิวพอร์ต) เพื่อแสดงข้อมูลอื่น ๆ เช่นโฟกัสความยาวของกล้องที่ใช้งานอยู่และตำแหน่งของกล้อง และมีวิธีย้ายข้อมูลนี้ไปที่ใดในหน้าต่าง 3d หรือไม่? เช่นในตัวอย่างนี้:

ดังนั้นฉันจึงพบสคริปต์ที่ช่วยให้ฉันแสดงจุดโฟกัสบนหน้าต่าง 3 มิติ

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ของ python และสร้างส่วนเสริมของคุณเอง โค้ดตัวอย่างต่อไปนี้เป็นไปตามเทมเพลต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()

คัดลอกและวางสคริปต์ลงในโปรแกรมแก้ไขข้อความเรียกใช้เลื่อนไปที่มุมมอง 3 มิติกดF3และพิมพ์ "ตัวดำเนินการแบบง่าย ... " เพื่อดำเนินการ หากคุณต้องการแปลงเป็น Add-on เพียงเพิ่มพจนานุกรม python ชื่อ "bl_info" ที่ด้านบนของ addon ของคุณ:https://wiki.blender.org/wiki/Process/Addons/Guidelines/metainfo


เพื่อให้ใช้งานได้กับเวอร์ชัน 2.7xคุณจะต้องแทนที่ 2 บรรทัดเนื่องจากการเปลี่ยนแปลงในการคูณเมทริกซ์และวิธีการตั้งค่าสีข้อความโดยใช้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