アストラルプリズム

PC、スマホ、ゲームなどの備忘録と日記

Blender python マトリックスワールドで回転させる

図の通り、回転する軸を指定して回転させたい

f:id:katsumi3:20200112232734p:plain

手動の場合

編集モードで回転させたい軸を選択して
メッシュ→スナップ→カーソル→選択物
にして

f:id:katsumi3:20200114232715p:plain
トランスフォームピポットポイントを3Dカーソルにして
f:id:katsumi3:20200114233005p:plain
後はrを押して回転させればいい。

pythonスクリプトの場合

bpy.bpy.ops.transform.rotateを使う場合

f:id:katsumi3:20200115002002p:plain
上の頂点の座標pが

p=(0.069568,-1.3847,-1.0381)

のとき

ノーマル座標を使う場合
bpy.ops.transform.rotate(
        value = radians(45),
        orient_axis = "Y",
        orient_type = 'NORMAL',
        center_override = p
        )
ローカル座標を使う場合
bpy.ops.transform.rotate(
        value = radians(45),
        orient_axis = "Z",
        orient_type = 'LOCAL',
        center_override = p
        )
オブジェクトの向きを使う場合
obj = bpy.context.object
orig_mat = obj.matrix_world
bpy.ops.transform.rotate(
        value = radians(45),
        orient_axis = "Z",
        orient_matrix = orig_mat.to_3x3(),
        center_override = p
        )

#radiansはテキストエディタだと
from math import radians
しないといけない

matrix_worldを使う場合

マトリックスワールドの勉強にためにやったが長くなるし正直bpy.ops系を使った方が短くて良い気がする・・・

回転する軸はvertices[0]と[1]で回転させたい面は選択してある状態とする。

import bpy 
from math import radians
from mathutils import Matrix

obj = bpy.context.active_object 
orig_mat = obj.matrix_world 
rot_mat = Matrix.Rotation(radians(-45),4,(orig_mat[0][2],orig_mat[1][2],orig_mat[2][2]))

msh = bpy.data.meshes[obj.data.name]
p1 = orig_mat @ ((msh.vertices[0].co + msh.vertices[1].co) / 2)
p0 = (msh.vertices[0].co + msh.vertices[1].co) / 2

orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose() 
loc_mat =  Matrix.Translation(p1) 
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)) 

#指定した座標を回転の中心にする
new_mat = loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat
inv = orig_mat.copy()
inv.invert()
id = msh.polygons.active
verts = msh.polygons[id].vertices[0:]
for v_id in verts:
    v = msh.vertices[v_id]
    v.co = inv @ (new_mat @ (v.co - p0))
オブジェクトごと回転させる場合
import bpy 
from math import radians
from mathutils import Matrix

obj = bpy.context.active_object 
orig_mat = obj.matrix_world

rot_mat = Matrix.Rotation(radians(-45),4,(orig_mat[0][2],orig_mat[1][2],orig_mat[2][2])) 

msh = bpy.data.meshes[obj.data.name]
p1=orig_mat @ ((msh.vertices[0].co + msh.vertices[1].co) / 2)
p0=(msh.vertices[0].co + msh.vertices[1].co) / 2
 
orig_loc, orig_rot, orig_scale = obj.matrix_world.decompose() 
loc_mat =  Matrix.Translation(p1) 
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)) 


new_mat = loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat
pn = new_mat @ p0
pn = new_mat.to_translation() - pn
loc_mat =  Matrix.Translation(pn)
obj.matrix_world = loc_mat @ new_mat