ラベル べジェ曲線 の投稿を表示しています。 すべての投稿を表示
ラベル べジェ曲線 の投稿を表示しています。 すべての投稿を表示

2025年7月19日土曜日

技術メモ べジェ曲線を使った単純モデリング

 Technical memo: Simple modeling using Bezier curves


I made a note of the steps to model simple shapes such as pits. Draw the border line with a Bezier curve, and reuse it to create individual unit terrain surfaces using the add-on Curves To Mesh function.


土坑等の単純形をモデリングする際の手順をメモしました。縁取線をべジェ曲線で描き、それを使いまわしながら、アドオンCurves To Mesh機能により単位地形面を個別に造形します。

1 単位地形面を2本のべジェ曲線で造形する

全ての単位地形面を2本のべジェ曲線の間を面張りすることによって表現することにします。面張りの実務はアドオンCurves To Meshにより行うものとします。

べジェ曲線の平面座標は資料平面図から、高さ座標は資料断面図から補間により獲得します。

2025.07.11記事「縄文遺構実測図の縁取線(地形変換線)の高度線形補間Blenderアドオン

2 縁取線をべジェ曲線で描く

全ての単位地形面の縁取線をべジェ曲線で描きます。


べジェ曲線による縁取線描画結果

作業の順番は、斜面造形を優先して行うことにします。斜面造形がしやすいようにべジェ曲線描画を工夫します。


べジェ曲線の描画単位

土坑を巡る斜面はべジェ曲線abに、段差斜面はべジェ曲線cdに対応します。

3 単位地形面の造形


造形結果


造形結果(単位地形面)

アドオンCurves To Meshにより、斜面1はべジェ曲線abから、斜面2はべジェ曲線cdから直接造形できます。

平坦面3はべジェ曲線bの一部とべジェ曲線cから造形します。

なお、べジェ曲線を使いまわす際、そのコピーはShift+Dで行います。(コピー元とコピー先にリンク関係が生じないようにするため。)

べジェ曲線の分離は編集モードで分離したい部分を指定してからPで行います。

平坦面4の造形はべジェ曲線d、bの一部(2箇所)、eを2本のべジェ曲線に整理してから、造形します。

ここではべジェ曲線bの一部(2箇所)とeを1本に統合しました。


造形結果

4 感想

斜面と平坦面という単位地形面毎に一つ一つ造形する手間をかけないと、結局望むレベルのモデリングができないことを認識しました。

なお、土坑の中の穴については、Blender合成により対応できます。

2025.07.15記事「土坑SK773A/B(千葉市有吉北貝塚)3Dモデル



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のバージョンを明示しなければ、今回も失敗していた可能性があります。