maya打开bvh脚本

news2024/9/20 20:30:53

目录

maya打开脚本编辑器

运行打开bvh脚本

maya导出bvh脚本


maya打开脚本编辑器

打开Maya软件,点击右下角 “脚本编辑器”

运行打开bvh脚本

https://github.com/jhoolmans/mayaImporterBVH/blob/master/bvh_importer.py

import os
import re
from typing import Optional

import maya.cmds as mc

space_re = re.compile(r"\s+")

# This maps the BVH naming convention to Maya
translationDict = {
    "Xposition": "translateX",
    "Yposition": "translateY",
    "Zposition": "translateZ",
    "Xrotation": "rotateX",
    "Yrotation": "rotateY",
    "Zrotation": "rotateZ"
}


class TinyDAG(object):
    """
    Tiny DAG class for storing the hierarchy of the BVH file.
    """

    def __init__(self, obj: str, parent: Optional["TinyDAG"] = None):
        """Constructor"""
        self.obj = obj
        self.__parent = parent

    @property
    def parent(self):
        """Returns the parent of the object"""
        return self.__parent

    def __str__(self) -> str:
        """String representation of the object"""
        return str(self.obj)

    def full_path(self) -> str:
        """Returns the full path of the object"""
        if self.parent is not None:
            return "%s|%s" % (self.parent.full_path(), str(self))
        return str(self.obj)


