blender 动画制作常用的脚本

如果想查看脚本的错误情况,可以
在这里插入图片描述

一些关于动画的操作

获得 blendshape 形态键的名字

作用 unity 使用的时候是通过序号来控制bs的,通过这里设置序号

objname='M_Head'
objname='M_LowerJaw'
keyList = bpy.data.objects[objname].data.shape_keys.key_blocks

arr=[]
for i in range(0, len(keyList) ):
    print( i,  keyList[i].name )
    arr.append( keyList[i].name )

SMPL数据驱动模型

主要保证每个骨骼坐标系一致,按照OGL,然后强行转换,这里省去了重定向的过程。

import numpy as np
import os
import bpy
from scipy.spatial.transform import Rotation as sciR
# short-key alt+p
from mathutils import Euler

from bpy import context
import builtins as __builtin__

def console_print(*args, **kwargs):
    for a in context.screen.areas:
        if a.type == 'CONSOLE':
            c = {}
            c['area'] = a
            c['space_data'] = a.spaces.active
            c['region'] = a.regions[-1]
            c['window'] = context.window
            c['screen'] = context.screen
            s = " ".join([str(arg) for arg in args])
            for line in s.split("\n"):
                bpy.ops.console.scrollback_append(c, text=line)

def print(*args, **kwargs):
    """Console print() function."""

    console_print(*args, **kwargs) # to py consoles
    __builtin__.print(*args, **kwargs) # to system console



class Cls_smpl2skeleton:
    def __init__(self, fbones2smpl): 
        self.NJ = 24
        self.cord_cvt = sciR.from_rotvec( np.array([1, 0, 0])*np.deg2rad(-90) ).as_matrix()
        self.bons_name=np.loadtxt( fbones2smpl , dtype=str).tolist()
        
    
    def get_N_eye(self, N, m=3):
        mats = [ np.eye(m) for i in range(N) ]
        return np.array(mats)
    
    def cvt_R_smpl2my(self, t3d, pose, intp, outp):
        N, J, *arr_d = pose.shape
        assert J == self.NJ
        if intp==0:
            pose = sciR.from_rotvec( pose.reshape(-1, 3) ).as_matrix().reshape(N, J, 3, 3)
        if outp == 0:
            return t3d, sciR.from_matrix( pose.reshape(-1, 3, 3) ).as_rotvec().reshape(N, J, 3)
        else:
            return t3d, pose

    def rotvec2ang_axis(self, vec, isdeg=False):
        ang = np.linalg.norm( vec, axis=1 )
        axis = vec.copy()
        ids = ang!=0
        axis[ids] /= ang[ids, np.newaxis]
        if isdeg:
            ang = np.rad2deg( ang ).reshape(-1, 1)
        ang = ang.reshape(-1, 1)
    
        #rotvec = np.hstack( (axis, ang) )
        rotvec = np.hstack( (ang, axis) )
        return rotvec

    def example(self, fpm):
        pm = np.load(fpm)
        
        arr_t, arr_p = pm[:, :3], pm[:, 3:].reshape(-1, self.NJ, 3)
        
        arr_t[:, 1] += params.add_pos
        NF = len(arr_t)
        pose=arr_p
        # 
        t3d, pose = self.cvt_R_smpl2my(arr_t, pose, 0, 0 )
        rot = self.rotvec2ang_axis( pose.reshape(-1, 3) ).reshape( len(pose), -1, 4 )
        rot = rot.reshape( NF, -1 )
        pm = np.concatenate( (arr_t, rot), axis=1 )
        #pm = np.concatenate( (arr_t/100, rot), axis=1 )
        return pm
    

class params:
    add_pos= -1.76
    t_scale = 100
    pass
    
def f2_set_keyframe_animation():
    fbx_ske_nm = "Armature"
    fbone_names = 'bones2smpl_fengqin.txt'
    fpm = 'test.npy'
    smpl2skeleton = Cls_smpl2skeleton(fbone_names)
    pms = smpl2skeleton.example( fpm )
    params.pms = pms
    params.NJ = smpl2skeleton.NJ
    
    params.pms_t3d_rt = np.einsum( "ca,na->nc", smpl2skeleton.cord_cvt, pms[:, :3] )
    #t3d = 
    
    ob = bpy.data.objects[fbx_ske_nm]
    params.actor_ob = ob
    
    bpy.app.handlers.frame_change_pre.clear()
   
    bpy.context.view_layer.objects.active = ob #相当于鼠标左键选中
    bpy.ops.object.mode_set(mode='POSE') #切换为pose更改模式
    
    arr = [] 
    bones = []
    bons_name = smpl2skeleton.bons_name
    for i in range( len(bons_name) ):
        bnm = bons_name[ i ]
        bone=ob.pose.bones[bnm] 
        bone.rotation_mode = 'AXIS_ANGLE' #'XYZ'
        bones.append( bone )
        if i==0:
            arr.append( bone.location.copy() )
        arr.append( bone.rotation_axis_angle )  # tuple arr
    #print( [ e[:] for e in arr ] )
    params.T_pose = arr
    params.bones = bones
    
    nframe = len(pms)
    bpy.context.scene.frame_current = 1
    bpy.context.scene.frame_end = nframe
    bpy.context.scene.render.fps = 60
    set_key_frame(nframe)


def set_key_frame(nframe):
    NJ = params.NJ
    bones = params.bones
    actor = params.actor_ob
    #actor_body = params.actor_ob_body
    for rcnt in range(1, nframe+1, 1 ):
        pm = params.pms[rcnt-1]
        for i in range(NJ-1, -1, -1):
            a = 3+i*4
            bones[i].rotation_axis_angle = tuple(pm[a:a+4].tolist())
            bones[i].keyframe_insert(data_path="rotation_axis_angle", frame=rcnt)
        bones[0].location = pm[:3] * params.t_scale
        #print(bones[0].location)
        #bones[0].location = (0, 100, 0)
        bones[0].keyframe_insert(data_path="location", frame=rcnt)


os.chdir( 'D:/myprog/2022-7-20-shortv/1.material/temp_try' )

f2_set_keyframe_animation()
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值