スポンサーリンク

| キーワード:

再考 Blender 2.8 pythonで矢印を作る

以前のコードが汎用性に欠けるというか使いにくかったのでもう一度書き直した。

Blender 2.8 pythonで矢印を作る

import bpy
import math
import mathutils

####################################################################
####################################################################
####################################################################
####################################################################
# @brief 任意軸回転
# @sa https://www.study.suzulang.com/bpy/bpy-arbitrary-axis-rotation
# @param [in,out] obj 回転するオブジェクト
# @param [in] axis 回転軸
# @param [in] radian 回転角をラジアンで指定
# @return なし
def rotate_object(obj,axis,radian):
    
    rot_mat= mathutils.Matrix.Rotation( radian, 4, axis ) 
    
    # decompose world_matrix's components, and from them assemble 4x4 matrices
    orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose()
    #
    orig_loc_mat   = mathutils.Matrix.Translation(orig_loc)
    orig_rot_mat   = orig_rot.to_matrix().to_4x4()
    orig_scale_mat = (mathutils.Matrix.Scale(orig_scale[0],4,(1,0,0)) @ 
                      mathutils.Matrix.Scale(orig_scale[1],4,(0,1,0)) @ 
                      mathutils.Matrix.Scale(orig_scale[2],4,(0,0,1)))
    #
    # assemble the new matrix
    obj.matrix_world = orig_loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat 

####################################################################
####################################################################
####################################################################
####################################################################
####################################################################
# @brief 指定した位置に矢印を作成
# @param [in] tail 矢印の根本
# @param [in] head 矢印の頭
# @param [in] body_radius 矢印根元の半径
# @return 作成した矢印のオブジェクト
def create_arrow(tail,head,body_radius):


    ###########################################
    ###########################################
    # tail->head の長さと方向を計算
    avec = head - tail
    aveclen = avec.length
    avec.normalize()

    ###########################################
    ###########################################
    # 回転軸と回転量
    zvec = mathutils.Vector([ 0.0 , 0.0 , 1.0])
    zvec.normalize()
    
    rotvec = mathutils.Vector.cross(zvec,avec)
    rotvec.normalize()
    rotang = math.acos(mathutils.Vector.dot(zvec,avec) )

    ###########################################
    ###########################################
    # 各パラメータ計算

    # bodyとheadの長さの比率
    head_ratio = 0.3
    
    # 頭部長さ変更
    head_length = aveclen * head_ratio
    
    # 頭部が長くなりすぎないように調整
    if head_length > 0.3*4:
        head_length = 0.3*4
    
    body_length = aveclen - head_length
    
    # 矢印の頭部分の付け根の大きさ(本体に対する倍率)
    head_root_ratio = 2.0

    ###########################################
    ###########################################
    # サークル追加
    # 半径は body_radius
    bpy.ops.mesh.primitive_circle_add(
        location=tail, 
        radius=body_radius
        )
        
    myarrow = bpy.context.object
    
    # 作成したサークルを回転して目標へ向ける
    rotate_object(myarrow,rotvec,rotang)

    #######################
    # サークルを面にする
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.fill()

    #######################
    # step 1 -    押し出し
    # 押し出し量は 矢印全体の長さ×比率
    bpy.ops.mesh.extrude_region_move(
        TRANSFORM_OT_translate={"value":avec*body_length } )

    #######################
    # step 2 -|   矢印頭部部分付け根拡大
    bpy.ops.mesh.extrude_region_move(
        TRANSFORM_OT_translate={"value":(0,0,0)} )
    bpy.ops.transform.resize(
        value=(
            head_root_ratio,
            head_root_ratio,
            head_root_ratio) )

    #######################
    # step 3 -|=  矢印頭部部分押し出し
    bpy.ops.mesh.extrude_region_move(
        TRANSFORM_OT_translate={"value":avec*head_length} )

    #######################
    # step 4 -|>  矢印を閉じる
    bpy.ops.transform.resize(value=(0,0,0) )

    bpy.ops.mesh.remove_doubles()

    bpy.ops.object.mode_set(mode='OBJECT')
    
    return myarrow


################################

#実行例
t = mathutils.Vector((1,2,1))#始点
h = mathutils.Vector((-1,2,3))#先端

arrow = create_arrow(t,h,0.1)

arrow.name = "my-arrow"
print (arrow)

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: