アストラルプリズム

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

Blender python オブジェクトの一番下にエンプティを置く

自作アドオンで何回か使いそうな気がするのでいくつか作っておこうと思う

  • オブジェクトの原点にてエンプティを置く(回転はローカル座標の回転方向)
  • オブジェクトの中心にエンプティを置く(回転はローカル座標の回転方向)
  • オブジェクトの一番下の辺の真ん中にエンプティを置く(回転はローカル座標の回転方向)
  • オブジェクトの一番下の辺の真ん中にエンプティを置く(回転は面の向きに合わせる(板ポリの場合のみ有効))

オブジェクトの原点にエンプティを置く

回転はローカル座標の回転方向
f:id:katsumi3:20200303010853p:plain

import bpy

obj = bpy.context.view_layer.objects.active
mat = obj.matrix_world

bpy.ops.object.empty_add(type='ARROWS', location=(0, 0, 0))
emp = bpy.context.view_layer.objects.active
emp.matrix_world = mat

for s in bpy.context.object.scale:
     s = 1

オブジェクトの中心にエンプティを置く

回転はローカル座標の回転方向
面だけならbmeshにbm.face.calc_center_median()という便利なものもあるがここでは使わない
f:id:katsumi3:20200303011221p:plain

import bpy 
from mathutils import Vector, Matrix
obj = bpy.context.view_layer.objects.active
mat = obj.matrix_world

x = []
y = []
z = []

for v in obj.data.vertices:
    x.append(v.co.x)
    y.append(v.co.y)
    z.append(v.co.z)

emp_x = min(x)+(max(x)-min(x))/2
emp_y = min(y)+(max(y)-min(y))/2
emp_z = min(z)+(max(z)-min(z))/2

emp_p = mat @ Vector((emp_x,emp_y,emp_z))

bpy.ops.object.empty_add(type='ARROWS', location=(0,0,0))
emp = bpy.context.object
mat_emp = mat.copy()
mat_emp[0][3]=emp_p[0]
mat_emp[1][3]=emp_p[1]
mat_emp[2][3]=emp_p[2]
emp.matrix_world = mat_emp

for s in bpy.context.object.scale:
    s = 1

オブジェクトの一番下の辺の真ん中にエンプティを置く

上下の定義は人によると思うがここではz軸とする
回転はローカル座標の回転方向
f:id:katsumi3:20200303010434p:plain

x = []
y = []
z = []

for e in obj.data.edges:
    id_0 = e.vertices[0]
    id_1 = e.vertices[1]
    v = obj.data.vertices
    c_p = mat @ v[id_1].co +(mat @ v[id_0].co-mat @ v[id_1].co)/2
    x.append(c_p[0])
    y.append(c_p[1])
    z.append(c_p[2])


id = z.index(min(z))
emp_x = x[id]
emp_y = y[id]
emp_z = min(z)

emp_p = Vector((emp_x,emp_y,emp_z))

bpy.ops.object.empty_add(type='ARROWS', location=(0,0,0))
emp = bpy.context.object
mat_emp = mat.copy()

mat_emp[0][3]=emp_p[0]
mat_emp[1][3]=emp_p[1]
mat_emp[2][3]=emp_p[2]
emp.matrix_world = mat_emp

for s in emp.scale:
    s = 1

オブジェクトの一番下の辺の真ん中にエンプティを置く

回転は面の向きに合わせる(オブジェクトが一枚の板ポリの場合のみ有効)
f:id:katsumi3:20200303210616p:plain

import bpy 
from mathutils import Vector, Matrix
obj = bpy.context.view_layer.objects.active
mat = obj.matrix_world
msh = obj.data

x = []
y = []
z = []

for e in msh.edges:
    id_0 = e.vertices[0]
    id_1 = e.vertices[1]
    v = msh.vertices
    c_p = (mat @ v[id_0].co + mat @ v[id_1].co)/2
    x.append(c_p[0])
    y.append(c_p[1])
    z.append(c_p[2])


id = z.index(min(z))
emp_x = x[id]
emp_y = y[id]
emp_z = min(z)

emp_p = Vector((emp_x,emp_y,emp_z))

m_id_0 = msh.edges[id].vertices[0]
m_id_1 = msh.edges[id].vertices[1]
muki = (mat@msh.vertices[m_id_0].co - mat@msh.vertices[m_id_1].co)
mw_rot = mat.decompose()[1]
norm = msh.polygons[0].normal

mx_inv = mat.inverted()
mx_norm = mx_inv.transposed().to_3x3()
world_norm = mx_norm @ norm
world_norm.normalize()

cro = muki.cross(world_no)
cro.normalize()
muki.normalize()

bpy.ops.object.empty_add(type='ARROWS', location=(0,0,0))

emp = bpy.context.object
moto_mat=emp.matrix_world

mat_emp = Matrix([[muki.x, -cro.x,world_norm.x, emp_p[0]],
                                [muki.y, -cro.y, world_norm, emp_p[1]],
                                [muki.z, -cro.z, world_norm.z, emp_p[2]], [0, 0, 0, 1]])

emp.matrix_world = moto_mat @ mat_emp