code wiki / (root) / nx_nxa_rig_motion_context_t140.nx

nx_nxa_rig_motion_context_t140.nx source

↩ module page · 171 lines · 6284 B

1// Caller-owned staging boundary for the existing native rig-motion frame evaluator. 2// This is an in-memory ABI, not an NXA replacement or a sampled animation format. 3import "nx_nxa_rig_motion_stream_t140.nx" 4const NRC_HEADER_W:i64=8 5const NRC_INPUT_W:i64=18 6const NRC_MAGIC:i64=1314014001 7const NRC_VERSION:i64=1 8const NRC_I64_MAX:i64=9223372036854775807 9func nrc_ptr(p:*i64,w:i64)->*i64 {return ((p as i64)+w*8) as *i64} 10func nrc_input_words(ns:i64,nt:i64,aw:i64)->i64 { 11 if ns<1||nt<1||aw<1 {return 0} 12 let max:i64=NRC_I64_MAX/8 13 if aw>max-NRC_INPUT_W {return 0} 14 if nt>(max-NRC_INPUT_W-aw)/6 {return 0} 15 return NRC_INPUT_W+nt*6+aw 16} 17func nrc_words(ns:i64,nt:i64,aw:i64)->i64 { 18 let input:i64=nrc_input_words(ns,nt,aw) 19 let work:i64=nrm_frame_words(ns,nt) 20 if input==0||work==0 {return 0} 21 let max:i64=NRC_I64_MAX/8 22 if input>max-NRC_HEADER_W {return 0} 23 var used:i64=NRC_HEADER_W+input 24 if __size_of(NrmFrameInput)/8>max-used {return 0} 25 used=used+__size_of(NrmFrameInput)/8 26 if work>max-used {return 0} 27 used=used+work 28 if ns>(max-used)/3 {return 0} 29 used=used+ns*3 30 if nt>(max-used)/8 {return 0} 31 return used+nt*8 32} 33func nrc_span(p:*i64,w:i64)->i64 { 34 let b:i64=p as i64 35 if b<=0||b%8!=0||w<1 {return 0} 36 if w>(NRC_I64_MAX-b)/8 {return 0} 37 return 1 38} 39// Bound every evaluated parent position and derived dt before arithmetic, from this rig's edges. 40// A q12 quaternion with components bounded by Q rotates each component by at most 4*L1(v). 41func nrc_envelope(input:*i64)->i64 { 42 let nt:i64=input[1] 43 let par:*i64=nrc_ptr(input,NRC_INPUT_W+nt) 44 let bind:*i64=nrc_ptr(par,nt) 45 let limit:i64=NRC_I64_MAX/(64*NRM_Q12) 46 let root_motion:i64=(32768*NA_DT_MM_TO_MODEL)*input[5]/input[4] 47 var j:i64=0 48 while j<nt { 49 var own:i64=0 50 var a:i64=0 51 while a<3 {let v:i64=na_abs(bind[j*3+a]);if v>own {own=v}a=a+1} 52 let budget:i64=limit-own 53 var total:i64=0 54 var k:i64=j 55 while par[k]>=0 { 56 let p:i64=par[k] 57 var edge:i64=0 58 a=0 59 while a<3 {edge=edge+na_abs(bind[k*3+a]-bind[p*3+a]);a=a+1} 60 if edge>(budget-total)/4 {return 0-28} 61 total=total+edge*4 62 k=p 63 } 64 var root:i64=0 65 a=0 66 while a<3 {let v:i64=na_abs(bind[k*3+a]);if v>root {root=v}a=a+1} 67 if root>budget-total {return 0-28} 68 total=total+root 69 if root_motion>budget-total {return 0-28} 70 j=j+1 71 } 72 return 0 73} 74func nrc_bind(ctx:*i64,capacity:i64,input:*i64,input_words:i64)->i64 { 75 if input_words<NRC_INPUT_W||nrc_span(input,input_words)==0 {return 0-20} 76 let ns:i64=input[0];let nt:i64=input[1];let aw:i64=input[2] 77 let iw:i64=nrc_input_words(ns,nt,aw) 78 let need:i64=nrc_words(ns,nt,aw) 79 if iw==0||iw!=input_words||need==0||capacity<need||nrc_span(ctx,need)==0 {return 0-20} 80 let cb:i64=ctx as i64;let ib:i64=input as i64 81 if cb<ib+iw*8&&ib<cb+need*8 {return 0-21} 82 if input[3]<0||input[4]<1||input[5]<1 {return 0-22} 83 // Packed ANIM translations have signed-i16 millimetre lanes; size scaling must fit i64. 84 if input[5]>NRC_I64_MAX/(32768*NA_DT_MM_TO_MODEL) {return 0-22} 85 var i:i64=0 86 while i<3 { 87 let sa:i64=input[6+i];let ta:i64=input[12+i] 88 if sa<0||sa>2||ta<0||ta>2 {return 0-23} 89 if input[9+i]!=1&&input[9+i]!=(0-1) {return 0-23} 90 if input[15+i]!=1&&input[15+i]!=(0-1) {return 0-23} 91 var k:i64=0 92 while k<i {if input[6+k]==sa||input[12+k]==ta {return 0-23}k=k+1} 93 i=i+1 94 } 95 let map:*i64=nrc_ptr(input,NRC_INPUT_W) 96 let par:*i64=nrc_ptr(map,nt) 97 let bind:*i64=nrc_ptr(par,nt) 98 let dist:*i64=nrc_ptr(bind,nt*3) 99 let limit:i64=NRC_I64_MAX/(64*NRM_Q12) 100 i=0 101 while i<nt { 102 if map[i]<0||map[i]>=ns||par[i]<(0-1)||par[i]>=i||dist[i]<0 {return 0-24} 103 var a:i64=0 104 while a<3 {if bind[i*3+a]<0-limit||bind[i*3+a]>limit {return 0-24}a=a+1} 105 i=i+1 106 } 107 if nrc_envelope(input)!=0 {return 0-28} 108 // Ready contexts are immutable: same-input retry succeeds; replacement needs a new context. 109 if ctx[0]==NRC_MAGIC { 110 if ctx[1]!=NRC_VERSION||ctx[2]!=need {return 0-27} 111 let previous:*i64=nrc_ptr(ctx,NRC_HEADER_W) 112 i=0 113 while i<iw {if previous[i]!=input[i] {return 0-27}i=i+1} 114 return 0 115 } 116 ctx[0]=0;ctx[7]=0-25 117 let copy:*i64=nrc_ptr(ctx,NRC_HEADER_W) 118 i=0 119 while i<iw {copy[i]=input[i];i=i+1} 120 let anim:*i64=nrc_ptr(copy,NRC_INPUT_W+nt*6) 121 let idx:*i64=nrc_ptr(copy,iw) 122 let order:*i64=nrc_ptr(idx,ns*2) 123 let dur:i64=na_index(anim,aw,ns,idx) 124 if dur<=0 {return 0-25} 125 na_index_order(anim,idx,ns,order) 126 ctx[1]=NRC_VERSION;ctx[2]=need;ctx[3]=ns;ctx[4]=nt;ctx[5]=aw;ctx[6]=dur;ctx[7]=0 127 ctx[0]=NRC_MAGIC 128 return 0 129} 130func nrc_frame(ctx:*i64,capacity:i64,time:i64)->i64 { 131 if capacity<NRC_HEADER_W||nrc_span(ctx,capacity)==0 {return 0-26} 132 if ctx[0]!=NRC_MAGIC||ctx[1]!=NRC_VERSION {return 0-26} 133 let ns:i64=ctx[3];let nt:i64=ctx[4];let aw:i64=ctx[5] 134 let need:i64=nrc_words(ns,nt,aw) 135 if need==0||need!=ctx[2]||need>capacity||ctx[6]<1 {return 0-26} 136 let input:*i64=nrc_ptr(ctx,NRC_HEADER_W) 137 let iw:i64=nrc_input_words(ns,nt,aw) 138 let map:*i64=nrc_ptr(input,NRC_INPUT_W) 139 let par:*i64=nrc_ptr(map,nt) 140 let bind:*i64=nrc_ptr(par,nt) 141 let dist:*i64=nrc_ptr(bind,nt*3) 142 let anim:*i64=nrc_ptr(dist,nt) 143 let idx:*i64=nrc_ptr(input,iw) 144 let order:*i64=nrc_ptr(idx,ns*2) 145 let frame:*NrmFrameInput=nrc_ptr(order,ns) as *NrmFrameInput 146 let work:*i64=((frame as i64)+__size_of(NrmFrameInput)) as *i64 147 let ww:i64=nrm_frame_words(ns,nt) 148 let rows:*i64=nrc_ptr(work,ww) 149 var t:i64=time%ctx[6] 150 if t<0 {t=t+ctx[6]} 151 frame.anim=anim 152 frame.tidx=idx 153 frame.order=order 154 frame.ns=ns 155 frame.nt=nt 156 frame.sax=nrc_ptr(input,6) 157 frame.ssg=nrc_ptr(input,9) 158 frame.tax=nrc_ptr(input,12) 159 frame.tsg=nrc_ptr(input,15) 160 frame.map=map 161 frame.tpar=par 162 frame.tbind=bind 163 frame.bdst=dist 164 frame.bound=input[3] 165 frame.sse=input[4] 166 frame.tse=input[5] 167 let rc:i64=nrm_frame(frame,t,rows,nt*8,work,ww) 168 ctx[7]=rc 169 if rc!=0 {return rc} 170 return rows as i64 171}