Skip to content

Commit

Permalink
Merge pull request godotengine#92284 from fire/vsk-bake-fps-4.3
Browse files Browse the repository at this point in the history
Add `bake_fps` for FBXDocument, GLTFDocument and both import-export.
  • Loading branch information
akien-mga committed May 23, 2024
2 parents bceebdf + 24f5600 commit f25676c
Show file tree
Hide file tree
Showing 13 changed files with 76 additions and 35 deletions.
3 changes: 2 additions & 1 deletion modules/fbx/editor/editor_scene_importer_ufbx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,15 @@ Node *EditorSceneFormatImporterUFBX::import_scene(const String &p_path, uint32_t
state->set_import_as_skeleton_bones(true);
}
p_flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
state->set_bake_fps(p_options["animation/fps"]);
Error err = fbx->append_from_file(path, state, p_flags, p_path.get_base_dir());
if (err != OK) {
if (r_err) {
*r_err = FAILED;
}
return nullptr;
}
return fbx->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], false);
return fbx->generate_scene(state, state->get_bake_fps(), (bool)p_options["animation/trimming"], false);
}

Variant EditorSceneFormatImporterUFBX::get_option_visibility(const String &p_path, bool p_for_animation,
Expand Down
11 changes: 8 additions & 3 deletions modules/fbx/fbx_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,10 @@ Error FBXDocument::_parse_animations(Ref<FBXState> p_state) {
additional_data["time_end"] = fbx_anim_stack->time_end;
animation->set_additional_data("GODOT_animation_time_begin_time_end", additional_data);
ufbx_bake_opts opts = {};
opts.resample_rate = p_state->get_bake_fps();
opts.minimum_sample_rate = p_state->get_bake_fps();
opts.max_keyframe_segments = 1024;

ufbx_error error;
ufbx_unique_ptr<ufbx_baked_anim> fbx_baked_anim{ ufbx_bake_anim(fbx_scene, fbx_anim_stack->anim, &opts, &error) };
if (!fbx_baked_anim) {
Expand Down Expand Up @@ -1759,7 +1763,7 @@ void FBXDocument::_generate_skeleton_bone_node(Ref<FBXState> p_state, const GLTF
}
}

void FBXDocument::_import_animation(Ref<FBXState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming, const bool p_remove_immutable_tracks) {
void FBXDocument::_import_animation(Ref<FBXState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const bool p_trimming, const bool p_remove_immutable_tracks) {
Ref<GLTFAnimation> anim = p_state->animations[p_index];

String anim_name = anim->get_name();
Expand All @@ -1771,7 +1775,7 @@ void FBXDocument::_import_animation(Ref<FBXState> p_state, AnimationPlayer *p_an
Ref<Animation> animation;
animation.instantiate();
animation->set_name(anim_name);
animation->set_step(1.0 / p_bake_fps);
animation->set_step(1.0 / p_state->get_bake_fps());

if (anim->get_loop()) {
animation->set_loop_mode(Animation::LOOP_LINEAR);
Expand Down Expand Up @@ -2118,6 +2122,7 @@ Node *FBXDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool
ERR_FAIL_COND_V(state.is_null(), nullptr);
ERR_FAIL_NULL_V(state, nullptr);
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
p_state->set_bake_fps(p_bake_fps);
GLTFNodeIndex fbx_root = state->root_nodes.write[0];
Node *fbx_root_node = state->get_scene_node(fbx_root);
Node *root = fbx_root_node;
Expand All @@ -2131,7 +2136,7 @@ Node *FBXDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool
root->add_child(ap, true);
ap->set_owner(root);
for (int i = 0; i < state->animations.size(); i++) {
_import_animation(state, ap, i, p_bake_fps, p_trimming, p_remove_immutable_tracks);
_import_animation(state, ap, i, p_trimming, p_remove_immutable_tracks);
}
}
ERR_FAIL_NULL_V(root, nullptr);
Expand Down
2 changes: 1 addition & 1 deletion modules/fbx/fbx_document.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class FBXDocument : public GLTFDocument {
void _generate_scene_node(Ref<FBXState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root);
void _generate_skeleton_bone_node(Ref<FBXState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root);
void _import_animation(Ref<FBXState> p_state, AnimationPlayer *p_animation_player,
const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming, const bool p_remove_immutable_tracks);
const GLTFAnimationIndex p_index, const bool p_trimming, const bool p_remove_immutable_tracks);
Error _parse(Ref<FBXState> p_state, String p_path, Ref<FileAccess> p_file);
};

Expand Down
1 change: 1 addition & 0 deletions modules/gltf/doc_classes/GLTFDocument.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<param index="3" name="remove_immutable_tracks" type="bool" default="true" />
<description>
Takes a [GLTFState] object through the [param state] parameter and returns a Godot Engine scene node.
The [param bake_fps] parameter overrides the bake_fps in [param state].
</description>
</method>
<method name="register_gltf_document_extension" qualifiers="static">
Expand Down
3 changes: 3 additions & 0 deletions modules/gltf/doc_classes/GLTFState.xml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@
</method>
</methods>
<members>
<member name="bake_fps" type="float" setter="set_bake_fps" getter="get_bake_fps" default="30.0">
The baking fps of the animation for either import or export.
</member>
<member name="base_path" type="String" setter="set_base_path" getter="get_base_path" default="&quot;&quot;">
The folder path associated with this GLTF data. This is used to find other files the GLTF file references, like images or binary buffers. This will be set during import when appending from a file, and will be set during export when writing to a file.
</member>
Expand Down
1 change: 1 addition & 0 deletions modules/gltf/editor/editor_scene_exporter_gltf_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ void SceneExporterGLTFPlugin::_export_scene_as_gltf(const String &p_file_path) {
state->set_copyright(_export_settings->get_copyright());
int32_t flags = 0;
flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
state->set_bake_fps(_export_settings->get_bake_fps());
Error err = _gltf_document->append_from_scene(root, state, flags);
if (err != OK) {
ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err)));
Expand Down
12 changes: 12 additions & 0 deletions modules/gltf/editor/editor_scene_exporter_gltf_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,16 @@ void EditorSceneExporterGLTFSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_copyright"), &EditorSceneExporterGLTFSettings::get_copyright);
ClassDB::bind_method(D_METHOD("set_copyright", "copyright"), &EditorSceneExporterGLTFSettings::set_copyright);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "copyright", PROPERTY_HINT_PLACEHOLDER_TEXT, "Example: 2014 Godette"), "set_copyright", "get_copyright");

ClassDB::bind_method(D_METHOD("get_bake_fps"), &EditorSceneExporterGLTFSettings::get_bake_fps);
ClassDB::bind_method(D_METHOD("set_bake_fps", "bake_fps"), &EditorSceneExporterGLTFSettings::set_bake_fps);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_fps"), "set_bake_fps", "get_bake_fps");
}

