code wiki / _hdl_build / nx_native_turntable.nx
nx_native_turntable.nx source
↩ module page · 73 lines · 3127 B
1// nx_native_turntable.nx -- FIRST-BIT-NATIVE MOTION VISUAL for the benchmark pages: load our .glb
2// with OUR loader, rasterize K turntable frames with OUR renderer, encode with OUR APNG writer.
3// No host GL, no third-party code anywhere in the chain: model -> render -> encode is all nishi,
4// and the output plays in any browser (APNG IS a PNG) including the Nishi browser's own decoders.
5// Also writes frame 0 as the native STILL. Composes nx_gltf_load + nx_trimesh + nx_png + nx_apng_write.
6// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_png.nx"
9import "nx_trimesh.nx"
10import "nx_gltf_load.nx"
11import "nx_apng_write.nx"
12const NT_MAGIC_6283: i64 = 6283
13const NT_MAGIC_2600: i64 = 2600
14
15// sized to the edge serve buffer: NX_SD2_DYN_CAP = 8MiB; 20 frames @ 240x368 RGB stored ~= 5.3MB
16const NT_W: i64 = 240
17const NT_H: i64 = 368
18const NT_FRAMES: i64 = 20
19const NT_BG: i64 = 24 + 26*256 + 34*65536
20
21func nt_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
22func nt_num(v: i64) -> i64 {
23 let b: *u8 = sys_mmap(32)
24 var x: i64 = v; var i: i64 = 31
25 if x == 0 { b[i]=48 as u8; i=i-1 }
26 while x > 0 { b[i]=(48+x%10) as u8; x=x/10; i=i-1 }
27 sys_write(1,(b as i64+i+1) as *u8,31-i)
28 return 0
29}
30
31func main() -> i64 {
32 nt_w("=== nx_native_turntable -- glb -> nishi raster -> nishi APNG (zero foreign bits) ===\n" as *u8)
33 let ok: i64 = gltf_load("knowledge/nishi_being.glb" as *u8)
34 if ok != 1 { nt_w("FAIL: glb load\n" as *u8); sys_exit(1); return 1 }
35 nt_w("loaded verts=" as *u8); nt_num(tm_nv()); nt_w(" tris=" as *u8); nt_num(tm_nt()); nt_w("\n" as *u8)
36
37 let npx: i64 = NT_W * NT_H
38 let fb: *i64 = sys_mmap(npx * 8) as *i64
39 let zb: *i64 = sys_mmap(npx * 8) as *i64
40 let rgb: *u8 = sys_mmap(npx * 3 + 16)
41
42 let st_raw: *u8 = sys_mmap(NX_APNG_STATE_BYTES)
43 let st: *ApngState = st_raw as *ApngState
44 if apng_open(st, "knowledge/nishi_native_turntable.png" as *u8, NT_W, NT_H, NT_FRAMES, 6, 100) != 0 {
45 nt_w("FAIL: apng open\n" as *u8); sys_exit(1); return 1
46 }
47
48 var f: i64 = 0
49 while f < NT_FRAMES {
50 var i: i64 = 0
51 while i < npx { fb[i] = NT_BG; i = i + 1 }
52 trimesh_zclear(zb, npx)
53 let yaw: i64 = f * NT_MAGIC_6283 / NT_FRAMES
54 trimesh_render(fb, zb, NT_W, NT_H, yaw, 0-200, NT_MAGIC_2600, 520, 2)
55 // pack the i64 framebuffer (r + g<<8 + b<<16) into RGB bytes for the APNG encoder
56 i = 0
57 while i < npx {
58 let px: i64 = fb[i]
59 rgb[i*3] = (px & 255) as u8
60 rgb[i*3+1] = ((px >> 8) & 255) as u8
61 rgb[i*3+2] = ((px >> 16) & 255) as u8
62 i = i + 1
63 }
64 apng_frame(st, rgb)
65 if f == 0 { write_png(fb, NT_W, NT_H, "knowledge/nishi_native_still.png" as *u8) }
66 f = f + 1
67 }
68 apng_close(st)
69 nt_w("WROTE knowledge/nishi_native_turntable.png (" as *u8); nt_num(NT_FRAMES)
70 nt_w(" frames, native chain: nx_gltf_load -> nx_trimesh -> nx_apng_write) + nishi_native_still.png\n" as *u8)
71 sys_exit(0)
72 return 0
73}