スポンサーリンク

Blender 2.8 pythonで矢印を作る

コード

import bpy
import math


from mathutils import Vector

from math import radians
from mathutils import Matrix

####################################################################
####################################################################
####################################################################
####################################################################
# rotate
# targetobjに現在のアクティブなオブジェクトを指定する
def rotate_object(targetobj,rot_mat):
    # decompose world_matrix's components, and from them assemble 4x4 matrices
    orig_loc, orig_rot, orig_scale = targetobj.matrix_world.decompose()
    #
    orig_loc_mat   = Matrix.Translation(orig_loc)
    orig_rot_mat   = orig_rot.to_matrix().to_4x4()
    orig_scale_mat = (Matrix.Scale(orig_scale[0],4,(1,0,0)) @ 
                      Matrix.Scale(orig_scale[1],4,(0,1,0)) @ 
                      Matrix.Scale(orig_scale[2],4,(0,0,1)))
    #
    # assemble the new matrix
    targetobj.matrix_world = orig_loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat 

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

#オブジェクトobjectのvid番目の頂点座標をグローバル座標で返す def get_coord_as_global(object,vid): v_local = object.data.vertices[vid].co # local vertex coordinate v_global = object.matrix_world @ v_local # global vertex coordinates return v_global
#objで指定したオブジェクトを元に矢印を作成 def create_arrow(obj): #parameters thickness_ratio = 0.03 head_ratio = 0.4 body_ratio = 1.0-head_ratio head_root_ratio = 2; zvec = Vector([ 0.0 , 0.0 , 1.0]) zvec.normalize() avec = get_coord_as_global(obj,1) - get_coord_as_global(obj,0) aveclen = avec.length avec.normalize() rotvec = Vector.cross(zvec,avec) rotvec.normalize() rotang = math.acos(Vector.dot(zvec,avec) ) globalpos = get_coord_as_global(obj,0) #add a circle bpy.ops.mesh.primitive_circle_add(location=globalpos, radius=aveclen*thickness_ratio) mycircle = bpy.context.object rotate_object(mycircle,Matrix.Rotation(rotang,4,rotvec)) ######################################### # extrude bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.fill() # step 1 - oshidashi bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":avec*aveclen*body_ratio} ) # step 2 -| oshidasi&scale 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 -|= oshidashi bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":avec*aveclen*head_ratio} ) # step 4 -|> bpy.ops.transform.resize(value=(0,0,0) ) bpy.ops.mesh.remove_doubles() bpy.ops.object.mode_set(mode='OBJECT') #現在選択中のオブジェクトを取得 obj = bpy.context.active_object
#objの第0頂点->第1頂点を示す矢印オブジェクトを新規作成 create_arrow(obj)

使い方

頂点が二つ以上あるオブジェクトを選択した状態でこのスクリプトを走らせると、第0頂点->第1頂点の矢印が新規オブジェクトとして生成される

説明

1.オブジェクトの2頂点を取得し、ベクトル化

    avec = get_coord_as_global(obj,1) - get_coord_as_global(obj,0)
    aveclen = avec.length
    avec.normalize()

※get_coord_as_globalは自作関数

2.ベクトル(0,0,1)と、先に求めたベクトルの外積で回転軸を、内積のacosで回転角を求める

    zvec = Vector([ 0.0 , 0.0 , 1.0])
    zvec.normalize()
    rotvec = Vector.cross(zvec,avec)
    rotvec.normalize()
    rotang = math.acos(Vector.dot(zvec,avec) )

3.第0頂点の位置にCircleを新規作成

    globalpos = get_coord_as_global(obj,0)

    #add a circle
    bpy.ops.mesh.primitive_circle_add(location=globalpos, radius=aveclen*thickness_ratio)
    mycircle = bpy.context.object

4.Circleを2で求めた角度と回転軸で回転

    rotate_object(mycircle,Matrix.Rotation(rotang,4,rotvec))

※rotate_objectは自作関数

5.Editモードに入り、Circleをメッシュ化

    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.fill()

5.Editモードに入り、Circleを押し出し

    # step 1 -    oshidashi
    bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":avec*aveclen*body_ratio} )

6.押し出した頂点をそのまま方向(0,0,0)で押し出し、やや拡大

    # step 2 -|   oshidasi&scale
    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) )

7.さらに押し出し

    # step 3 -|=  oshidashi
    bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":avec*aveclen*head_ratio} )

8.押し出した頂点をmerge at centerする

    # step 4 -|>
    bpy.ops.transform.resize(value=(0,0,0) )

    bpy.ops.mesh.remove_doubles())

コメントを残す

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

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


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