0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

選択面がレンダリングでどれくらいの大きさで表示されるか計算

0
Posted at

画面に貼り込むテクスチャを用意する場合に
どの程度の大きさで表示されるのか知っておきたいという局面が出たので
blenderアドオンを作成したのでメモ程度に

image.png

選択面の縦横をカメラ座標に投影したものをのバウンディングボックスを取得するだけのものです

calc_face2camera_pixels.py
bl_info = {
    "name": "Selected Face Camera Pixels",
    "author": "Yukimi",
    "version": (1, 1),
    "blender": (4, 0, 0),
    "location": "View3D > N Panel > Face Camera Pixels",
    "description": "アクティブカメラから見た選択面のピクセルサイズを表示",
    "category": "3D View",
}

import bpy
import bmesh
from bpy_extras.object_utils import world_to_camera_view

def calculate_face_pixels(context):
    """選択面のカメラ投影ピクセルサイズを計算"""
    obj = context.active_object
    if obj.mode != 'EDIT': return 0.0, 0.0
    
    bm = bmesh.from_edit_mesh(obj.data)
    selected_faces = [f for f in bm.faces if f.select]
    
    if not selected_faces: return 0.0, 0.0
    
    # 全頂点のワールド座標
    world_verts = [obj.matrix_world @ v.co for face in selected_faces for v in face.verts]
    
    if len(world_verts) < 2: return 0.0, 0.0
    
    # カメラ投影
    projected = []
    for v in world_verts:
        coord = world_to_camera_view(context.scene, context.scene.camera, v)
        if 0 <= coord.x <= 1 and 0 <= coord.y <= 1:  # 視野内のみ
            projected.append(coord)
    
    if len(projected) < 2: return 0.0, 0.0
    
    xs = [p.x for p in projected]
    ys = [p.y for p in projected]
    #bbox
    width_norm = max(xs) - min(xs)
    height_norm = max(ys) - min(ys)
    # レンダリング画像基準のサイズ
    render = context.scene.render
    width_px = width_norm * render.resolution_x
    height_px = height_norm * render.resolution_y
    
    return width_px, height_px


class Y_FACE_CAMERA_PIXELS_PT_panel(bpy.types.Panel):
    bl_label = "Face Camera Pixels"
    bl_idname = "FACE_CAMERA_PIXELS_PT_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Item"

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        obj = context.active_object

        box = layout.box()
        box.label(text="アクティブカメラからの投影サイズ", icon='CAMERA_DATA')        
        
        if not obj or obj.type == 'MESH':
            width, height = calculate_face_pixels(context)
            if not scene.camera:
                box.label(text="シーンにアクティブカメラがありません")
            else:
                if width > 0 or height > 0:
                    col = box.column(align=True)
                    col.label(text=f"Width:   {width:.1f} px")
                    col.label(text=f"Height:  {height:.1f} px")
                    col.label(text=f"Area:    {width * height:.1f} px²")
                else:
                    box.label(text="選択面がありません", icon='INFO')
                    box.label(text="Edit Modeで面を選択してください")
        else:
            self.report({'WARNING'}, "メッシュオブジェクトを選択してください")            


# 登録・解除
def register():
    bpy.utils.register_class(Y_FACE_CAMERA_PIXELS_PT_panel)


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


if __name__ == "__main__":
    register()

XのGrokで生成してみたものを微調整しました
自分でも作れましたが 一瞬でエラー処理も含めて動くものが出るのは改めてすごいものですね

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?