fbx转bvh

文章介绍了如何使用BPy在Blender中读取FBX文件获取所有节点名,以及不同方法实现FBX转Bvh的过程,包括Mixamo、AutodeskMotionBuilder、iPiMotionCapture等工具,并提到了如何在第一帧添加T-pose。
摘要由CSDN通过智能技术生成

目录

bpy读取fbx获取所有节点名

fbx转bvh

bpy读取fbx,转bvh

其他fbx转bvh方法

Mixamo

bpy导入fbx,第一帧加上t-pose,t-pose有了,但是后面的动画丢了


bpy读取fbx获取所有节点名

bpy.ops.import_scene.fbx(filepath=fbx_in,axis_forward='Z', axis_up='Y')
armature = bpy.data.objects.get('Armature')  # 获取名为 "Armature" 的对象

if armature and armature.type == 'ARMATURE':
    # 使用.pose.bones来访问骨骼数据
    for bone in armature.pose.bones:
        print(bone.name)

fbx转bvh

c++ visual studio项目

https://github.com/zyndor/fbx2bvh

FBX SDK | Autodesk Platform Services

bpy读取fbx,转bvh

bpy直接转bvh后,丢失了根节点的平移和旋转信息

代码是读取fbx每帧根节点的平移和旋转信息

import bpy

# 假设已经导入了FBX文件
# fbx_filepath = 'path/to/your/fbx/file.fbx'
# bpy.ops.import_scene.fbx(filepath=fbx_filepath)

# 获取根节点
# 这里假设根节点为场景中的第一个对象
root_object = bpy.context.scene.objects[0]

# 确保根对象是选中的并且是活动对象
bpy.context.view_layer.objects.active = root_object
root_object.select_set(True)

# 获取动画数据
animation_data = root_object.animation_data

if animation_data is not None and animation_data.action is not None:
    fcurves = animation_data.action.fcurves
    for fcurve in fcurves:
        # fcurve.data_path 会告诉你这是位置动画还是旋转动画
        for keyframe_point in fcurve.keyframe_points:
            frame = keyframe_point.co[0]  # 关键帧的帧数
            value = keyframe_point.co[1]  # 关键帧的值
            # 根据 fcurve.data_path 和 index 处理位置或旋转值

# 导出BVH
bvh_filepath = 'path/to/export.bvh'
bpy.ops.export_anim.bvh(filepath=bvh_filepath, check_existing=True)

其他fbx转bvh方法

  1. Autodesk MotionBuilder:

    • Autodesk MotionBuilder是一个专业的3D字符动画软件,提供了强大的动画制作和编辑功能。它支持多种文件格式,包括FBX和BVH,因此可以用来转换文件格式。MotionBuilder更适用于专业用户,需要购买许可证。
  2. Mixamo:

    • Mixamo是Adobe提供的一个在线服务,它允许用户上传角色,自动绑定骨骼,并应用动作。Mixamo支持上传FBX格式的文件,并可以导出为多种格式,包括BVH。Mixamo适用于快速角色动画,但可能不支持所有FBX到BVH的高级转换需求。
  3. iPi Motion Capture:

    • iPi Motion Capture是一个基于视觉的动作捕捉软件,支持将录制的视频转换为动画。它可以导入FBX格式,并导出为BVH格式。这个工具适用于需要从真实动作生成动画的用户。
  4. AccuRIG (by AccuRIG):

    • AccuRIG是一个自动化的角色绑定和设置工具,可以将FBX文件导入,自动设置骨骼和权重,然后导出为多种动画格式,包括BVH。它提供了一个相对简单和自动化的流程来处理角色和动画。
  5. 在线转换工具:

    • 网络上也有一些在线服务提供FBX到BVH的转换,例如“AnyConv”、“CloudConvert”等。这些工具通常用户界面友好,但可能不提供高级的编辑或调整功能。
  6. 自定义脚本和库:

    • 对于具有编程经验的用户,可以使用如fbx2bvh这样的开源工具或库来进行转换。此外,使用Python的bpy模块(在Blender中)或其他语言的相应库,用户可以编写自定义脚本来精细控制转换过程。

Mixamo

GitHub - enziop/mixamo_converter: Blender addon for converting mixamo animations to Unreal 4 rootmotion

GitHub - Nor-s/mediapipe-to-mixamo: mediapipe landmark to mixamo skeleton

bpy导入fbx,第一帧加上t-pose,t-pose有了,但是后面的动画丢了

import os.path
import time

import bpy
import numpy as np


from img_read import ImgReader

name_mapping = {
        "f_avg_Pelvis": "Pelvis",
        "f_avg_L_Hip": "Left_hip",
        "f_avg_R_Hip": "Right_hip",
        "f_avg_Spine1": "Spine1",
        "f_avg_L_Knee": "Left_knee",
        "f_avg_R_Knee": "Right_knee",
        "f_avg_Spine2": "Spine2",
        "f_avg_L_Ankle": "Left_ankle",
        "f_avg_R_Ankle": "Right_ankle",
        "f_avg_Spine3": "Spine3",
        "f_avg_L_Foot": "Left_foot",
        "f_avg_R_Foot": "Right_foot",
        "f_avg_Neck": "Neck",
        "f_avg_L_Collar": "Left_collar",
        "f_avg_R_Collar": "Right_collar",
        "f_avg_Head": "Head",
        "f_avg_L_Shoulder": "Left_shoulder",
        "f_avg_R_Shoulder": "Right_shoulder",
        "f_avg_L_Elbow": "Left_elbow",
        "f_avg_R_Elbow": "Right_elbow",
        "f_avg_L_Wrist": "Left_wrist",
        "f_avg_R_Wrist": "Right_wrist",
        "f_avg_L_Hand": "Left_palm",
        "f_avg_R_Hand": "Right_palm",
        # Add more mappings as needed
    }


