自定义默认动画图表#

警告

创建自定义动画图表尚未正式支持,但我们目前提供有关内部结构的一些初步信息,以帮助您在出现问题时调试微服务内部结构。

警告

请注意,配置微服务所需的姿势提供程序节点动画图表功能目前在公共 USD Composer 版本中不可用。这些功能将在未来版本中提供。

默认动画图表由以下部分组成

  • 姿势

  • 手势

  • 位置

  • 面部表情

  • Audio2Face 输入

动画图表生成#

此动画图表的一部分可以手动调整到一定程度,但姿势、手势和面部表情的状态机非常庞大,以至于需要使用 Python 脚本生成。名为 animation_graph_builder_behavior_script.py 的脚本链接在 Animation Graph 原语内部。在初始化时,它会检查提到的状态机是否存在。如果不存在,它将使用原语 Animations 下的动画剪辑生成它们。

从默认图表中添加或删除动画#

要更改图表使用的动画集,无需构建新图表。按照这些步骤 添加自定义动画 添加或删除动画。

自定义动画图表#

除非您想更改上述机制,否则不建议进一步更改默认动画图表。在这种情况下,请考虑以下限制。

场景的结构#

场景以两种方式使用:1) 使用动画图表微服务控制头像动画,以及 2) 在 Omniverse 渲染器微服务中渲染角色。当前,相同的场景用于这两种服务。对于头像动画,有一个通用的 NVIDIA 拟人角色,它在场景中不可见,以通用方式处理动画。该动画的重定向和渲染发生在渲染器微服务中,使用应在最终结果中的任何角色。这样,动画图表微服务无需考虑最终角色,而仅使用一个通用绑定。为了使其工作,此通用绑定及其关联的原语需要以固定的方式进行结构化。

硬编码的原语路径#

场景中某些原语的路径在微服务中是硬编码的。这些原语需要根据下表定位和命名。

场景中某些原语的路径在微服务中是硬编码的。因此,这些原语需要根据下表定位和命名。#

变量名

原语路径

描述

scene_skel_roots_scope_prim_path

/World/SkelRoots

角色的父原语。微服务将复制多个副本,直到达到最大支持的流容量。

scene_skel_root_prim_path

/World/SkelRoots/Rig_Retarget/SkelRoot

SkelRoot 是分配动画图表的原语。

scene_skeleton_prim_path

/World/SkelRoots/Rig_Retarget/SkelRoot /Skeleton

Skeleton 定义了关节命名、层级结构和变换以及重定向标签。

scene_character_anim_pose_prim_path

/World/SkelRoots/Rig_Retarget/SkelRoot /Skeleton/AnimGraphOutputPose

来自动画图表的最终姿势。这是在运行时自动创建的。

scene_skel_animation_prim_path

/World/Animations/Rig_Retarget/SkelRoot /Skeleton/ACE_Animation_Target

微服务在渲染器端向其写入姿势的动画剪辑。

scene_camera_prim_path

/World/SkelRoots/Rig_Camera/SkelRoot /Skeleton/root/camera_location /camera_body/camera_main

场景中主摄像头的位置。目前尚未使用,但将来可能会使用。

自定义图层数据#

无论哪些动画图表变量应由微服务公开,都需要在主 USD 场景文件的 customLayerData 部分中显式指定。然后,动画图表微服务将在启动时动态生成必要的端点。

来自默认 Avatar_Scene.usda 的自定义图层数据示例#
   #usda 1.0
   (
      customLayerData = {
         dictionary animation_graph_microservice_api_mapping = {
            dictionary animation_graphs = {
               dictionary avatar = {
                  string animation_graph_prim_path = "/World/..."
                  dictionary variable_routes = {
                     dictionary gesture_state = {
                        string variable_name = "gesture_state"
                     }
                     dictionary posture_state = {
                        string variable_name = "posture_state"
                     }
                     dictionary facial_gesture_state = {
                        string variable_name = "facial_gesture_state"
                     }
                     dictionary position_state = {
                        string variable_name = "position_state"
                     }
                  }
               }
            }
         }
      }
   )

关于面部表情的注意事项#

面部表情的工作方式与(身体)手势类似,不同之处在于它们是累加的。这意味着面部表情不会中断正在进行的(身体)手势或姿势,而是与其他同时发生的动画结合。由于混合节点的累加模式仍处于早期开发阶段,因此它尚未从结果中减去角色的静止姿势。这意味着,如果您要添加两个中性姿势,它们会堆叠起来,角色在视觉上会爆炸。因此,用作面部表情的所有动画都需要已经从中减去静止姿势(使用相对变换)。因此,面部表情的动画仅在此特定上下文中有效。它们仅包括 blendshape 动画以及头部和颈部关节在相对空间中的运动。

An example of how combining two animations additively leads to unpredictable results if the rest pose is not subtracted from one of the animations.