double EditorSceneExporterGLTFSettings::get_bake_fps() const {
return _bake_fps;
}

void EditorSceneExporterGLTFSettings::set_bake_fps(const double p_bake_fps) {
_bake_fps = p_bake_fps;
}
4 changes: 4 additions & 0 deletions modules/gltf/editor/editor_scene_exporter_gltf_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class EditorSceneExporterGLTFSettings : public RefCounted {
HashMap<String, Ref<GLTFDocumentExtension>> _config_name_to_extension_map;

String _copyright;
double _bake_fps = 30.0;

protected:
static void _bind_methods();
Expand All @@ -58,6 +59,9 @@ class EditorSceneExporterGLTFSettings : public RefCounted {

String get_copyright() const;
void set_copyright(const String &p_copyright);

double get_bake_fps() const;
void set_bake_fps(const double p_bake_fps);
};

#endif // TOOLS_ENABLED
Expand Down
5 changes: 3 additions & 2 deletions modules/gltf/editor/editor_scene_importer_gltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t
if (p_options.has(SNAME("nodes/import_as_skeleton_bones")) ? (bool)p_options[SNAME("nodes/import_as_skeleton_bones")] : false) {
state->set_import_as_skeleton_bones(true);
}
state->set_bake_fps(p_options["animation/fps"]);
Error err = gltf->append_from_file(p_path, state, p_flags);
if (err != OK) {
if (r_err) {
Expand All @@ -75,9 +76,9 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t

#ifndef DISABLE_DEPRECATED
bool trimming = p_options.has("animation/trimming") ? (bool)p_options["animation/trimming"] : false;
return gltf->generate_scene(state, (float)p_options["animation/fps"], trimming, false);
return gltf->generate_scene(state, state->get_bake_fps(), trimming, false);
#else
return gltf->generate_scene(state, (float)p_options["animation/fps"], (bool)p_options["animation/trimming"], false);
return gltf->generate_scene(state, state->get_bake_fps(), (bool)p_options["animation/trimming"], false);
#endif
}

Expand Down
54 changes: 28 additions & 26 deletions modules/gltf/gltf_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4860,7 +4860,7 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) {
t["sampler"] = samplers.size();
Dictionary s;
Vector<real_t> times;
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
{
double time = 0.0;
bool last = false;
Expand Down Expand Up @@ -5902,7 +5902,8 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T
ERR_FAIL_V(p_values[0]);
}

void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming, const bool p_remove_immutable_tracks) {
void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, const GLTFAnimationIndex p_index, const bool p_trimming, const bool p_remove_immutable_tracks) {
ERR_FAIL_COND(p_state.is_null());
Ref<GLTFAnimation> anim = p_state->animations[p_index];

String anim_name = anim->get_name();
Expand All @@ -5914,7 +5915,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_
Ref<Animation> animation;
animation.instantiate();
animation->set_name(anim_name);
animation->set_step(1.0 / p_bake_fps);
animation->set_step(1.0 / p_state->get_bake_fps());

if (anim->get_loop()) {
animation->set_loop_mode(Animation::LOOP_LINEAR);
Expand Down Expand Up @@ -6081,7 +6082,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_
}
}

const double increment = 1.0 / p_bake_fps;
const double increment = 1.0 / p_state->get_bake_fps();
double time = anim_start;

Vector3 base_pos;
Expand Down Expand Up @@ -6158,7 +6159,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_
}
} else {
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / p_bake_fps;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand Down Expand Up @@ -6372,7 +6373,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.scale_track.times.clear();
p_track.scale_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand Down Expand Up @@ -6407,7 +6408,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.position_track.times.clear();
p_track.position_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand Down Expand Up @@ -6442,7 +6443,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.rotation_track.times.clear();
p_track.rotation_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand Down Expand Up @@ -6482,7 +6483,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.position_track.times.clear();
p_track.position_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand Down Expand Up @@ -6515,7 +6516,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.rotation_track.times.clear();
p_track.rotation_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand Down Expand Up @@ -6551,7 +6552,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.scale_track.times.clear();
p_track.scale_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
const double increment = 1.0 / p_state->get_bake_fps();
double time = 0.0;
bool last = false;
while (true) {
Expand All @@ -6577,14 +6578,14 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
}
}
} else if (track_type == Animation::TYPE_BEZIER) {
const int32_t keys = anim_end * BAKE_FPS;
const int32_t keys = anim_end * p_state->get_bake_fps();
if (path.contains(":scale")) {
if (!p_track.scale_track.times.size()) {
p_track.scale_track.interpolation = gltf_interpolation;
Vector<real_t> new_times;
new_times.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) {
new_times.write[key_i] = key_i / BAKE_FPS;
new_times.write[key_i] = key_i / p_state->get_bake_fps();
}
p_track.scale_track.times = new_times;

Expand All @@ -6597,11 +6598,11 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
for (int32_t key_i = 0; key_i < keys; key_i++) {
Vector3 bezier_track = p_track.scale_track.values[key_i];
if (path.contains(":scale:x")) {
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":scale:y")) {
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":scale:z")) {
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
}
p_track.scale_track.values.write[key_i] = bezier_track;
}
Expand All @@ -6612,7 +6613,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
Vector<real_t> new_times;
new_times.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) {
new_times.write[key_i] = key_i / BAKE_FPS;
new_times.write[key_i] = key_i / p_state->get_bake_fps();
}
p_track.position_track.times = new_times;

