nx_rigbench_motion_t21.nx source
↩ module page · 161 lines · 6775 B
1// Additive rigbench temporal contract; reuse the normative NXA evaluator.
2import "nx_syscalls.nx"
3import "nx_nxa.nx"
4import "nx_nxa_anim_lib.nx"
5const RBM_BYTES: i64 = 8
6const RBM_QUAT: i64 = 4
7const RBM_VERT_STRIDE: i64 = 3
8const RBM_SKIN_STRIDE: i64 = 8
9const RBM_OK: i64 = 0
10const RBM_ABSTAIN: i64 = 3
11const RBM_REFUSE: i64 = 4
12const RBM_R_JOINTS: i64 = 0
13const RBM_R_DURATION: i64 = 1
14const RBM_R_TRACKED: i64 = 2
15const RBM_R_CHANGED: i64 = 3
16const RBM_R_NONIDENTITY_A: i64 = 4
17const RBM_R_NONIDENTITY_B: i64 = 5
18const RBM_R_TIME_A: i64 = 6
19const RBM_R_TIME_B: i64 = 7
20const RBM_R_ASSET_RC: i64 = 8
21const RBM_R_CONSUMER_RC: i64 = 9
22const RBM_R_CONSUMER_MISMATCH_A: i64 = 10
23const RBM_R_CONSUMER_MISMATCH_B: i64 = 11
24const RBM_R_REASON: i64 = 12
25const RBM_R_WORDS: i64 = 13
26const RBM_REASON_NONE: i64 = 0
27const RBM_REASON_SHAPE: i64 = 1
28const RBM_REASON_NO_ANIM: i64 = 2
29const RBM_REASON_TIMES: i64 = 3
30const RBM_REASON_TRACKS: i64 = 4
31const RBM_REASON_STATIC: i64 = 5
32
33func rb_motion_init(rep: *i64) -> i64 {
34 var k: i64 = 0
35 while k < RBM_R_WORDS { rep[k] = 0; k = k + 1 }
36 rep[RBM_R_ASSET_RC] = RBM_ABSTAIN
37 rep[RBM_R_CONSUMER_RC] = RBM_ABSTAIN
38 rep[RBM_R_CONSUMER_MISMATCH_A] = 0 - 1
39 rep[RBM_R_CONSUMER_MISMATCH_B] = 0 - 1
40 return 0
41}
42// A dual quaternion and its simultaneous negation encode the same transform.
43// Comparisons use normative integer rows, before a renderer converts to f32.
44func rb_motion_row_equal(a: *i64, b: *i64, nj: i64, j: i64) -> i64 {
45 let ro: i64 = j * RBM_QUAT
46 let du: i64 = nj * RBM_QUAT + ro
47 var same: i64 = 1
48 var opposite: i64 = 1
49 var k: i64 = 0
50 while k < RBM_QUAT {
51 if a[ro+k] != b[ro+k] { same = 0 }
52 if a[du+k] != b[du+k] { same = 0 }
53 if a[ro+k] != 0-b[ro+k] { opposite = 0 }
54 if a[du+k] != 0-b[du+k] { opposite = 0 }
55 k = k + 1
56 }
57 if same == 1 { return 1 }
58 return opposite
59}
60func rb_motion_nonidentity(a: *i64, nj: i64, j: i64) -> i64 {
61 let ro: i64 = j * RBM_QUAT
62 let du: i64 = nj * RBM_QUAT + ro
63 var k: i64 = 0
64 while k < RBM_QUAT {
65 if a[du+k] != 0 { return 1 }
66 if k < RBM_QUAT-1 { if a[ro+k] != 0 { return 1 } }
67 k = k + 1
68 }
69 let qw: i64 = a[ro+RBM_QUAT-1]
70 if qw == NA_Q12 { return 0 }
71 if qw == 0-NA_Q12 { return 0 }
72 return 1
73}
74func rb_motion_fail(rep: *i64, rc: i64, reason: i64) -> i64 {
75 rep[RBM_R_ASSET_RC] = rc
76 rep[RBM_R_REASON] = reason
77 return rc
78}
79// Inputs are validated counted payloads. Caller owns buffers sized from nj.
80// Raw authored motion has no fitted root drift and no frozen-pose hold.
81func rb_motion_pair(anim: *i64, nw: i64, skel: *i64, nj: i64, ta: i64, tb: i64, idx: *i64, rv: *i64, a: *i64, b: *i64, scr: *i64, rep: *i64) -> i64 {
82 rb_motion_init(rep)
83 rep[RBM_R_JOINTS] = nj
84 rep[RBM_R_TIME_A] = ta
85 rep[RBM_R_TIME_B] = tb
86 if nj < 1 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
87 if ta < 0 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_TIMES) }
88 if tb <= ta { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_TIMES) }
89 let duration: i64 = na_index(anim,nw,nj,idx)
90 if duration < 0 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_TRACKS) }
91 rep[RBM_R_DURATION] = duration
92 if tb > duration { return rb_motion_fail(rep,RBM_ABSTAIN,RBM_REASON_TIMES) }
93 var j: i64 = 0
94 while j < nj { if idx[j*NA_IDX_W] >= 0 { rep[RBM_R_TRACKED] = rep[RBM_R_TRACKED]+1 } j=j+1 }
95 var k: i64 = 0
96 while k < NA_RV_W { rv[k]=0; k=k+1 }
97 na_rows(anim,idx,nj,skel,0 as *i64,0 as *i64,0,rv,ta,0,a,scr)
98 na_rows(anim,idx,nj,skel,0 as *i64,0 as *i64,0,rv,tb,0,b,scr)
99 j=0
100 while j < nj {
101 if rb_motion_row_equal(a,b,nj,j) == 0 { rep[RBM_R_CHANGED]=rep[RBM_R_CHANGED]+1 }
102 rep[RBM_R_NONIDENTITY_A]=rep[RBM_R_NONIDENTITY_A]+rb_motion_nonidentity(a,nj,j)
103 rep[RBM_R_NONIDENTITY_B]=rep[RBM_R_NONIDENTITY_B]+rb_motion_nonidentity(b,nj,j)
104 j=j+1
105 }
106 if rep[RBM_R_CHANGED] == 0 { return rb_motion_fail(rep,RBM_ABSTAIN,RBM_REASON_STATIC) }
107 return rb_motion_fail(rep,RBM_OK,RBM_REASON_NONE)
108}
109// API receipts must independently bind asset/evaluator/scene/observation hashes.
110// Matching these two palettes alone does not prove a visible rendered animation.
111func rb_motion_consumer(a: *i64,b: *i64,oa: *i64,ob: *i64,nj: i64,rep: *i64) -> i64 {
112 rep[RBM_R_CONSUMER_RC]=RBM_ABSTAIN
113 if rep[RBM_R_ASSET_RC] != RBM_OK { return RBM_ABSTAIN }
114 if nj != rep[RBM_R_JOINTS] { rep[RBM_R_CONSUMER_RC]=RBM_REFUSE; return RBM_REFUSE }
115 var j: i64 = 0
116 var ma: i64 = 0
117 var mb: i64 = 0
118 while j < nj {
119 if rb_motion_row_equal(a,oa,nj,j) == 0 { ma=ma+1 }
120 if rb_motion_row_equal(b,ob,nj,j) == 0 { mb=mb+1 }
121 j=j+1
122 }
123 rep[RBM_R_CONSUMER_MISMATCH_A]=ma
124 rep[RBM_R_CONSUMER_MISMATCH_B]=mb
125 if ma+mb > 0 { rep[RBM_R_CONSUMER_RC]=RBM_REFUSE; return RBM_REFUSE }
126 rep[RBM_R_CONSUMER_RC]=RBM_OK
127 return RBM_OK
128}
129func rb_motion_asset(b: *u8,flen: i64,ta: i64,tb: i64,max_joints: i64,rep: *i64) -> i64 {
130 rb_motion_init(rep)
131 let vo: i64 = nxa_counted_section(b,flen,nxa_tag4("VERT" as *u8),RBM_VERT_STRIDE)
132 let so: i64 = nxa_counted_section(b,flen,nxa_tag4("SKEL" as *u8),NA_SKEL_W)
133 let ko: i64 = nxa_counted_section(b,flen,nxa_tag4("SKIN" as *u8),RBM_SKIN_STRIDE)
134 if vo < 0 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
135 if so < 0 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
136 if ko < 0 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
137 let w: *i64 = b as *i64
138 let nj: i64 = w[so]
139 rep[RBM_R_JOINTS]=nj
140 if nj < 1 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
141 if nj > max_joints { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
142 if w[vo] != w[ko] { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
143 let ae: i64 = nxa_section_entry(b,flen,nxa_tag4("ANIM" as *u8))
144 if ae == 0-1 { return rb_motion_fail(rep,RBM_ABSTAIN,RBM_REASON_NO_ANIM) }
145 if ae < 0 { return rb_motion_fail(rep,RBM_REFUSE,RBM_REASON_SHAPE) }
146 let anim: *i64 = ((b as i64)+w[ae+1]) as *i64
147 let skel: *i64 = ((b as i64)+(so+1)*RBM_BYTES) as *i64
148 let ni: i64 = nj*NA_IDX_W*RBM_BYTES
149 let nr: i64 = nj*NA_ROW_W*RBM_BYTES
150 let ns: i64 = NA_SCR_W*RBM_BYTES
151 let nv: i64 = NA_RV_W*RBM_BYTES
152 let idx: *i64 = sys_mmap(ni) as *i64
153 let a: *i64 = sys_mmap(nr) as *i64
154 let outb: *i64 = sys_mmap(nr) as *i64
155 let scr: *i64 = sys_mmap(ns) as *i64
156 let rv: *i64 = sys_mmap(nv) as *i64
157 let rc: i64 = rb_motion_pair(anim,w[ae+2],skel,nj,ta,tb,idx,rv,a,outb,scr,rep)
158 sys_munmap(idx as *u8,ni);sys_munmap(a as *u8,nr);sys_munmap(outb as *u8,nr)
159 sys_munmap(scr as *u8,ns);sys_munmap(rv as *u8,nv)
160 return rc
161}