class BVHImporterDialog(object):
    """
    BVH Importer Dialog

    This class is the main dialog for the BVH importer.
    """

    def __init__(self, debug=False):
        self._name = "bvhImportDialog"
        self._title = "BVH Importer v2.0"

        if debug:
            print("Debug is deprecated.")

        # UI related
        self._textfield = ""
        self._scale_field = ""
        self._frame_field = ""
        self._rotation_order = ""
        self._reload = ""

        # Other
        self._root_node = None  # Used for targeting

        # BVH specific stuff
        self._filename = ""
        self._channels = []

        self.setup_ui()

    def setup_ui(self):
        """
        Builds the UI
        """
        win = self._name
        if mc.window(win, ex=True):
            mc.deleteUI(win)

        # Non sizeable dialog
        win = mc.window(self._name, title=self._title, w=200, rtf=True,
                        sizeable=False)

        mc.columnLayout(adj=1, rs=5)
        mc.separator()
        mc.text("Options")
        mc.separator()

        mc.rowColumnLayout(numberOfColumns=2,
                           columnWidth=[(1, 80), (2, 150)],
                           cal=[(1, "right"), (2, "center")],
                           cs=[(1, 5), (2, 5)],
                           rs=[(1, 5), (2, 5)])

        mc.text("Rig scale")
        self._scale_field = mc.floatField(minValue=0.01, maxValue=2, value=1)
        mc.text("Frame offset")
        self._frame_field = mc.intField(minValue=0)
        mc.text("Rotation Order")
        self._rotation_order = mc.optionMenu()
        mc.menuItem(label='XYZ')
        mc.menuItem(label='YZX')
        mc.menuItem(label='ZXY')
        mc.menuItem(label='XZY')
        mc.menuItem(label='YXZ')
        mc.menuItem(label='ZYX')

        mc.setParent("..")
        mc.separator()

        # Targeting UI
        mc.text("Skeleton Targeting")
        mc.text("(Select the hips)")
        mc.separator()

        mc.rowColumnLayout(numberOfColumns=2,
                           columnWidth=[(1, 150), (2, 80)],
                           cs=[(1, 5), (2, 5)],
                           rs=[(1, 5), (2, 5)])

        self._textfield = mc.textField(editable=False)
        mc.button("Select/Clear", c=self._on_select_root)

        mc.setParent("..")
        mc.separator()
        mc.button("Import..", c=self._on_select_file)
        self._reload = mc.button("Reload", enable=False, c=self._read_bvh)

        # Footer
        mc.text("by Jeroen Hoolmans")

        mc.window(win, e=True, rtf=True, sizeable=False)
        mc.showWindow(win)

    def _on_select_file(self, e):
        """
        Callback for the import button.
        """
        file_filter = "All Files (*.*);;Motion Capture (*.bvh)"
        result = mc.fileDialog2(fileFilter=file_filter, dialogStyle=1, fm=1)

        if result is None or not len(result):
            return

        self._filename = result[0]

        mc.button(self._reload, e=True, enable=True)

        # Action!
        self._read_bvh()

    def load_bvh(self, filename):
        self._filename = filename
        self._read_bvh()

    def _read_bvh(self, *_args):
        # Safe close is needed for End Site part to keep from setting new
        # parent.
        safe_close = False
        # Once motion is active, animate.
        motion = False
        # Clear channels before appending
        self._channels = []

        # Scale the entire rig and animation
        rig_scale = mc.floatField(self._scale_field, q=True, value=True)
        frame = mc.intField(self._frame_field, q=True, value=True)
        rot_order = mc.optionMenu(self._rotation_order, q=True, select=True) - 1

        with open(self._filename) as f:
            # Check to see if the file is valid (sort of)
            if not f.readline().startswith("HIERARCHY"):
                mc.error("No valid .bvh file selected.")
                return False

            if self._root_node is None:
                # Create a group for the rig, easier to scale.
                # (Freeze transform when ungrouping please..)
                mocap_name = os.path.basename(self._filename)
                grp = mc.group(em=True, name="_mocap_%s_grp" % mocap_name)
                mc.setAttr("%s.scale" % grp, rig_scale, rig_scale, rig_scale)

                # The group is now the 'root'
                my_parent = TinyDAG(grp, None)
            else:
                my_parent = TinyDAG(self._root_node, None)
                self._clear_animation()

            for line in f:
                line = line.replace("	", " ")  # force spaces
                if not motion:
                    # root joint
                    if line.startswith("ROOT"):
                        # Set the Hip joint as root
                        if self._root_node:
                            my_parent = TinyDAG(str(self._root_node), None)
                        else:
                            my_parent = TinyDAG(line[5:].rstrip(), my_parent)
                            # Update root node in case we want to reload.
                            self._root_node = my_parent
                            mc.textField(self._textfield,
                                         e=True,
                                         text=my_parent.full_path())

                    if "JOINT" in line:
                        jnt = space_re.split(line.strip())
                        # Create the joint
                        my_parent = TinyDAG(jnt[1], my_parent)

                    if "End Site" in line:
                        # Finish up a hierarchy and ignore a closing bracket
                        safe_close = True

                    if "}" in line:
                        # Ignore when safeClose is on
                        if safe_close:
                            safe_close = False
                            continue

                        # Go up one level
                        if my_parent is not None:
                            my_parent = my_parent.parent
                            if my_parent is not None:
                                mc.select(my_parent.full_path())

                    if "CHANNELS" in line:
                        chan = line.strip()
                        chan = space_re.split(chan)

                        # Append the channels that are animated
                        for i in range(int(chan[1])):
                            self._channels.append("%s.%s" % (
                                my_parent.full_path(),
                                translationDict[chan[2 + i]]
                            ))

                    if "OFFSET" in line:
                        offset = line.strip()
                        offset = space_re.split(offset)
                        jnt_name = str(my_parent)

                        # When End Site is reached, name it "_tip"
                        if safe_close:
                            jnt_name += "_tip"

                        # skip if exists
                        if mc.objExists(my_parent.full_path()):
                            jnt = my_parent.full_path()
                        else:
                            # Build a new joint
                            jnt = mc.joint(name=jnt_name, p=(0, 0, 0))

                        mc.setAttr(jnt + ".rotateOrder", rot_order)
                        mc.setAttr(
                            jnt + ".translate",
                            float(offset[1]),
                            float(offset[2]),
                            float(offset[3])
                        )

                    if "MOTION" in line:
                        # Animate!
                        motion = True

                else:
                    # We don't really need to use Frame count and time
                    # (since Python handles file reads nicely)
                    if "Frame" not in line:
                        data = space_re.split(line.strip())
                        # Set the values to channels
                        for index, value in enumerate(data):
                            mc.setKeyframe(self._channels[index],
                                           time=frame,
                                           value=float(value))

                        frame = frame + 1

    def _clear_animation(self):
        if self._root_node is None:
            mc.error("Could not find root node to clear animation.")
            return

        # Select hierarchy
        mc.select(str(self._root_node), hi=True)
        nodes = mc.ls(sl=True)

        trans_attrs = ["translateX", "translateY", "translateZ"]
        rot_attrs = ["rotateX", "rotateY", "rotateZ"]
        for node in nodes:
            for attr in trans_attrs + rot_attrs:
                # Delete input connections
                connections = mc.listConnections("%s.%s" % (node, attr),
                                                 s=True,
                                                 d=False)
                if connections is not None:
                    mc.delete(connections)

            for attr in rot_attrs:
                # Reset rotation
                mc.setAttr("%s.%s" % (node, attr), 0)

    def _on_select_root(self, *_args):
        # When targeting, set the root joint (Hips)
        selection = mc.ls(sl=True, type="joint", l=True)
        if len(selection) == 0:
            self._root_node = None
            mc.textField(self._textfield, e=True, text="")
        else:
            self._root_node = selection[0]
            mc.textField(self._textfield, e=True, text=self._root_node)


