From 086067cfa95dfbf8c1f4f9c0b9453f520dcdeadf Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 29 Jun 2026 23:55:52 +0300 Subject: [PATCH] add declarative skeleton animation component (WIP) --- res/scripts/components/animator.lua | 154 ++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 res/scripts/components/animator.lua diff --git a/res/scripts/components/animator.lua b/res/scripts/components/animator.lua new file mode 100644 index 000000000..2bcaadc6b --- /dev/null +++ b/res/scripts/components/animator.lua @@ -0,0 +1,154 @@ +local tsf = entity.transform +local rig = entity.skeleton +local body = entity.rigidbody + + +local body_idx = rig:index("body") + +local leg_left = rig:index("leg_left") +local leg_right = rig:index("leg_right") + +local leg_left_btm = rig:index("leg_left_btm") +local leg_right_btm = rig:index("leg_right_btm") + +local hand_left = rig:index("hand_left") +local hand_right = rig:index("hand_right") + +local hand_left_btm = rig:index("hand_left_btm") +local hand_right_btm = rig:index("hand_right_btm") + + +local tm_offset = random.random(10) +local prev_speed = 0.0 + +local CH_TRANSLATE = 1 +local CH_ROTATE = 2 + +local AX_X = 1 +local AX_Y = 2 +local AX_Z = 3 + +local function compile_track(bone_index, lines) + local env = { + mat4 = mat4, + } + table.extend(env, math) + + local code = "" + local translation = {false, false, false} + local rotation = {false, false, false} + for i, line in ipairs(lines) do + code = code .. "\n local l" .. i .. " = (" .. line.expression .. ")" + if line.channel == CH_TRANSLATE then + translation[line.axis] = i + elseif line.channel == CH_ROTATE then + rotation[line.axis] = i + end + end + + code = code .. "\n mat4.idt(dst)" + if translation[1] or translation[2] or translation[3] then + code = code .. "\n mat4.translate(dst, {" .. + (translation[1] and ("l" .. translation[1]) or '0').. ", " .. + (translation[2] and ("l" .. translation[2]) or '0').. ", " .. + (translation[3] and ("l" .. translation[3]) or '0').. "}, dst)" + end + + for axis, var in ipairs(rotation) do + if var then + code = code .. "\n mat4.rotate(dst, {" + .. ((axis == 1) and '1' or '0') .. ", " + .. ((axis == 2) and '1' or '0') .. ", " + .. ((axis == 3) and '1' or '0') .. "}, l" .. var .. ", dst)" + end + end + + local src = "return function(dst, t, m)" .. code .. "\n return dst\nend" + local generator, err = load(src, "", "bt", env) + if not generator then + error(err) + end + print(src) + return { + bone_index = bone_index, + generator = generator() + } +end + +local tracks = { + compile_track(body_idx, {{ + channel = CH_TRANSLATE, + axis = AX_Y, + expression = "sin(t * 2) * 0.1 * m" + }}), + compile_track(leg_left, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "sin(t) * 45 * m" + }}), + compile_track(leg_right, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "-sin(t) * 45 * m" + }}), + compile_track(leg_left_btm, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "(-sin(t * 2) * 45 - 45) * m" + }}), + compile_track(leg_right_btm, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "(-sin(t * 2) * 45 - 45) * m" + }}), + compile_track(hand_left, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "-sin(t) * 45 * m" + }}), + compile_track(hand_right, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "sin(t) * 45 * m" + }}), + compile_track(hand_left_btm, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "(sin(t * 2) * 45 + 45) * m" + }}), + compile_track(hand_right_btm, {{ + channel = CH_ROTATE, + axis = AX_X, + expression = "(sin(t * 2) * 45 + 45) * m" + }}), +} + +function on_render() + local tm = time.uptime() * 10 + tm_offset + local speed = vec3.length(body:get_vel()) / 7.0 + local delta = time.delta() + + prev_speed = prev_speed * (1.0 - delta * 10) + speed * delta * 10 + speed = prev_speed + + local ttm = time.precise_time() + local matrix = mat4.idt() + for i, track in ipairs(tracks) do + rig:set_matrix(track.bone_index, track.generator(matrix, tm, speed)) + end + + -- rig:set_matrix(body_idx, mat4.translate({0, math.sin(tm * 2) * 0.1 * speed, 0})) + + -- rig:set_matrix(leg_left, mat4.rotate({1, 0, 0}, (math.sin(tm) * 45) * speed)) + -- rig:set_matrix(leg_right, mat4.rotate({1, 0, 0}, (-math.sin(tm) * 45) * speed)) + + -- rig:set_matrix(leg_left_btm, mat4.rotate({1, 0, 0}, (-math.sin(tm * 2) * 45 - 45) * speed)) + -- rig:set_matrix(leg_right_btm, mat4.rotate({1, 0, 0}, (-math.sin(tm * 2) * 45 - 45) * speed)) + + -- rig:set_matrix(hand_left, mat4.rotate({1, 0, 0}, (-math.sin(tm) * 45) * speed)) + -- rig:set_matrix(hand_right, mat4.rotate({1, 0, 0}, (math.sin(tm) * 45) * speed)) + + -- rig:set_matrix(hand_left_btm, mat4.rotate({1, 0, 0}, (math.sin(tm * 2) * 45 + 45) * speed)) + -- rig:set_matrix(hand_right_btm, mat4.rotate({1, 0, 0}, (math.sin(tm * 2) * 45 + 45) * speed)) + print(math.floor((time.precise_time() - ttm) * 1e6), "mcs") +end