nx_nxa_affine_palette_t34.nx source
↩ module page · 36 lines · 2820 B
1// Private existing-animation consumer contract: W(t)*inverse(authored BindPose).
2import "nx_fbx_affine_t32.nx"
3import "nx_linalg_affine_t34.nx"
4const AF_Q20_TO_Q30:i64=1024
5func af_promote_q30(input:*i64,out:*i64)->i64{
6 var i:i64=0;while i<16{if input[i]<=0-LA_AFFINE_MAX/AF_Q20_TO_Q30||input[i]>=LA_AFFINE_MAX/AF_Q20_TO_Q30{return LA_AFFINE_RANGE};i=i+1}
7 i=0;while i<16{out[i]=input[i]*AF_Q20_TO_Q30;i=i+1};return 0
8}
9func af_inverse_bind(bind:*i64,out:*i64,residual_budget:i64,report:*i64)->i64{
10 if bind[3]!=0||bind[7]!=0||bind[11]!=0||bind[15]!=FBB_Q{return FBB_BAD}
11 let full:*i64=sys_mmap(128) as *i64;let linear:*i64=sys_mmap(128) as *i64;let translation:*i64=sys_mmap(128) as *i64
12 let a:*Mat=nx_mat_new(3,3);let inverse:*Mat=nx_mat_new(3,3)
13 var rc:i64=af_promote_q30(bind,full)
14 if rc==0{var r:i64=0;while r<3{var c:i64=0;while c<3{nx_mat_set(a,r,c,full[c*4+r]);c=c+1};r=r+1};rc=la_inverse3_q30(a,inverse,residual_budget,report)}
15 if rc==0{var r:i64=0;while r<3{var c:i64=0;while c<3{linear[c*4+r]=nx_mat_get(inverse,r,c);c=c+1};r=r+1};linear[15]=FQ_ONE
16 translation[0]=FQ_ONE;translation[5]=FQ_ONE;translation[10]=FQ_ONE;translation[15]=FQ_ONE;translation[12]=0-full[12];translation[13]=0-full[13];translation[14]=0-full[14]
17 rc=la_affine_compose_q30(linear,translation,out)
18 }
19 sys_munmap(full as *u8,128);sys_munmap(linear as *u8,128);sys_munmap(translation as *u8,128);sys_munmap(a.data as *u8,72);sys_munmap(a as *u8,NX_MAT_BYTES);sys_munmap(inverse.data as *u8,72);sys_munmap(inverse as *u8,NX_MAT_BYTES);return rc
20}
21func af_palette_matrix(world:*i64,inverse_bind:*i64,out:*i64)->i64{
22 let promoted:*i64=sys_mmap(128) as *i64;let delta:*i64=sys_mmap(128) as *i64
23 var rc:i64=af_promote_q30(world,promoted)
24 if rc==0{rc=la_affine_compose_q30(promoted,inverse_bind,delta)}
25 if rc==0{var i:i64=0;while i<16{out[i]=delta[i]/AF_Q20_TO_Q30;i=i+1}}
26 sys_munmap(promoted as *u8,128);sys_munmap(delta as *u8,128);return rc
27}
28// Inverse transpose of the blended vertex linear transform, not a blend of inverse transposes.
29// Caller normalizes the resulting normal; singular blends explicitly refuse.
30func af_normal_matrix(blended:*i64,out:*i64,residual_budget:i64,report:*i64)->i64{
31 let a:*Mat=nx_mat_new(3,3);let inverse:*Mat=nx_mat_new(3,3);var r:i64=0;var rc:i64=0
32 while r<3&&rc==0{var c:i64=0;while c<3&&rc==0{let value:i64=blended[c*4+r];if value<=0-LA_AFFINE_MAX/AF_Q20_TO_Q30||value>=LA_AFFINE_MAX/AF_Q20_TO_Q30{rc=LA_AFFINE_RANGE}else{nx_mat_set(a,r,c,value*AF_Q20_TO_Q30)};c=c+1};r=r+1}
33 if rc==0{rc=la_inverse3_q30(a,inverse,residual_budget,report)}
34 if rc==0{r=0;while r<3{var c:i64=0;while c<3{out[c*3+r]=nx_mat_get(inverse,c,r);c=c+1};r=r+1}}
35 sys_munmap(a.data as *u8,72);sys_munmap(a as *u8,NX_MAT_BYTES);sys_munmap(inverse.data as *u8,72);sys_munmap(inverse as *u8,NX_MAT_BYTES);return rc
36}