code wiki / (root) / nx_scene.nx

nx_scene.nx source

↩ module page · 139 lines · 5099 B

1// nx_scene.nx -- SCENE / POSITION as DATA (beat-HS2 rung 2: the Illusion-family "scene"/"position" concept, 2// on OUR moddable-data law). A scene = a set of CHANNELS, each a keyframed timeline {time, value}; sampling 3// at time t linearly interpolates (integer) the surrounding keys. Channels address anything drivable by id: 4// IK-target axes, morph weights, region params, camera. Sampled channel values feed the character stack 5// (skeleton IK targets / morph banks / region params) -- so a SCENE PACK (NXSC1) drives the whole rig, and 6// scenes flow through the CID mod economy exactly like block/morph/anatomy packs. ALL INTEGER, deterministic. 7// license_tier: ORIGINAL 8import "nx_syscalls.nx" 9const SC_MAGIC_2147483648: i64 = 2147483648 10const SC_MAGIC_4294967296: i64 = 4294967296 11 12// header: [0]=nchannels [1]=nkeys_total [2]=duration 13// channel dir at 64: 4 slots {target_id, nkeys, key_off, spare} 14// key pool after dir: 2 slots {time, value} 15const SC_MAXC: i64 = 64 16const SC_MAXK: i64 = 4096 17 18func sc_hdr(base: i64) -> *i64 { return base as *i64 } 19func sc_chan(base: i64, c: i64) -> *i64 { return (base + 64 + c * 32) as *i64 } 20func sc_key(base: i64, k: i64) -> *i64 { return (base + 64 + SC_MAXC * 32 + k * 16) as *i64 } 21func sc_bytes() -> i64 { return 64 + SC_MAXC * 32 + SC_MAXK * 16 + 64 } 22 23func sc_init(base: i64) -> i64 { 24 let h: *i64 = sc_hdr(base) 25 h[0] = 0 26 h[1] = 0 27 h[2] = 0 28 return 0 29} 30func sc_channel(base: i64, target_id: i64) -> i64 { 31 let h: *i64 = sc_hdr(base) 32 if h[0] >= SC_MAXC { return 0 - 1 } 33 let c: *i64 = sc_chan(base, h[0]) 34 c[0] = target_id 35 c[1] = 0 36 c[2] = h[1] 37 h[0] = h[0] + 1 38 return h[0] - 1 39} 40// keys MUST be added in ascending time per channel (the sampler assumes sorted) 41func sc_key_add(base: i64, chan: i64, time: i64, value: i64) -> i64 { 42 let h: *i64 = sc_hdr(base) 43 if h[1] >= SC_MAXK { return 0 - 1 } 44 let k: *i64 = sc_key(base, h[1]) 45 k[0] = time 46 k[1] = value 47 let c: *i64 = sc_chan(base, chan) 48 c[1] = c[1] + 1 49 h[1] = h[1] + 1 50 if time > h[2] { h[2] = time } 51 return 0 52} 53func sc_target(base: i64, chan: i64) -> i64 { let c: *i64 = sc_chan(base, chan); return c[0] } 54func sc_duration(base: i64) -> i64 { let h: *i64 = sc_hdr(base); return h[2] } 55 56// sample channel `chan` at time t: clamp before-first/after-last, else linear-interp the bracketing keys 57func sc_sample(base: i64, chan: i64, t: i64) -> i64 { 58 let c: *i64 = sc_chan(base, chan) 59 let n: i64 = c[1] 60 let off: i64 = c[2] 61 if n == 0 { return 0 } 62 let first: *i64 = sc_key(base, off) 63 if t <= first[0] { return first[1] } 64 let last: *i64 = sc_key(base, off + n - 1) 65 if t >= last[0] { return last[1] } 66 var i: i64 = 0 67 while i < n - 1 { 68 let ka: *i64 = sc_key(base, off + i) 69 let kb: *i64 = sc_key(base, off + i + 1) 70 if t >= ka[0] { if t <= kb[0] { 71 let span: i64 = kb[0] - ka[0] 72 if span == 0 { return ka[1] } 73 return ka[1] + (kb[1] - ka[1]) * (t - ka[0]) / span 74 } } 75 i = i + 1 76 } 77 return last[1] 78} 79 80// ---- NXSC1 pack: "NXSC" + nchan + dur + per-channel {target,nkeys}{keys...} as i32 LE ---- 81func sc_w32(buf: *u8, off: i64, v: i64) -> i64 { 82 buf[off] = (v & 255) as u8 83 buf[off + 1] = ((v >> 8) & 255) as u8 84 buf[off + 2] = ((v >> 16) & 255) as u8 85 buf[off + 3] = ((v >> 24) & 255) as u8 86 return 0 87} 88func sc_r32(buf: *u8, off: i64) -> i64 { 89 var v: i64 = (buf[off] as i64) | ((buf[off + 1] as i64) << 8) | ((buf[off + 2] as i64) << 16) | ((buf[off + 3] as i64) << 24) 90 if v >= SC_MAGIC_2147483648 { v = v - SC_MAGIC_4294967296 } 91 return v 92} 93func sc_save(base: i64, buf: *u8) -> i64 { 94 let h: *i64 = sc_hdr(base) 95 buf[0] = 78 as u8; buf[1] = 88 as u8; buf[2] = 83 as u8; buf[3] = 67 as u8 // "NXSC" 96 sc_w32(buf, 4, h[0]) 97 sc_w32(buf, 8, h[2]) 98 var p: i64 = 12 99 var c: i64 = 0 100 while c < h[0] { 101 let ch: *i64 = sc_chan(base, c) 102 sc_w32(buf, p, ch[0]); sc_w32(buf, p + 4, ch[1]); p = p + 8 103 var k: i64 = 0 104 while k < ch[1] { 105 let key: *i64 = sc_key(base, ch[2] + k) 106 sc_w32(buf, p, key[0]); sc_w32(buf, p + 4, key[1]); p = p + 8 107 k = k + 1 108 } 109 c = c + 1 110 } 111 return p 112} 113func sc_load(base: i64, buf: *u8, len: i64) -> i64 { 114 if len < 12 { return 0 - 1 } 115 if buf[0] as i64 != 78 { return 0 - 1 } 116 if buf[1] as i64 != 88 { return 0 - 1 } 117 if buf[2] as i64 != 83 { return 0 - 1 } 118 if buf[3] as i64 != 67 { return 0 - 1 } 119 sc_init(base) 120 let nc: i64 = sc_r32(buf, 4) 121 var p: i64 = 12 122 var c: i64 = 0 123 while c < nc { 124 if p + 8 > len { return 0 - 1 } 125 let target: i64 = sc_r32(buf, p) 126 let nk: i64 = sc_r32(buf, p + 4) 127 p = p + 8 128 let ci: i64 = sc_channel(base, target) 129 var k: i64 = 0 130 while k < nk { 131 if p + 8 > len { return 0 - 1 } 132 sc_key_add(base, ci, sc_r32(buf, p), sc_r32(buf, p + 4)) 133 p = p + 8 134 k = k + 1 135 } 136 c = c + 1 137 } 138 return nc 139}