1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Add glTF STEP interpolation support (#15525)

This commit is contained in:
Lars Müller 2024-12-24 15:25:07 +01:00 committed by GitHub
parent d1dd044455
commit b087e2554f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 37 additions and 7 deletions

View file

@ -677,8 +677,17 @@ void SelfType::MeshExtractor::loadAnimation(const std::size_t animIdx)
for (const auto &channel : anim.channels) {
const auto &sampler = anim.samplers.at(channel.sampler);
if (sampler.interpolation != tiniergltf::AnimationSampler::Interpolation::LINEAR)
throw std::runtime_error("unsupported interpolation, only linear interpolation is supported");
bool interpolate = ([&]() {
switch (sampler.interpolation) {
case tiniergltf::AnimationSampler::Interpolation::STEP:
return false;
case tiniergltf::AnimationSampler::Interpolation::LINEAR:
return true;
default:
throw std::runtime_error("Only STEP and LINEAR keyframe interpolation are supported");
}
})();
const auto inputAccessor = Accessor<f32>::make(m_gltf_model, sampler.input);
const auto n_frames = inputAccessor.getCount();
@ -686,32 +695,38 @@ void SelfType::MeshExtractor::loadAnimation(const std::size_t animIdx)
if (!channel.target.node.has_value())
throw std::runtime_error("no animated node");
const auto &joint = m_loaded_nodes.at(*channel.target.node);
auto *joint = m_loaded_nodes.at(*channel.target.node);
switch (channel.target.path) {
case tiniergltf::AnimationChannelTarget::Path::TRANSLATION: {
const auto outputAccessor = Accessor<core::vector3df>::make(m_gltf_model, sampler.output);
auto &channel = joint->keys.position;
channel.interpolate = interpolate;
for (std::size_t i = 0; i < n_frames; ++i) {
f32 frame = inputAccessor.get(i);
core::vector3df position = outputAccessor.get(i);
m_irr_model->addPositionKey(joint, frame, convertHandedness(position));
channel.pushBack(frame, convertHandedness(position));
}
break;
}
case tiniergltf::AnimationChannelTarget::Path::ROTATION: {
const auto outputAccessor = Accessor<core::quaternion>::make(m_gltf_model, sampler.output);
auto &channel = joint->keys.rotation;
channel.interpolate = interpolate;
for (std::size_t i = 0; i < n_frames; ++i) {
f32 frame = inputAccessor.get(i);
core::quaternion rotation = outputAccessor.get(i);
m_irr_model->addRotationKey(joint, frame, convertHandedness(rotation));
channel.pushBack(frame, convertHandedness(rotation));
}
break;
}
case tiniergltf::AnimationChannelTarget::Path::SCALE: {
const auto outputAccessor = Accessor<core::vector3df>::make(m_gltf_model, sampler.output);
auto &channel = joint->keys.scale;
channel.interpolate = interpolate;
for (std::size_t i = 0; i < n_frames; ++i) {
f32 frame = inputAccessor.get(i);
core::vector3df scale = outputAccessor.get(i);
m_irr_model->addScaleKey(joint, frame, scale);
channel.pushBack(frame, scale);
}
break;
}