Skip to content

Commit ef8aafc

Browse files
committed
Merge pull request #94165 from aaronfranke/gltf-khr-anim-ptr
GLTF: Implement `KHR_animation_pointer` for animating custom properties
2 parents 8536506 + 0513943 commit ef8aafc

29 files changed

+2643
-653
lines changed

modules/fbx/fbx_document.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,7 +1389,7 @@ Error FBXDocument::_parse_animations(Ref<FBXState> p_state) {
13891389

13901390
for (const ufbx_baked_node &fbx_baked_node : fbx_baked_anim->nodes) {
13911391
const GLTFNodeIndex node = fbx_baked_node.typed_id;
1392-
GLTFAnimation::Track &track = animation->get_tracks()[node];
1392+
GLTFAnimation::NodeTrack &track = animation->get_node_tracks()[node];
13931393

13941394
for (const ufbx_baked_vec3 &key : fbx_baked_node.translation_keys) {
13951395
track.position_track.times.push_back(float(key.time));
@@ -1779,8 +1779,8 @@ void FBXDocument::_import_animation(Ref<FBXState> p_state, AnimationPlayer *p_an
17791779

17801780
double anim_start_offset = p_trimming ? double(additional_animation_data["time_begin"]) : 0.0;
17811781

1782-
for (const KeyValue<int, GLTFAnimation::Track> &track_i : anim->get_tracks()) {
1783-
const GLTFAnimation::Track &track = track_i.value;
1782+
for (const KeyValue<int, GLTFAnimation::NodeTrack> &track_i : anim->get_node_tracks()) {
1783+
const GLTFAnimation::NodeTrack &track = track_i.value;
17841784
//need to find the path: for skeletons, weight tracks will affect the mesh
17851785
NodePath node_path;
17861786
//for skeletons, transform tracks always affect bones

modules/gltf/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def get_doc_classes():
2020
"GLTFLight",
2121
"GLTFMesh",
2222
"GLTFNode",
23+
"GLTFObjectModelProperty",
2324
"GLTFPhysicsBody",
2425
"GLTFPhysicsShape",
2526
"GLTFSkeleton",

modules/gltf/doc_classes/GLTFAccessor.xml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
The offset relative to the start of the buffer view in bytes.
2323
</member>
2424
<member name="component_type" type="int" setter="set_component_type" getter="get_component_type" default="0">
25-
The glTF component type as an enum. Possible values are 5120 for "BYTE", 5121 for "UNSIGNED_BYTE", 5122 for "SHORT", 5123 for "UNSIGNED_SHORT", 5125 for "UNSIGNED_INT", and 5126 for "FLOAT". A value of 5125 or "UNSIGNED_INT" must not be used for any accessor that is not referenced by mesh.primitive.indices.
25+
The glTF component type as an enum. See [enum GLTFComponentType] for possible values. Within the core glTF specification, a value of 5125 or "UNSIGNED_INT" must not be used for any accessor that is not referenced by mesh.primitive.indices.
2626
</member>
2727
<member name="count" type="int" setter="set_count" getter="get_count" default="0">
2828
The number of elements referenced by this accessor.
@@ -80,5 +80,41 @@
8080
<constant name="TYPE_MAT4" value="6" enum="GLTFAccessorType">
8181
Accessor type "MAT4". For the glTF object model, this maps to "float4x4", represented in the glTF JSON as an array of sixteen floats.
8282
</constant>
83+
<constant name="COMPONENT_TYPE_NONE" value="0" enum="GLTFComponentType">
84+
Component type "NONE". This is not a valid component type, and is used to indicate that the component type is not set.
85+
</constant>
86+
<constant name="COMPONENT_TYPE_SIGNED_BYTE" value="5120" enum="GLTFComponentType">
87+
Component type "BYTE". The value is [code]0x1400[/code] which comes from OpenGL. This indicates data is stored in 1-byte or 8-bit signed integers. This is a core part of the glTF specification.
88+
</constant>
89+
<constant name="COMPONENT_TYPE_UNSIGNED_BYTE" value="5121" enum="GLTFComponentType">
90+
Component type "UNSIGNED_BYTE". The value is [code]0x1401[/code] which comes from OpenGL. This indicates data is stored in 1-byte or 8-bit unsigned integers. This is a core part of the glTF specification.
91+
</constant>
92+
<constant name="COMPONENT_TYPE_SIGNED_SHORT" value="5122" enum="GLTFComponentType">
93+
Component type "SHORT". The value is [code]0x1402[/code] which comes from OpenGL. This indicates data is stored in 2-byte or 16-bit signed integers. This is a core part of the glTF specification.
94+
</constant>
95+
<constant name="COMPONENT_TYPE_UNSIGNED_SHORT" value="5123" enum="GLTFComponentType">
96+
Component type "UNSIGNED_SHORT". The value is [code]0x1403[/code] which comes from OpenGL. This indicates data is stored in 2-byte or 16-bit unsigned integers. This is a core part of the glTF specification.
97+
</constant>
98+
<constant name="COMPONENT_TYPE_SIGNED_INT" value="5124" enum="GLTFComponentType">
99+
Component type "INT". The value is [code]0x1404[/code] which comes from OpenGL. This indicates data is stored in 4-byte or 32-bit signed integers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code].
100+
</constant>
101+
<constant name="COMPONENT_TYPE_UNSIGNED_INT" value="5125" enum="GLTFComponentType">
102+
Component type "UNSIGNED_INT". The value is [code]0x1405[/code] which comes from OpenGL. This indicates data is stored in 4-byte or 32-bit unsigned integers. This is a core part of the glTF specification.
103+
</constant>
104+
<constant name="COMPONENT_TYPE_SINGLE_FLOAT" value="5126" enum="GLTFComponentType">
105+
Component type "FLOAT". The value is [code]0x1406[/code] which comes from OpenGL. This indicates data is stored in 4-byte or 32-bit floating point numbers. This is a core part of the glTF specification.
106+
</constant>
107+
<constant name="COMPONENT_TYPE_DOUBLE_FLOAT" value="5130" enum="GLTFComponentType">
108+
Component type "DOUBLE". The value is [code]0x140A[/code] which comes from OpenGL. This indicates data is stored in 8-byte or 64-bit floating point numbers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code].
109+
</constant>
110+
<constant name="COMPONENT_TYPE_HALF_FLOAT" value="5131" enum="GLTFComponentType">
111+
Component type "HALF_FLOAT". The value is [code]0x140B[/code] which comes from OpenGL. This indicates data is stored in 2-byte or 16-bit floating point numbers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code].
112+
</constant>
113+
<constant name="COMPONENT_TYPE_SIGNED_LONG" value="5134" enum="GLTFComponentType">
114+
Component type "LONG". The value is [code]0x140E[/code] which comes from OpenGL. This indicates data is stored in 8-byte or 64-bit signed integers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code].
115+
</constant>
116+
<constant name="COMPONENT_TYPE_UNSIGNED_LONG" value="5135" enum="GLTFComponentType">
117+
Component type "UNSIGNED_LONG". The value is [code]0x140F[/code] which comes from OpenGL. This indicates data is stored in 8-byte or 64-bit unsigned integers. This is NOT a core part of the glTF specification, and may not be supported by all glTF importers. May be used by some extensions including [code]KHR_interactivity[/code].
118+
</constant>
83119
</constants>
84120
</class>

modules/gltf/doc_classes/GLTFDocument.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@
4545
Takes a Godot Engine scene node and exports it and its descendants to the given [GLTFState] object through the [param state] parameter.
4646
</description>
4747
</method>
48+
<method name="export_object_model_property" qualifiers="static">
49+
<return type="GLTFObjectModelProperty" />
50+
<param index="0" name="state" type="GLTFState" />
51+
<param index="1" name="node_path" type="NodePath" />
52+
<param index="2" name="godot_node" type="Node" />
53+
<param index="3" name="gltf_node_index" type="int" />
54+
<description>
55+
Determines a mapping between the given Godot [param node_path] and the corresponding glTF Object Model JSON pointer(s) in the generated glTF file. The details of this mapping are returned in a [GLTFObjectModelProperty] object. Additional mappings can be supplied via the [method GLTFDocumentExtension._import_object_model_property] callback method.
56+
</description>
57+
</method>
4858
<method name="generate_buffer">
4959
<return type="PackedByteArray" />
5060
<param index="0" name="state" type="GLTFState" />
@@ -70,6 +80,14 @@
7080
[b]Note:[/b] If this method is run before a GLTFDocumentExtension is registered, its extensions won't be included in the list. Be sure to only run this method after all extensions are registered. If you run this when the engine starts, consider waiting a frame before calling this method to ensure all extensions are registered.
7181
</description>
7282
</method>
83+
<method name="import_object_model_property" qualifiers="static">
84+
<return type="GLTFObjectModelProperty" />
85+
<param index="0" name="state" type="GLTFState" />
86+
<param index="1" name="json_pointer" type="String" />
87+
<description>
88+
Determines a mapping between the given glTF Object Model [param json_pointer] and the corresponding Godot node path(s) in the generated Godot scene. The details of this mapping are returned in a [GLTFObjectModelProperty] object. Additional mappings can be supplied via the [method GLTFDocumentExtension._export_object_model_property] callback method.
89+
</description>
90+
</method>
7391
<method name="register_gltf_document_extension" qualifiers="static">
7492
<return type="void" />
7593
<param index="0" name="extension" type="GLTFDocumentExtension" />

modules/gltf/doc_classes/GLTFDocumentExtension.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
This method can be used to modify the final JSON of each node. Data should be primarily stored in [param gltf_node] prior to serializing the JSON, but the original Godot [param node] is also provided if available. The node may be null if not available, such as when exporting glTF data not generated from a Godot scene.
3434
</description>
3535
</method>
36+
<method name="_export_object_model_property" qualifiers="virtual">
37+
<return type="GLTFObjectModelProperty" />
38+
<param index="0" name="state" type="GLTFState" />
39+
<param index="1" name="node_path" type="NodePath" />
40+
<param index="2" name="godot_node" type="Node" />
41+
<param index="3" name="gltf_node_index" type="int" />
42+
<param index="4" name="target_object" type="Object" />
43+
<param index="5" name="target_depth" type="int" />
44+
<description>
45+
Part of the export process. Allows GLTFDocumentExtension classes to provide mappings for properties of nodes in the Godot scene tree, to JSON pointers to glTF properties, as defined by the glTF object model.
46+
Returns a [GLTFObjectModelProperty] instance that defines how the property should be mapped. If your extension can't handle the property, return null, or an instance without any JSON pointers (see [method GLTFObjectModelProperty.has_json_pointers]). You should use [method GLTFObjectModelProperty.set_types] to set the types, and set the JSON pointer(s) using the [member GLTFObjectModelProperty.json_pointers] property.
47+
The parameters provide context for the property, including the NodePath, the Godot node, the GLTF node index, and the target object. The [param target_object] will be equal to [param godot_node] if no sub-object can be found, otherwise it will point to a sub-object. For example, if the path is [code]^"A/B/C/MeshInstance3D:mesh:surface_0/material:emission_intensity"[/code], it will get the node, then the mesh, and then the material, so [param target_object] will be the [Material] resource, and [param target_depth] will be 2 because 2 levels were traversed to get to the target.
48+
</description>
49+
</method>
3650
<method name="_export_post" qualifiers="virtual">
3751
<return type="int" enum="Error" />
3852
<param index="0" name="state" type="GLTFState" />
@@ -109,6 +123,17 @@
109123
This method can be used to make modifications to each of the generated Godot scene nodes.
110124
</description>
111125
</method>
126+
<method name="_import_object_model_property" qualifiers="virtual">
127+
<return type="GLTFObjectModelProperty" />
128+
<param index="0" name="state" type="GLTFState" />
129+
<param index="1" name="split_json_pointer" type="PackedStringArray" />
130+
<param index="2" name="partial_paths" type="NodePath[]" />
131+
<description>
132+
Part of the import process. Allows GLTFDocumentExtension classes to provide mappings for JSON pointers to glTF properties, as defined by the glTF object model, to properties of nodes in the Godot scene tree.
133+
Returns a [GLTFObjectModelProperty] instance that defines how the property should be mapped. If your extension can't handle the property, return null, or an instance without any NodePaths (see [method GLTFObjectModelProperty.has_node_paths]). You should use [method GLTFObjectModelProperty.set_types] to set the types, and [method GLTFObjectModelProperty.append_path_to_property] function is useful for most simple cases.
134+
In many cases, [param partial_paths] will contain the start of a path, allowing the extension to complete the path. For example, for [code]/nodes/3/extensions/MY_ext/prop[/code], Godot will pass you a NodePath that leads to node 3, so the GLTFDocumentExtension class only needs to resolve the last [code]MY_ext/prop[/code] part of the path. In this example, the extension should check [code]split.size() &gt; 4 and split[0] == "nodes" and split[2] == "extensions" and split[3] == "MY_ext"[/code] at the start of the function to check if this JSON pointer applies to it, then it can use [param partial_paths] and handle [code]split[4][/code].
135+
</description>
136+
</method>
112137
<method name="_import_post" qualifiers="virtual">
113138
<return type="int" enum="Error" />
114139
<param index="0" name="state" type="GLTFState" />

modules/gltf/doc_classes/GLTFNode.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@
2727
The argument should be the [GLTFDocumentExtension] name (does not have to match the extension name in the glTF file), and the return value can be anything you set. If nothing was set, the return value is null.
2828
</description>
2929
</method>
30+
<method name="get_scene_node_path">
31+
<return type="NodePath" />
32+
<param index="0" name="gltf_state" type="GLTFState" />
33+
<param index="1" name="handle_skeletons" type="bool" default="true" />
34+
<description>
35+
Returns the [NodePath] that this GLTF node will have in the Godot scene tree after being imported. This is useful when importing glTF object model pointers with [GLTFObjectModelProperty], for handling extensions such as [code]KHR_animation_pointer[/code] or [code]KHR_interactivity[/code].
36+
If [param handle_skeletons] is true, paths to skeleton bone glTF nodes will be resolved properly. For example, a path that would be [code]^"A/B/C/Bone1/Bone2/Bone3"[/code] if false will become [code]^"A/B/C/Skeleton3D:Bone3"[/code].
37+
</description>
38+
</method>
3039
<method name="set_additional_data">
3140
<return type="void" />
3241
<param index="0" name="extension_name" type="StringName" />

0 commit comments

Comments
 (0)