code wiki / (root) / nx_autorig_mesh.nx

nx_autorig_mesh.nx source

↩ module page · 79 lines · 3877 B

1// nx_autorig_mesh.nx -- ONE-CALL SOVEREIGN AUTO-RIG OF A BARE MESH: skeleton then skin weights in a SINGLE 2// invocation, composing nx_curveskel_lib (cs_run) and nx_boneheat_lib (bh_run). This is the DC16 "arbitrary 3// topology" entry point: "run two tools in order" is not a delivered capability, one call is. Blender's Rigify 4// only assembles a control rig from a meta-rig a human PLACES, and UniRig/RigNet predict with a learned model; 5// this is the classical deterministic route, no checkpoint and no data, bare mesh in and a skinned rigged NXA out. 6// It emits the skeleton and the skinned rig as TWO EXPLICIT artifacts -- no hidden sibling writes -- geodesic 7// weights by default. Its neutrality is provable and its gate proves it: the one-call output is BYTE-IDENTICAL 8// to cs_run then bh_run run separately, so this organ adds an entry point and changes no arithmetic. 9// UNITS/format inherited from the composed libs (NXA v1, 0.01 mm). license_tier: ORIGINAL expect_exit: 0 10import "nx_syscalls.nx" 11import "nx_curveskel_lib.nx" 12 13const AM_CELLS_DEFAULT: i64 = 64 // bone-heat grid resolution default; overridable, derived from the asset otherwise 14const AM_EXIT_OK: i64 = 0 15const AM_EXIT_USAGE: i64 = 2 16const AM_EXIT_SKEL: i64 = 3 // the skeleton stage refused (a volumeless sheet, an unreadable mesh) 17const AM_EXIT_SKIN: i64 = 4 // the weight stage refused (no skeleton to weight against) 18 19func amw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 20func amn(v: i64) -> i64 { 21 let b: *u8 = sys_mmap(32) 22 var x: i64 = v 23 if x < 0 { b[0] = 45 as u8; sys_write(1, b, 1); x = 0 - x } 24 if x == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 25 var d: i64 = 0 26 var y: i64 = x 27 while y > 0 { d = d + 1; y = y / 10 } 28 var i: i64 = d 29 while i > 0 { i = i - 1; b[i] = ((x % 10) + 48) as u8; x = x / 10 } 30 sys_write(1, b, d) 31 return 0 32} 33func am_atoi(s: *u8) -> i64 { 34 var v: i64 = 0 35 var i: i64 = 0 36 while s[i] != (0 as u8) { 37 let c: i64 = s[i] as i64 38 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } 39 i = i + 1 40 } 41 return v 42} 43// compose: bare -> skeleton (cs_run) -> skinned (bh_run geodesic). crep/brep are the composed libs' own reports, 44// zeroed here so a caller reads them straight. Returns AM_EXIT_OK, or the stage code of the first refusal. 45func amesh_run(bare: *u8, skel: *u8, skinned: *u8, cells: i64, crep: *i64, brep: *i64) -> i64 { 46 var k: i64 = 0 47 while k < CR_WORDS { crep[k] = 0; k = k + 1 } 48 let rcS: i64 = cs_run(bare, skel, crep) 49 if rcS != CS_EXIT_OK { return AM_EXIT_SKEL } 50 k = 0 51 while k < BR_WORDS { brep[k] = 0; k = k + 1 } 52 let rcB: i64 = bh_run(skel, skinned, BH_MODE_GEODESIC, cells, brep) 53 if rcB != BH_EXIT_OK { return AM_EXIT_SKIN } 54 return AM_EXIT_OK 55} 56func main(argc: i64, argv: *i64) -> i64 { 57 if argc < 4 { 58 amw("usage: nx_autorig_mesh <bare.nxa> <skel_out.nxa> <skinned_out.nxa> [cells]\n" as *u8) 59 return AM_EXIT_USAGE 60 } 61 let bare: *u8 = argv[1] as *u8 62 let skel: *u8 = argv[2] as *u8 63 let skinned: *u8 = argv[3] as *u8 64 var cells: i64 = AM_CELLS_DEFAULT 65 if argc >= 5 { cells = am_atoi(argv[4] as *u8) } 66 if cells < 1 { cells = AM_CELLS_DEFAULT } 67 let crep: *i64 = sys_mmap(CR_WORDS * 8) as *i64 68 let brep: *i64 = sys_mmap(BR_WORDS * 8) as *i64 69 let rc: i64 = amesh_run(bare, skel, skinned, cells, crep, brep) 70 cs_report(crep, bare, skel) 71 if rc == AM_EXIT_OK { bh_report(BH_MODE_GEODESIC, brep, skel, skinned) } 72 amw("NXAUTORIG-MESH rc=" as *u8); amn(rc) 73 amw(" limbs=" as *u8); amn(crep[CR_LIMBS]) 74 amw(" joints=" as *u8); amn(crep[CR_JOINTS]) 75 amw(" branches=" as *u8); amn(crep[CR_BRANCHES]) 76 amw(" mixed_verts=" as *u8); amn(brep[BR_MIXED]) 77 amw("\n" as *u8) 78 return rc 79}