code wiki / (root) / nx_nxa_rig_motion_stream.nx

nx_nxa_rig_motion_stream.nx source

↩ module page · 127 lines · 4566 B

1// nx_nxa_rig_motion_stream.nx -- Computes motion transformations for animated entities using basis matrices and affine composition. 2import "nx_nxa_rig_motion_20260909.nx" 3 4import "nx_nxa_anim_lib.nx" 5 6// Continuous frame evaluation uses the same admitted map and source ANIM as the native gate. 7// Workspace and rows belong to one caller; no global palette, entity count or joint ceiling. 8func nrm_frame_words(ns:i64,nt:i64)->i64 { 9 if ns<1||nt<1 {return 0} 10 let max:i64=9223372036854775807/8 11 if nt>(max-64)/10 {return 0} 12 let rest:i64=max-64-nt*10 13 if ns>rest/7 {return 0} 14 return ns*7+nt*10+64 15} 16func nrm_basis(v:*i64,out:*i64,sax:*i64,ssg:*i64,tax:*i64,tsg:*i64)->i64 { 17 var c:i64=0 18 while c<3 {out[tax[c]]=v[sax[c]]*ssg[c]*tsg[c];c=c+1} 19 return 0 20} 21func nrm_basis_det(sax:*i64,ssg:*i64,tax:*i64,tsg:*i64,m:*i64)->i64 { 22 var i:i64=0 23 while i<9 {m[i]=0;i=i+1} 24 i=0 25 while i<3 {m[tax[i]*3+sax[i]]=ssg[i]*tsg[i];i=i+1} 26 return m[0]*(m[4]*m[8]-m[5]*m[7])-m[1]*(m[3]*m[8]-m[5]*m[6])+m[2]*(m[3]*m[7]-m[4]*m[6]) 27} 28// External initialization must admit the ANIM index, signed-permutation frame and disjoint spans. 29// Time is source clip milliseconds; caller retains phase and actor/root policy. 30struct NrmFrameInput { 31 anim: *i64 32 tidx: *i64 33 order: *i64 34 ns: i64 35 nt: i64 36 sax: *i64 37 ssg: *i64 38 tax: *i64 39 tsg: *i64 40 map: *i64 41 tpar: *i64 42 tbind: *i64 43 bdst: *i64 44 bound: i64 45 sse: i64 46 tse: i64 47} 48func nrm_frame(frame:*NrmFrameInput,t:i64,rows:*i64,row_words:i64,work:*i64,work_words:i64)->i64 { 49 let anim:*i64=frame.anim 50 let tidx:*i64=frame.tidx 51 let order:*i64=frame.order 52 let ns:i64=frame.ns 53 let nt:i64=frame.nt 54 let sax:*i64=frame.sax 55 let ssg:*i64=frame.ssg 56 let tax:*i64=frame.tax 57 let tsg:*i64=frame.tsg 58 let map:*i64=frame.map 59 let tpar:*i64=frame.tpar 60 let tbind:*i64=frame.tbind 61 let bdst:*i64=frame.bdst 62 let bound:i64=frame.bound 63 let sse:i64=frame.sse 64 let tse:i64=frame.tse 65 let need:i64=nrm_frame_words(ns,nt) 66 if need==0||work_words<need {return 0-10} 67 if row_words/8<nt {return 0-11} 68 let q:*i64=work 69 let d:*i64=((q as i64)+ns*32) as *i64 70 let W:*i64=((d as i64)+ns*24) as *i64 71 let P:*i64=((W as i64)+nt*32) as *i64 72 let dt:*i64=((P as i64)+nt*24) as *i64 73 let scratch:*i64=((dt as i64)+nt*24) as *i64 74 let tmp:*i64=((scratch as i64)+64) as *i64 75 let matrix:*i64=((scratch as i64)+128) as *i64 76 let det:i64=nrm_basis_det(sax,ssg,tax,tsg,matrix) 77 var j:i64=0 78 while j<ns { 79 let qp:*i64=((q as i64)+j*32) as *i64 80 let dp:*i64=((d as i64)+j*24) as *i64 81 qp[0]=0;qp[1]=0;qp[2]=0;qp[3]=NRM_Q12 82 dp[0]=0;dp[1]=0;dp[2]=0 83 if tidx[j*2]>=0 { 84 if order[j]==1 {na_eval_track_ordered(anim,tidx[j*2],tidx[j*2+1],t,qp,dp,scratch)} 85 else {na_eval_track(anim,tidx[j*2],tidx[j*2+1],t,qp,dp,scratch)} 86 } 87 nrm_basis(qp,tmp,sax,ssg,tax,tsg) 88 qp[0]=tmp[0]*det;qp[1]=tmp[1]*det;qp[2]=tmp[2]*det 89 nrm_basis(dp,tmp,sax,ssg,tax,tsg) 90 dp[0]=tmp[0];dp[1]=tmp[1];dp[2]=tmp[2] 91 j=j+1 92 } 93 let rc:i64=nrm_compose(ns,nt,q,d,map,tpar,tbind,bdst,bound,sse,tse,W,P,dt,scratch) 94 if rc!=0 {return rc} 95 return nrm_affine_rows(nt,tbind,W,dt,rows,scratch) 96} 97 98func nrm_affine_rows(nj:i64,bind:*i64,q:*i64,dt:*i64,out:*i64,scr:*i64)->i64 { 99 // Bound both quaternion products and the three-term affine dual sum in i64. 100 let coordinate_limit:i64=9223372036854775807/(64*NRM_Q12) 101 var lane:i64=0 102 while lane<nj*4 {if q[lane]<0-NRM_Q12||q[lane]>NRM_Q12 {return 0-1}lane=lane+1} 103 lane=0 104 while lane<nj*3 { 105 if bind[lane]<0-coordinate_limit||bind[lane]>coordinate_limit {return 0-1} 106 if dt[lane]<0-coordinate_limit||dt[lane]>coordinate_limit {return 0-1} 107 lane=lane+1 108 } 109 let rot:*i64=scr 110 let work:*i64=((scr as i64)+32) as *i64 111 var j:i64=0 112 while j<nj { 113 let r:i64=j*4;let d:i64=nj*4+r 114 let qp:*i64=((q as i64)+r*8) as *i64 115 nf_qrotv(qp,bind[j*3],bind[j*3+1],bind[j*3+2],rot,work) 116 let tx:i64=bind[j*3]+dt[j*3]-rot[0] 117 let ty:i64=bind[j*3+1]+dt[j*3+1]-rot[1] 118 let tz:i64=bind[j*3+2]+dt[j*3+2]-rot[2] 119 out[r]=q[r];out[r+1]=q[r+1];out[r+2]=q[r+2];out[r+3]=q[r+3] 120 out[d]=(tx*q[r+3]+ty*q[r+2]-tz*q[r+1])/2 121 out[d+1]=(0-tx*q[r+2]+ty*q[r+3]+tz*q[r])/2 122 out[d+2]=(tx*q[r+1]-ty*q[r]+tz*q[r+3])/2 123 out[d+3]=(0-tx*q[r]-ty*q[r+1]-tz*q[r+2])/2 124 j=j+1 125 } 126 return 0 127}