def reset_rotation_and_keyframe(obj, frame_number):
    # 设置当前帧
    bpy.context.scene.frame_set(frame_number)

    # 重置对象的旋转
    obj.rotation_euler = (0.0, 0.0, 0.0)

    # 插入旋转的关键帧
    obj.keyframe_insert(data_path="rotation_euler", frame=frame_number)
def reset_transforms_and_insert_keyframes(obj, frame_number):
    # 设置当前帧
    bpy.context.scene.frame_set(frame_number)

    # 重置对象的位置和旋转
    obj.location = (0.0, 0.0, 0.0)
    obj.rotation_euler = (0.0, 0.0, 0.0)

    # 插入位置和旋转的关键帧
    obj.keyframe_insert(data_path="location", frame=frame_number)
    obj.keyframe_insert(data_path="rotation_euler", frame=frame_number)

    # 递归调用此函数以处理所有子对象
    for child in obj.children:
        reset_transforms_and_insert_keyframes(child, frame_number)
def fbx_to_bvh(fbx_dir,order="ZXY",modify_node=False):

    imgReader = ImgReader(fbx_dir, suffix='fbx', if_dir=1)
    total_frames = imgReader.total_frames
    start = time.time()
    print('start convert bvh...', total_frames)

    save_bvh = True
    y_xishu = 1
    data_len=0
    for i in range(total_frames):
        fbx_in, img_i, img_path = imgReader.get_filename(i)
        # if "_m" not in fbx_in:
        #     continue
        data_len+=1

        bvh_out = os.path.dirname(fbx_in)+'/'+os.path.basename(fbx_in).split("_T")[0]+".bvh"

        print("data_len", data_len, i, fbx_in,bvh_out)
        bpy.ops.import_scene.fbx(filepath=fbx_in,axis_forward='Z', axis_up='Y')
        armature = bpy.data.objects.get('Armature')  # 获取名为 "Armature" 的对象

        if armature and armature.type == 'ARMATURE':
            bpy.context.view_layer.objects.active = armature
            bpy.ops.object.mode_set(mode='POSE')
            # 使用.pose.bones来访问骨骼数据
            for bone in armature.pose.bones:
                print(bone.name)
                bone.rotation_mode = 'XYZ'
                bone.rotation_euler = (0.0, 0.0, 0.0)
                bone.keyframe_insert(data_path="rotation_euler", frame=1)
            bpy.context.view_layer.update()
            bpy.ops.object.mode_set(mode='OBJECT')
        if modify_node:

            if armature and armature.type == 'ARMATURE':
                bpy.context.view_layer.objects.active = armature
                bpy.ops.object.mode_set(mode='EDIT')

                # 修改特定骨骼的名字
                for bone in armature.data.edit_bones:
                    if bone.name in name_mapping:
                        bone.name = name_mapping[bone.name]

                bpy.ops.object.mode_set(mode='OBJECT')


        bpy.context.view_layer.objects.active = armature
        # armature.select_set(True)
        #
        #
        # animation_data = armature.animation_data
        #
        # if animation_data is not None and animation_data.action is not None:
        #     fcurves = animation_data.action.fcurves
        #     for fcurve in fcurves:
        #         # fcurve.data_path 会告诉你这是位置动画还是旋转动画
        #         if "rotation" in fcurve.data_path: #or "location" in fcurve.data_path:
        #             for keyframe_point in fcurve.keyframe_points:
        #                 if keyframe_point.co[0] == 1:  # 第一帧
        #                     # 设置第一帧的关键帧值为0
        #                     keyframe_point.co[1] = 0.0
        #     bpy.context.view_layer.update()

        # 遍历所有对象
        # for obj in bpy.data.objects:
        #     # 只对网格和骨架对象进行操作
        #     if obj.type in ('MESH', 'ARMATURE'):
        #         reset_rotation_and_keyframe(obj, 1)
        # reset_transforms_and_insert_keyframes(armature, 0)

        character_object = bpy.context.active_object
        character_object.rotation_euler[1] += np.pi / 2  # 绕Y轴旋转90度

        # 确定动画范围
        action = armature.animation_data.action if armature.animation_data else None
        frame_start = action.frame_range[0] if action else 0
        frame_end = action.frame_range[1] if action else 1

        bpy.ops.export_anim.bvh(filepath=bvh_out, frame_start=int(frame_start), frame_end=int(frame_end), global_scale=100, rotate_mode=order, root_transform_only=True)

        if action:
            bpy.data.actions.remove(action)

        # 清理场景
        bpy.ops.object.select_all(action='SELECT')
        bpy.ops.object.delete()

def fbx_len(fbx_path):

    bpy.ops.import_scene.fbx(filepath=fbx_path, axis_forward='Z', axis_up='Y')

    frame_start = 100
    frame_end = -1
    action = bpy.data.actions[-1]
    frame_end = max(frame_end, action.frame_range[1])
    frame_start = min(frame_start, action.frame_range[0])
    print(frame_start,int(frame_end))

if __name__ == '__main__':
    fbx_dir=r"E:\tmp"

    # fbx_len(fbx_file)
    fbx_to_bvh(fbx_dir,order='ZXY',modify_node=0)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值