スポンサーリンク

| キーワード:

Blender PythonでEmpty Arrowを二点座標指定して追加

from → to を指すempty arrowを追加する。以下では、現在のアクティブオブジェクトのoriginから3D cursorへ矢印を作成する

import bpy
import math
import numpy
import mathutils

# @brief オブジェクトを指定座標へ向けるための回転軸と回転角を計算する
# @param [in] オブジェクト
# @param [in] 向ける方向(座標)
# @return 回転軸,回転角(ラジアン)
def calc_lookat_param(obj,lookat):
    
    # オブジェクトのローカルのZ軸のベクトルを取得
    mat = obj.matrix_world
    localZ = mathutils.Vector((mat[0][2],mat[1][2],mat[2][2]))
    
    print(localZ)
    
    va = mathutils.Vector(lookat) - obj.location
    vb = mathutils.Vector(localZ)
    
    va.normalize()
    vb.normalize()
    
    # 外積
    axis = mathutils.Vector.cross(va,vb)
    axis.normalize()
    
    # 内積
    th = mathutils.Vector.dot(va,vb)
    
    # 角度算出
    rad = -math.acos( numpy.clip(th,-1.0,1.0) )

    return axis , rad
    

    
# @brief 任意軸回転
# @param [in,out] obj 回転するオブジェクト
# @param [in] axis 回転軸
# @param [in] radian 回転角をラジアンで指定
# @return なし
# @sa https://www.study.suzulang.com/bpy-calculation/bpy-arbitrary-axis-rotation
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 _fromから_toを指すEmptyArrowを作成
# @param [in] 矢印の根元の座標
# @param [in] 矢印の先端の座標
# @return 作成したオブジェクト
def make_empty_arrow(_from,_to):


    # 新しいEmpty ObjectのArrowを作成
    bpy.ops.object.empty_add(type="SINGLE_ARROW",location=_from)
    aobj = bpy.context.object

    # 方向を一致させるためのパラメータ取得
    axis , rad = calc_lookat_param(aobj,_to)

    # 回転
    rotate_object(aobj,axis,rad)

    # _from → _to の距離を計算
    objlen = ( _from - _to ).length

    # 矢印の長さ==スケール
    aobj.scale[0] = objlen
    aobj.scale[1] = objlen
    aobj.scale[2] = objlen
    
    return aobj
# 使用例
obj = bpy.context.active_object

arrow = make_empty_arrow(
    obj.location,
    bpy.context.scene.cursor.location
)

print(arrow.name)

コメントを残す

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

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


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