Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLTF: Implement KHR_animation_pointer for animating custom properties #94165

Merged
merged 8 commits into from
Nov 5, 2024
6 changes: 3 additions & 3 deletions modules/fbx/fbx_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,7 @@ Error FBXDocument::_parse_animations(Ref<FBXState> p_state) {

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

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

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

for (const KeyValue<int, GLTFAnimation::Track> &track_i : anim->get_tracks()) {
const GLTFAnimation::Track &track = track_i.value;
for (const KeyValue<int, GLTFAnimation::NodeTrack> &track_i : anim->get_node_tracks()) {
const GLTFAnimation::NodeTrack &track = track_i.value;
//need to find the path: for skeletons, weight tracks will affect the mesh
NodePath node_path;
//for skeletons, transform tracks always affect bones
Expand Down
1 change: 1 addition & 0 deletions modules/gltf/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def get_doc_classes():
"GLTFLight",
"GLTFMesh",
"GLTFNode",
"GLTFObjectModelProperty",
"GLTFPhysicsBody",
"GLTFPhysicsShape",
"GLTFSkeleton",
Expand Down
38 changes: 37 additions & 1 deletion modules/gltf/doc_classes/GLTFAccessor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
The offset relative to the start of the buffer view in bytes.
</member>
<member name="component_type" type="int" setter="set_component_type" getter="get_component_type" default="0">
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.
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.
</member>
<member name="count" type="int" setter="set_count" getter="get_count" default="0">
The number of elements referenced by this accessor.
Expand Down Expand Up @@ -80,5 +80,41 @@
<constant name="TYPE_MAT4" value="6" enum="GLTFAccessorType">
Accessor type "MAT4". For the glTF object model, this maps to "float4x4", represented in the glTF JSON as an array of sixteen floats.
</constant>
<constant name="COMPONENT_TYPE_NONE" value="0" enum="GLTFComponentType">
Component type "NONE". This is not a valid component type, and is used to indicate that the component type is not set.
</constant>
<constant name="COMPONENT_TYPE_SIGNED_BYTE" value="5120" enum="GLTFComponentType">
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.
</constant>
<constant name="COMPONENT_TYPE_UNSIGNED_BYTE" value="5121" enum="GLTFComponentType">
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.
</constant>
<constant name="COMPONENT_TYPE_SIGNED_SHORT" value="5122" enum="GLTFComponentType">
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.
</constant>
<constant name="COMPONENT_TYPE_UNSIGNED_SHORT" value="5123" enum="GLTFComponentType">
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.
</constant>
<constant name="COMPONENT_TYPE_SIGNED_INT" value="5124" enum="GLTFComponentType">
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].
</constant>
<constant name="COMPONENT_TYPE_UNSIGNED_INT" value="5125" enum="GLTFComponentType">
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.
</constant>
<constant name="COMPONENT_TYPE_SINGLE_FLOAT" value="5126" enum="GLTFComponentType">
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.
</constant>
<constant name="COMPONENT_TYPE_DOUBLE_FLOAT" value="5130" enum="GLTFComponentType">
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].
</constant>
<constant name="COMPONENT_TYPE_HALF_FLOAT" value="5131" enum="GLTFComponentType">
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].
</constant>
<constant name="COMPONENT_TYPE_SIGNED_LONG" value="5134" enum="GLTFComponentType">
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].
</constant>
<constant name="COMPONENT_TYPE_UNSIGNED_LONG" value="5135" enum="GLTFComponentType">
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].
</constant>
</constants>
</class>
18 changes: 18 additions & 0 deletions modules/gltf/doc_classes/GLTFDocument.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@
Takes a Godot Engine scene node and exports it and its descendants to the given [GLTFState] object through the [param state] parameter.
</description>
</method>
<method name="export_object_model_property" qualifiers="static">
<return type="GLTFObjectModelProperty" />
<param index="0" name="state" type="GLTFState" />
<param index="1" name="node_path" type="NodePath" />
<param index="2" name="godot_node" type="Node" />
<param index="3" name="gltf_node_index" type="int" />
<description>
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.
</description>
</method>
<method name="generate_buffer">
<return type="PackedByteArray" />
<param index="0" name="state" type="GLTFState" />
Expand All @@ -70,6 +80,14 @@
[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.
</description>
</method>
<method name="import_object_model_property" qualifiers="static">
<return type="GLTFObjectModelProperty" />
<param index="0" name="state" type="GLTFState" />
<param index="1" name="json_pointer" type="String" />
<description>
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.
</description>
</method>
<method name="register_gltf_document_extension" qualifiers="static">
<return type="void" />
<param index="0" name="extension" type="GLTFDocumentExtension" />
Expand Down
25 changes: 25 additions & 0 deletions modules/gltf/doc_classes/GLTFDocumentExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@
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.
</description>
</method>
<method name="_export_object_model_property" qualifiers="virtual">
<return type="GLTFObjectModelProperty" />
<param index="0" name="state" type="GLTFState" />
<param index="1" name="node_path" type="NodePath" />
<param index="2" name="godot_node" type="Node" />
<param index="3" name="gltf_node_index" type="int" />
<param index="4" name="target_object" type="Object" />
<param index="5" name="target_depth" type="int" />
<description>
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.
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.
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.
</description>
</method>
<method name="_export_post" qualifiers="virtual">
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
Expand Down Expand Up @@ -109,6 +123,17 @@
This method can be used to make modifications to each of the generated Godot scene nodes.
</description>
</method>
<method name="_import_object_model_property" qualifiers="virtual">
<return type="GLTFObjectModelProperty" />
<param index="0" name="state" type="GLTFState" />
<param index="1" name="split_json_pointer" type="PackedStringArray" />
<param index="2" name="partial_paths" type="NodePath[]" />
<description>
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.
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.
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].
</description>
</method>
<method name="_import_post" qualifiers="virtual">
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
Expand Down
9 changes: 9 additions & 0 deletions modules/gltf/doc_classes/GLTFNode.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@
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.
</description>
</method>
<method name="get_scene_node_path">
<return type="NodePath" />
<param index="0" name="gltf_state" type="GLTFState" />
<param index="1" name="handle_skeletons" type="bool" default="true" />
<description>
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].
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].
</description>
</method>
<method name="set_additional_data">
<return type="void" />
<param index="0" name="extension_name" type="StringName" />
Expand Down
Loading
Loading