bone_widget/transform_utils.py

82 lines
2.2 KiB
Python

import bpy
from mathutils import Matrix, Vector
def get_bone_size_factor(bone, ob, relative=True):
world_box = [ob.matrix_world @ Vector(co) for co in ob.bound_box]
height = (world_box[1]-world_box[0]).length
depth = (world_box[3]-world_box[0]).length
width = (world_box[4]-world_box[0]).length
'''
length = height
if height < 0.001:
if depth > 0.001:
length = depth
elif width > 0.001:
length = width
'''
length = max((height, depth, width))
size_factor = 1 / length
if relative:
size_factor /= bone.bone.length
return size_factor
def transform_matrix(loc=(0, 0, 0), rot=(0, 0, 0), scale=(1, 1, 1)):
l_mat = Matrix.Translation(Vector(loc))
rx_mat = Matrix.Rotation(rot[0], 4, 'X')
ry_mat = Matrix.Rotation(rot[1], 4, 'Y')
rz_mat =Matrix.Rotation(rot[2], 4, 'Z')
r_mat = rz_mat @ ry_mat @ rx_mat
sx_mat = Matrix.Scale(scale[0], 4, Vector((1,0,0)))
sy_mat = Matrix.Scale(scale[1], 4, Vector((0,1,0)))
sz_mat = Matrix.Scale(scale[2], 4, Vector((0,0,1)))
s_mat = sx_mat @ sy_mat @ sz_mat
return l_mat @ r_mat @ s_mat
def get_bone_matrix(bone):
bone_mat = bone.matrix
if bone.custom_shape_transform:
bone_mat = bone.custom_shape_transform.matrix
bone_mat = bone_mat @ transform_matrix(scale=(bone.bone.length,)*3)
bone_mat = bone.id_data.matrix_world @ bone_mat
return bone_mat
def apply_mat_to_verts(data, mat, coords=None):
if coords is None:
coords = [v.co for v in data.vertices]
coords = [v for co in coords for v in mat @ co]
data.vertices.foreach_set('co', coords)
data.update()
def transform_mesh(data, loc, rot, scale, xz_scale, size, slide, coords=None):
if coords is None:
coords = [0]*len(data.vertices)*3
data.vertices.foreach_get('co', coords)
sx = scale[0] * size * xz_scale
sy = scale[1] * size
sz = scale[2] * size * xz_scale
l_vec = loc + Vector((0, slide, 0))
mat = transform_matrix(l_vec, rot, (sx, sy, sz))
data.vertices.foreach_set('co', coords)
data.transform(mat)
#apply_mat_to_verts(data, mat, coords)