if __name__ == "__main__":
    dialog = BVHImporterDialog()

maya导出bvh脚本

https://github.com/zhaozigu/maya-export-bvh/blob/main/export_bvh.py

import os
import math

import maya.cmds as cmds
import maya.api.OpenMaya as om


def get_bone_rotation(bone):
    cur_mat = om.MMatrix(cmds.xform(bone, q=True, ws=True, m=True))
    parent = cmds.listRelatives(bone, p=True)[0]
    parent_mat = om.MMatrix(cmds.xform(parent, q=True, ws=True, m=True))

    local_mat = cur_mat * parent_mat.inverse()
    cur_xfo_mat = om.MTransformationMatrix(local_mat)
    rotation = [math.degrees(x) for x in cur_xfo_mat.rotation().asVector()]
    return rotation


def export_motion(joints, start_frame, end_frame, rot_order: tuple):
    motion_str = ""

    root_joint = joints[0]

    for frame in range(start_frame, end_frame + 1):
        cmds.currentTime(frame)
        for joint in joints:
            joint_name = cmds.ls(joint, long=True)[0]
            rot = get_bone_rotation(joint_name)

            if joint == root_joint:
                loc = cmds.xform(joint_name, q=True, translation=True)
                motion_str += "%.6f %.6f %.6f " % (loc[0], loc[1], loc[2])
            motion_str += "%.6f %.6f %.6f " % (
                rot[rot_order[0]], rot[rot_order[1]], rot[rot_order[2]])

        motion_str += "\n"

    return motion_str


def export_hierarchy(joints, rot_order: str):
    hierarchy_str = "HIERARCHY\n"

    def _process_joint(joint, indent):
        nonlocal hierarchy_str
        joint_name_raw = cmds.ls(joint, long=True)[0]
        joint_name = joint_name_raw.split("|")[-1].split(":")[-1]

        if indent == 0:
            hierarchy_str += "{}ROOT {}\n".format('\t' * indent, joint_name)
        else:
            hierarchy_str += "{}JOINT {}\n".format('\t' * indent, joint_name)

        loc = cmds.xform(joint_name_raw, q=True, translation=True)
        hierarchy_str += "{}{{\n".format('\t' * indent)
        hierarchy_str += "{}OFFSET {:.6f} {:.6f} {:.6f}\n".format(
            '\t' * (indent + 1), loc[0], loc[1], loc[2])

        if indent == 0:
            hierarchy_str += "{}CHANNELS 6 Xposition Yposition Zposition {}rotation {}rotation {}rotation\n".format(
                '\t' * (indent + 1), rot_order[0], rot_order[1], rot_order[2])
        else:
            hierarchy_str += "{}CHANNELS 3 {}rotation {}rotation {}rotation\n".format(
                '\t' * (indent + 1), rot_order[0], rot_order[1], rot_order[2])

        children = cmds.listRelatives(joint, children=True, type="joint")
        if children:
            for child in children:
                _process_joint(child, indent + 1)
        else:
            hierarchy_str += "{}End Site\n".format('\t' * (indent + 1))
            hierarchy_str += "{}{{\n".format('\t' * (indent + 1))
            hierarchy_str += "{}OFFSET 0.0 0.0 0.0\n".format(
                '\t' * (indent + 2))
            hierarchy_str += "{}}}\n".format('\t' * (indent + 1))

        hierarchy_str += "{}}}\n".format('\t' * indent)

    root_joint = joints[0]
    _process_joint(root_joint, 0)
    return hierarchy_str


