当前位置: 首页 > 工具软件 > PlayCanvas > 使用案例 >

Playcanvas动画格式解析

车思淼
2023-12-01

Playcanvas是一款开源的3d引擎,底层格式是自家定义的json格式,其文档说明如下:

https://developer.playcanvas.com/en/user-manual/graphics/file-format/

但是在官网翻不到其动画文件的解析代码,这里根据其引擎源码的解析,对其源码文件格式解析如下记录

{
    "animation":{
        // 动画时长
        "duration": 0.2,
        "nodes":[
            {
                // key.t 动画对应的时间节点
                // key.p 该时间节点对应的translations
                // key.r 该时间节点对应的rotations
                // key.s 该时间节点对应的scale
                "keys":[
                    {"p":[0,0,0],"s":[1,1,1],"r":[0,0,0],"t":0}
                ],
                //节点名称
                "name": "RootNode",
                // 一般为空,当keys为null时,取default作为keys的值
                "default": {}
            },
            {
                "keys":[
                    {"p":[0,0,0],"s":[1,1,1],"r":[0,0,0],"t":0},
                    {"p":[0.1,0,0],"s":[1,1,1],"r":[0,0,0],"t":0.1},
                    {"p":[0.1,0,0.1],"s":[1,1,1],"r":[0,0,0],"t":0.2}
                ],
                "name": "Node1",
                // 一般为空,当keys为null时,取default作为keys的值
                "default": {}
            }          
        ]
    }
}

实现playcanvas动画到gltf动画的转换(python代码示例)

animation_nodes = animation_data['nodes']
# 一般animation_nodes第一个节点为root,无需转换
animation_nodes.pop(0)
animations = []
channels = []
samplers = []
for animation_node in animation_nodes:
    # 查找node name 对应 gltf node 的 index
    node_index = self.search_node_index(animation_node['name'])
    if node_index == -1:
        continue
    current_times = []
    translations = []
    rotations = []
    scales = []
    for key in animation_node['keys']:
        current_times.append(key['t'])
 
        translations.extend(key['p'])
        rotations.extend(math_util.euler_to_quaternion(key['r']))
        scales.extend(key['s'])
     
    input_accessor = gltf_accessor_util.create_gltf_accessors(
                current_times, AccessorComponentType.FLOAT, 'SCALAR', 0
    )
 
    output_t_accessor = gltf_accessor_util.create_gltf_accessors(
                translations, AccessorComponentType.FLOAT, 'VEC3', 0
    )
    output_r_accessor = gltf_accessor_util.create_gltf_accessors(
                rotations, AccessorComponentType.FLOAT, 'VEC4', 0
    )
    output_s_accessor = gltf_accessor_util.create_gltf_accessors(
                scales, AccessorComponentType.FLOAT, 'VEC3', 0
    )
    # playcanvas每个node的p、r、s 对应 gltf三个sampler和channel
    path_accessor_relatives = dict(
        translation=output_t_accessor,
        rotation=output_r_accessor,
        scale=output_s_accessor,
    )
  
    for path, accessor in path_accessor_relatives.items():
        samplers.append(
            dict(
                input=input_accessor,
                interpolation='LINEAR',  # 默认
                output=accessor,
            )
        )
        channels.append(
            dict(
                target=dict(node=node_index, path=path),
                sampler=len(samplers) - 1,
            )
        )
if len(channels) > 0 and len(samplers) > 0:
    animation_dict['channels'] = channels
    animation_dict['samplers'] = samplers
    # 当有多段动画(多个json)时,可以在最外层添加for循环,并添加到animations
    animations.append(animation_dict)
     
if len(animations) > 0:
    self.gltf_json['animations'] = animations  

 

 类似资料: