Add glTF STEP interpolation support (#15525)
This commit is contained in:
@@ -318,7 +318,7 @@ Many glTF features are not supported *yet*, including:
|
||||
|
||||
* Animations
|
||||
* Only a single animation is supported, use frame ranges within this animation.
|
||||
* Only linear interpolation is supported.
|
||||
* `CUBICSPLINE` interpolation is not supported.
|
||||
* Cameras
|
||||
* Materials
|
||||
* Only base color textures are supported
|
||||
|
||||
@@ -55,6 +55,20 @@ core.register_entity("gltf:simple_skin", {
|
||||
end
|
||||
})
|
||||
|
||||
core.register_entity("gltf:simple_skin_step", {
|
||||
initial_properties = {
|
||||
infotext = "Simple skin, but using STEP interpolation",
|
||||
visual = "mesh",
|
||||
visual_size = vector.new(5, 5, 5),
|
||||
mesh = "gltf_simple_skin_step.gltf",
|
||||
textures = {},
|
||||
backface_culling = false
|
||||
},
|
||||
on_activate = function(self)
|
||||
self.object:set_animation({x = 0, y = 5.5}, 1)
|
||||
end
|
||||
})
|
||||
|
||||
-- The claws rendering incorrectly from one side is expected behavior:
|
||||
-- They use an unsupported double-sided material.
|
||||
core.register_entity("gltf:frog", {
|
||||
|
||||
BIN
games/devtest/mods/gltf/models/gltf_simple_skin_step.gltf
Normal file
BIN
games/devtest/mods/gltf/models/gltf_simple_skin_step.gltf
Normal file
Binary file not shown.
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user