2025年7月9日水曜日

Blenderべジェ曲線の頂点インデックス(番号)表示

 Blender Bezier curve vertex index (number) display


Blender Bezier curve vertex index (number) display is now possible. This allows efficient and accurate manipulation of Bezier curves. This BlenderPython has been completed for the first time in a month.


Blenderべジェ曲線の頂点インデックス(番号)表示ができるようになりました。これでべジェ曲線の操作が効率的かつ正確にできるようになります。1カ月ぶりにこのBlenderPythonが完成しました。

1 Blenderべジェ曲線の頂点インデックス(番号)表示


Blenderべジェ曲線の頂点インデックス(番号)表示

この例は閉じたべジェ曲線で、0~77のインデックスが表示されています。

2 Blenderバージョン4.4.3用の頂点インデックス表示BlenderPythonスクリプト


import bpy
import blf
from bpy_extras import view3d_utils

handler = None

def draw_callback_px(self, context):
    obj = context.active_object
    if not obj or obj.type != 'CURVE' or obj.mode != 'EDIT':
        return

    region = context.region
    rv3d = context.space_data.region_3d
    curve = obj.data

    font_id = 0
    blf.size(font_id, 14)

    for spline in curve.splines:
        if spline.type != 'BEZIER':
            continue

        for i, bez in enumerate(spline.bezier_points):
            if not bez.select_control_point:
                continue

            # 3D位置 → スクリーン座標
            co_world = obj.matrix_world @ bez.co
            screen_coord = view3d_utils.location_3d_to_region_2d(region, rv3d, co_world)

            if screen_coord:
                blf.position(font_id, screen_coord.x, screen_coord.y, 0)
                blf.draw(font_id, str(i))

def register_draw_handler():
    global handler
    if handler is None:
        handler = bpy.types.SpaceView3D.draw_handler_add(
            draw_callback_px, (None, bpy.context), 'WINDOW', 'POST_PIXEL'
        )
        print("インデックス表示を開始しました。")

def unregister_draw_handler():
    global handler
    if handler is not None:
        bpy.types.SpaceView3D.draw_handler_remove(handler, 'WINDOW')
        handler = None
        print("インデックス表示を停止しました。")

class CURVE_OT_toggle_index_display(bpy.types.Operator):
    bl_idname = "curve.toggle_index_display"
    bl_label = "ベジェインデックス表示切り替え"

    def execute(self, context):
        if handler is None:
            register_draw_handler()
            self.report({'INFO'}, "表示開始")
        else:
            unregister_draw_handler()
            self.report({'INFO'}, "表示停止")
        return {'FINISHED'}

def register():
    bpy.utils.register_class(CURVE_OT_toggle_index_display)

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

if __name__ == "__main__":
    register()
    bpy.ops.curve.toggle_index_display()

3 頂点インデックス(番号)表示の意義

Blenderで、XY座標平面に縄文遺構の幾つかの縁取線をトレースし、それらの縁取線を該当する標高に移動し、その縁取線からアドオンCurves To Meshで3Dモデルを作成します。しかし、縁取線は等高線ではなく、標高が変化する線分です。その標高変化を表現するには、標高が判明している少数の頂点の間をトポロジー的に補間する必要があります。その補間作業のために、標高判明頂点を把握する必要があり、どうしても、全体の頂点インデックスが必要になります。

このBlenderPythonスクリプトにより、その頂点インデックスが3Dビューポートで一見して判るようになりました。

縄文遺構3Dモデル構築作業にとって重要な基礎ツールの一つができました。

4 メモ

このBlenderPythonスクリプトは1カ月程前にChatGPTにより作成チャレンジして、半分失敗しました。当時作成したスクリプトはBlenderバージョン3では使えましたが、バージョン4では使えませんでした。失敗した理由は、ChatGPTにBlenderバージョンを明示しなかったからであると推察します。

今回はBlenderバージョン4.4.3で使うことを前提に指示しました。ChatGPTとのやりとりの中で、Blenderバージョン4.4の特性に関する扱いが幾つか出てきました。このような経緯から、Blenderのバージョンを明示しなければ、今回も失敗していた可能性があります。


0 件のコメント:

コメントを投稿