Expand All @@ -6622,11 +6623,11 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
for (int32_t key_i = 0; key_i < keys; key_i++) {
Vector3 bezier_track = p_track.position_track.values[key_i];
if (path.contains(":position:x")) {
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":position:y")) {
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":position:z")) {
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
}
p_track.position_track.values.write[key_i] = bezier_track;
}
Expand All @@ -6636,7 +6637,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
Vector<real_t> new_times;
new_times.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) {
new_times.write[key_i] = key_i / BAKE_FPS;
new_times.write[key_i] = key_i / p_state->get_bake_fps();
}
p_track.rotation_track.times = new_times;

Expand All @@ -6645,13 +6646,13 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
for (int32_t key_i = 0; key_i < keys; key_i++) {
Quaternion bezier_track = p_track.rotation_track.values[key_i];
if (path.contains(":rotation:x")) {
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":rotation:y")) {
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":rotation:z")) {
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
} else if (path.contains(":rotation:w")) {
bezier_track.w = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
bezier_track.w = p_animation->bezier_track_interpolate(p_track_i, key_i / p_state->get_bake_fps());
}
p_track.rotation_track.values.write[key_i] = bezier_track;
}
Expand Down Expand Up @@ -7305,6 +7306,7 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, boo
ERR_FAIL_NULL_V(state, nullptr);
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
Error err = OK;
p_state->set_bake_fps(p_bake_fps);
Node *root = _generate_scene_node_tree(state);
ERR_FAIL_NULL_V(root, nullptr);
_process_mesh_instances(state, root);
Expand All @@ -7313,7 +7315,7 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, boo
root->add_child(ap, true);
ap->set_owner(root);
for (int i = 0; i < state->animations.size(); i++) {
_import_animation(state, ap, i, p_bake_fps, p_trimming, p_remove_immutable_tracks);
_import_animation(state, ap, i, p_trimming, p_remove_immutable_tracks);
}
}
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
Expand Down
3 changes: 1 addition & 2 deletions modules/gltf/gltf_document.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ class GLTFDocument : public Resource {
};

private:
const float BAKE_FPS = 30.0f;
int _naming_version = 1;
String _image_format = "PNG";
float _lossy_quality = 0.75f;
Expand Down Expand Up @@ -328,7 +327,7 @@ class GLTFDocument : public Resource {
void _generate_scene_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root);
void _generate_skeleton_bone_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root);
void _import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player,
const GLTFAnimationIndex p_index, const float p_bake_fps, const bool p_trimming, const bool p_remove_immutable_tracks);
const GLTFAnimationIndex p_index, const bool p_trimming, const bool p_remove_immutable_tracks);
void _convert_mesh_instances(Ref<GLTFState> p_state);
GLTFCameraIndex _convert_camera(Ref<GLTFState> p_state, Camera3D *p_camera);
void _convert_light_to_gltf(Light3D *p_light, Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node);
Expand Down
Loading

0 comments on commit f25676c

Please sign in to comment.