leef-b3d-cd2025/read_b3d_bone.lua
2023-08-28 17:38:31 -07:00

70 lines
2.3 KiB
Lua

--INACTIVE FILE
local binary_search_frame = modlib.table.binary_search_comparator(function(a, b)
return modlib.table.default_comparator(a, b.frame)
end)
--> list of { bone_name = string, parent_bone_name = string, position = vector, rotation = quaternion, scale = vector }
function get_animated_bone_properties(self, keyframe, interpolate)
local function get_frame_values(keys)
local values = keys[keyframe]
if values and values.frame == keyframe then
return {
position = values.position,
rotation = values.rotation,
scale = values.scale
}
end
local index = binary_search_frame(keys, keyframe)
if index > 0 then
return keys[index]
end
index = -index
assert(index > 1 and index <= #keys)
local a, b = keys[index - 1], keys[index]
if not interpolate then
return a
end
local ratio = (keyframe - a.frame) / (b.frame - a.frame)
return {
position = (a.position and b.position and modlib.vector.interpolate(a.position, b.position, ratio)) or a.position or b.position,
rotation = (a.rotation and b.rotation and modlib.quaternion.slerp(a.rotation, b.rotation, ratio)) or a.rotation or b.rotation,
scale = (a.scale and b.scale and modlib.vector.interpolate(a.scale, b.scale, ratio)) or a.scale or b.scale,
}
end
local bone_properties = {}
local function get_props(node, parent_bone_name)
local properties = {parent_bone_name = parent_bone_name}
if keyframe > 0 and node.keys and next(node.keys) ~= nil then
modlib.table.add_all(properties, get_frame_values(node.keys))
end
if not properties.position then -- animation not present, fall back to node position
properties.position = modlib.table.copy(node.position)
end
if properties.rotation then -- animation is relative to node rotation
properties.rotation = modlib.quaternion.compose(node.rotation, properties.rotation)
else
properties.rotation = modlib.table.copy(node.rotation)
end
if not properties.scale then -- animation not present, fall back to node scale
properties.scale = modlib.table.copy(node.scale)
end
if node.bone then
properties.bone_name = node.name
table.insert(bone_properties, properties)
end
for _, child in pairs(node.children or {}) do
get_props(child, properties.bone_name)
end
end
get_props(self.node)
return bone_properties
end