ludic/packages/ludic.anim/ozz.ludic
Orkuncakilkaya 9a56ee9b9d feat(ludic.anim): ozz-animation 0.17.0 underneath - a skin's skeleton and each clip built at load, sampled to 1e-4 of anim_mix (phase 19.1)
No bake and no new file: the skeleton comes from the skin's parents and rest pose (its own joints
and their ancestors - a kit holds several rigs), a clip from anim_read_doc's channels. Built by
native/build.sh from the pinned release; the Windows DLL imports KERNEL32 alone and passes there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:44:49 +03:00

46 lines
2.2 KiB
Text

# ozz.ludic - a skin's skeleton and a clip built in ozz-animation at load, and a clip sampled through
# it (phase 19.1): the numbers are the ones the package already holds, the skin's parents and rest
# pose and a clip's flattened channels, so nothing is baked and no file is added
# the skeleton of a skin: its joints and their ancestors, and no other node - a kit's file holds
# several rigs, and each actor samples only its own
export function anim_oz_skel(sk: Skin) -> pointer {
if sk == null or sk.n_nodes <= 0 { return null }
let n = sk.n_nodes
let rest = floats(n * 10)
let par = words(n)
for i in 0 .. n { par[i] = -2 }
for j in 0 .. sk.n_joints {
var at = sk.joints[j]
while at >= 0 and par[at] == -2 {
par[at] = sk.par[at]
at = sk.par[at]
}
}
for i in 0 .. n {
for k in 0 .. 3 { rest[i * 10 + k] = sk.rest_t[i * 3 + k] }
for k in 0 .. 4 { rest[i * 10 + 3 + k] = sk.rest_r[i * 4 + k] }
for k in 0 .. 3 { rest[i * 10 + 7 + k] = sk.rest_s[i * 3 + k] }
}
return ozz_skel_new(n, par, rest)
}
export function anim_oz_skel_free(s: pointer) -> void { if s != null { ozz_skel_free(s) } }
export function anim_oz_joints(s: pointer) -> int { return ozz_skel_joints(s) }
# a clip for that skeleton; its translations only when the table plays them (anim_set_positions)
export function anim_oz_clip(anim_st: AnimState, s: pointer, c: Clip) -> pointer {
if s == null or c == null { return null }
var p = 0
if anim_st.positions { p = 1 }
return ozz_clip_new(s, c.dur, c.n, c.cnode, c.cpath, c.ckeys, c.coff, c.cvoff, c.times, c.vals, p)
}
export function anim_oz_clip_free(c: pointer) -> void { if c != null { ozz_clip_free(c) } }
export function anim_oz_clip_bytes(c: pointer) -> int { return ozz_clip_bytes(c) }
# what one actor samples with, made once; a clip sampled at t into rot (4 a node) and pos (3 a node)
export function anim_oz_ctx(s: pointer) -> pointer { return ozz_ctx_new(s) }
export function anim_oz_ctx_free(c: pointer) -> void { if c != null { ozz_ctx_free(c) } }
export function anim_oz_sample(ctx: pointer, clip: pointer, t: float, rot: floats, pos: floats, n: int) -> bool {
if ctx == null or clip == null or len(rot) < n * 4 or len(pos) < n * 3 { return false }
return ozz_sample(ctx, clip, t, rot, pos, n) == 1
}