mirror of
https://github.com/open-goal/jak-project
synced 2026-07-09 06:53:45 -04:00
Fix animation processing interpolation bug, crash on no merc material (#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 https://github.com/open-goal/jak-project/issues/3786 Also fix a crash in `goalc` when using merc models without any materials. Co-authored-by: water111 <awaterford1111445@gmail.com>
This commit is contained in:
@@ -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();
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user