def export_bvh(joints, output_file_path, start_frame, end_frame, rot_order="ZXY"):
    _order = {
        "XYZ": (0, 1, 2),
        "XZY": (0, 2, 1),
        "YXZ": (1, 0, 2),
        "YZX": (1, 2, 0),
        "ZXY": (2, 0, 1),
        "ZYX": (2, 1, 0),
    }
    assert rot_order in _order, "The parameters of the rotation order are incorrect"

    hierarchy = export_hierarchy(joints, rot_order)
    motion = export_motion(joints, start_frame, end_frame, _order[rot_order])
    num_frames = end_frame - start_frame + 1
    frame_rate = cmds.playbackOptions(query=True, framesPerSecond=True)
    if frame_rate == 0:
        frame_rate = 24.0
    frame_time = 1.0 / frame_rate

    with open(output_file_path, "w") as output_file:
        output_file.write(hierarchy)
        output_file.write(
            f"MOTION\nFrames: {num_frames}\nFrame Time: {frame_time:.6f}\n")
        output_file.write(motion)


def get_ordered_joints(joint):
    ordered_joints = [joint]

    children = cmds.listRelatives(joint, children=True, type="joint")
    if children:
        for child in children:
            ordered_joints.extend(get_ordered_joints(child))

    return ordered_joints


if __name__ == "__main__":
    root_joint_name = "root"
    root_joint = None
    children = cmds.listRelatives(
        root_joint_name, children=True, type="joint")
    if children:
        root_joint = children[0]
    else:
        raise ValueError(f"No joint found under {root_joint_name}")

    joints = get_ordered_joints(root_joint)
    print(joints)

    start_frame = int(cmds.playbackOptions(query=True, minTime=True))
    end_frame = int(cmds.playbackOptions(query=True, maxTime=True))

    # Set the output file path
    output_file_path = os.path.join(
        os.path.expanduser("~"), "maya_body_test.bvh")

    export_bvh(joints, output_file_path, start_frame, end_frame, "ZYX")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1544007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis消息队列与thinkphp/queue操作

业务场景 场景一 用户完成注册后需要发送欢迎注册的问候邮件、同时后台要发送实时消息给用户对应的业务员有新的客户注册、最后将用户的注册数据通过接口推送到一个营销用的第三方平台。 遇到两个问题: 由于代码是串行方式,流程大致为:开…

关于网格数据导出指定格式的测试(以Gmsh导出nas格式为例)

本文主要讲述Gmsh如何导出nas格式的网格数据,众所周知,Gmsh可以导出多种网格数据格式,比如大家熟悉的msh、stl、inp、cgns(似乎不完善)等等,但是gmsh不支持nas格式的导出,只支持nas格式的导入&a…

基于java+springboot+vue实现的图书借阅系统(文末源码+Lw+ppt)23-328

摘 要 伴随着我国社会的发展,人民生活质量日益提高。于是对系统进行规范而严格是十分有必要的,所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套“期待相遇”图书借阅系统,帮助商…

Harmony(鸿蒙)Stage模型综述

设计思想 ​Stage模型的设计,是为了提供给开发者一个更好的开发方式,更好的适用于多设备、分布式场景。 ​Stage模型的设计思想如下图所示。 ​Stage模型的设计基于如下三个出发点: 应用进程的有序管理 随着设备的内存越来越大&#xff0…

【docker】查看并拷贝容器内文件

