Skip to content

Commit

Permalink
Fix animation processing interpolation bug, crash on no merc material (
Browse files Browse the repository at this point in the history
…#3794)

Fixes the issue with animations doing a full 180 degree rotation and
disappearing. The quaternions in the GLB export "flip", and when
interpolating animation frames in between a flip, we got bogus
quaternions.

Fixes #3786

Also fix a crash in `goalc` when using merc models without any
materials.

Co-authored-by: water111 <[email protected]>
  • Loading branch information
water111 and water111 authored Dec 7, 2024
1 parent 6e4e5d2 commit a2f9d36
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
7 changes: 4 additions & 3 deletions goalc/build_actor/common/MercExtract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ void extract(const std::string& name,
out.new_model.max_draws = 0;

auto process_normal_draw = [&](tfrag3::MercEffect& eff, int mat_idx, const tfrag3::MercDraw& d_) {
const auto& mat = model.materials[mat_idx];
eff.all_draws.push_back(d_);
auto& draw = eff.all_draws.back();
draw.mode = gltf_util::make_default_draw_mode();
Expand All @@ -107,6 +106,8 @@ void extract(const std::string& name,
draw.tree_tex_id = 0;
return;
}
const auto& mat = model.materials[mat_idx];

int tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index;
if (tex_idx == -1) {
lg::warn("Material {} has no texture, using default texture.", mat.name);
Expand Down Expand Up @@ -172,8 +173,8 @@ void extract(const std::string& name,
};

for (const auto& [mat_idx, d_] : draw_by_material) {
const auto& mat = model.materials[mat_idx];
if (!gltf_util::material_has_envmap(mat) || !gltf_util::envmap_is_valid(mat)) {
if (mat_idx < 0 || !gltf_util::material_has_envmap(model.materials[mat_idx]) ||
!gltf_util::envmap_is_valid(model.materials[mat_idx])) {
process_normal_draw(e, mat_idx, d_);
} else {
envmap_eff.has_envmap = true;
Expand Down
25 changes: 17 additions & 8 deletions goalc/build_actor/common/animation_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ int find_max_joint(const tinygltf::Animation& anim, const std::map<int, int>& no
template <typename T>
std::vector<T> compute_keyframes(const std::vector<float>& times,
const std::vector<T>& values,
float framerate) {
float framerate,
bool quaternion_interp) {
std::vector<T> ret;
ASSERT(!times.empty());
ASSERT(times.size() == values.size());
Expand All @@ -36,8 +37,15 @@ std::vector<T> compute_keyframes(const std::vector<float>& times,
}

const float fraction = (t - times.at(i)) / (times.at(i + 1) - times.at(i));
ret.push_back(values.at(i) * (1.f - fraction) + values.at(i + 1) * fraction);
// lg::info("{} + {:.3f}, {}", i, fraction, ret.back().to_string_aligned());
if (quaternion_interp) {
float multiplier = 1;
if (values.at(i).dot(values.at(i + 1)) < 0) {
multiplier = -1;
}
ret.push_back(values.at(i) * (1.f - fraction) + values.at(i + 1) * fraction * multiplier);
} else {
ret.push_back(values.at(i) * (1.f - fraction) + values.at(i + 1) * fraction);
}
t += 1.f / framerate;
}
return ret;
Expand All @@ -47,12 +55,13 @@ template <int n>
std::vector<math::Vector<float, n>> extract_keyframed_gltf_vecn(
const tinygltf::Model& model,
const tinygltf::AnimationSampler& sampler,
float framerate) {
float framerate,
bool quaternion_interp) {
std::vector<float> times = gltf_util::extract_floats(model, sampler.input);
std::vector<math::Vector<float, n>> values =
gltf_util::extract_vec<float, n>(model, sampler.output, TINYGLTF_COMPONENT_TYPE_FLOAT);
ASSERT(times.size() == values.size());
return compute_keyframes(times, values, framerate);
return compute_keyframes(times, values, framerate, quaternion_interp);
}
} // namespace

Expand All @@ -75,13 +84,13 @@ UncompressedJointAnim extract_anim_from_gltf(const tinygltf::Model& model,
const auto& sampler = anim.samplers.at(channel.sampler);
if (channel.target_path == "translation") {
out.joints.at(channel_joint).trans_frames =
extract_keyframed_gltf_vecn<3>(model, sampler, framerate);
extract_keyframed_gltf_vecn<3>(model, sampler, framerate, false);
} else if (channel.target_path == "rotation") {
out.joints.at(channel_joint).quat_frames =
extract_keyframed_gltf_vecn<4>(model, sampler, framerate);
extract_keyframed_gltf_vecn<4>(model, sampler, framerate, true);
} else if (channel.target_path == "scale") {
out.joints.at(channel_joint).scale_frames =
extract_keyframed_gltf_vecn<3>(model, sampler, framerate);
extract_keyframed_gltf_vecn<3>(model, sampler, framerate, false);
} else {
lg::die("unknown target_path {}", channel.target_path);
}
Expand Down

0 comments on commit a2f9d36

Please sign in to comment.