一、查询容器 查询所有容器 docker ps查询名为os11的容器 docker ps | grep os11查询名为os11的容器(包含不运行的) docker ps -a| grep os11 docker ps [option] 显示结果介绍如下: 参考:[https://blog.51cto.com/u_15009374/31…

详解华为软件研发管理IPD

IPD,即集成产品开发(Integrated Product Development),是一种综合多种管理模型和理论、企业最佳实践的管理体系。旨在帮助企业快速适应市场变化,缩短产品上市时间,减少资源浪费,并提高生产力,以实现商业成功。 IPD的核心是跨部门团队的合作,涉及市场、研发、制造、服…

java项目将静态资源中的文件转为浏览器可访问的http地址

新增一个类叫啥无所谓,主要是实现 WebMvcConfigurer 加上注解 Configuration项目启动时加入bean中 只操作addResourceHandlers这一个方法 其他都没用 文章下方附带一个简易的上传图片代码 package cn.exam.config;import org.springframework.context.annotati…

Java代码基础算法练习-字符串反转-2024.03.25

任务描述: 输入一个字符串,然后将此字符串反转(字符串最长不超过25个字符) 任务要求: 代码示例: package M0317_0331;import java.util.Scanner;public class m240325_1 {public static void main(String…

Mysql锁及适用场景

一、mysql中的锁有哪些? 1.1 锁的类型 (1)共享锁(Shared Lock): 共享锁允许事务读取数据,但不允许其他事务修改数据。多个事务可以同时持有共享锁。 -- 事务A获取共享锁 START TRANSACTION; …

Matlab|基于模型预测控制(MPC)的微电网调度优化的研究

目录 1 主要内容 2 程序难点及问题说明 3 部分程序 4 下载链接 1 主要内容 该程序分为两部分,日前优化部分——该程序首先根据《电力系统云储能研究框架与基础模型》上面方法,根据每个居民的实际需要得到响应储能充放电功率,优化得到整…

网络通信VLAN学习篇

拓扑图 如上图,pc3,pc5同一网络,pc4,pc6同一网络,vlan的划分就是虚拟局域网,局域网的理解就是同一vlan下的设备可以相互通信,不同vlan不可以通信(通过三层交换机可以实现通信的&…

一分钟学习Markdown语法

title: 一分钟学习Markdown语法 date: 2024/3/24 19:33:29 updated: 2024/3/24 19:33:29 tags: MD语法文本样式列表结构链接插入图片展示练习实践链接问题 欢迎来到Markdown语法的世界!Markdown是一种简单而直观的标记语言,让文本排版变得轻松有趣。接下…

RK3568驱动指南|第十三篇 输入子系统-第154章 固定usb设备的设备节点实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

Linux调试器-gdb

一、背景 程序的发布方式有两种,debug模式和release模式 debug模式:编译器形成可执行程序的时候会给可执行程序添加调试信息 程序员调试时使用debug模式,而release模式用于测试 而gcc/g默认编译,采用release模式 用gcc/g使用…

windows11 openssh服务开启;第三方ping不通局域网windows电脑;ssh连接内部ubuntu系统

参考:https://blog.csdn.net/2301_77554343/article/details/134328867 1、windows11 openssh开启 1)我这边可选功能在设置-系统里面;其他网上看在应用下;添加可选openssh服务器安装 2)安装后打开,管理员…

Python对文件的常见操作用法

在 Python 中,操作文件通常涉及打开文件、读取内容、写入内容以及关闭文件等步骤。下面是一些常见的文件操作及其示例: 1. 打开文件 使用内置的 open() 函数来打开文件。这个函数接受两个主要参数:文件名和模式。模式指定了文件应如何打开&a…

前端-html-01

1.HTML的标签分类 1.1常用排版标签 标签名语义和功能属性单标签还是双标签h1 ~ h6一级标题~六级标题无双标签p段落无双标签hr分隔线无单标签br换行无单标签pre原格式显示无双标签div无语义&#xff0c;用于页面布局无双标签 1.1.1h标题标签 <!DOCTYPE html> <htm…

nav仿真(2)

开启仿真和建图 打开第一个窗口启动仿真&#xff1a; source devel/setup.bash export TURTLEBOT3_MODELburger roslaunch turtlebot3_gazebo turtlebot3_world.launch # 启动仿真打开第二个窗口&#xff0c;开始建图&#xff1a; source devel/setup.bash export TURTLEBOT3_…

Nginx 内存池

目录 零、基本框架 一、基础结构 二、对外接口 三、函数实现 1、ngx_create_pool 2、ngx_destroy_pool 3、ngx_reset_pool 4、ngx_palloc 5、ngx_pnalloc 6、ngx_pmemalign 7、ngx_pfree 8、ngx_pcalloc 9、ngx_pool_cleanup_add 10、ngx_pool_run_cleanup_file…

【spring】@Component注解学习

Component介绍 Component 是 Spring 框架中的一个注解&#xff0c;用于将一个类标记为 Spring 上下文中的一个组件。当一个类被标记为 Component 时&#xff0c;Spring 容器会在启动时自动扫描并实例化这个类&#xff0c;并将其注册到 Spring 上下文中。 Component 注解可以用…