nx_gltf_pose_math_t316.nx source
↩ module page · 90 lines · 3959 B
1// WASM-safe arithmetic extracted byte-for-byte from existing glTF pose and FBX bind owners.
2// Format parsing and file allocators remain in their owners; this adapter calls only caller-scratch math.
3import "nx_vecmath.nx"
4const GLD_I64_MAX:i64=9223372036854775807
5const VM_Q30:i64=1073741824
6const VM_Q30_BITS:i64=30
7func vm_q_norm_q30(a:*i64,out:*i64,tolerance:i64)->i64 {
8 if tolerance<0||tolerance>VM_Q30{return -1}
9 var sum:i64=0;var i:i64=0
10 while i<4{if a[i]<0-VM_Q30||a[i]>VM_Q30{return -1};sum=sum+a[i]*a[i];i=i+1}
11 let length:i64=vm_isqrt(sum);if length<=0||vm_abs(length-VM_Q30)>tolerance{return -2}
12 i=0;while i<4{out[i]=a[i]*VM_Q30/length;i=i+1};return 0
13}
14func vm_q_slerp_q30(a:*i64,b:*i64,t:i64,tolerance:i64,out:*i64,scratch:*i64)->i64 {
15 if t<0||t>VM_Q30{return -1}
16 let lo:*i64=scratch;let hi:*i64=(scratch as i64+32) as *i64;let mid:*i64=(scratch as i64+64) as *i64
17 let lowrc:i64=vm_q_norm_q30(a,lo,tolerance);if lowrc!=0{return lowrc}
18 let highrc:i64=vm_q_norm_q30(b,hi,tolerance);if highrc!=0{return highrc}
19 var dot:i64=0;var i:i64=0;while i<4{dot=dot+lo[i]*hi[i];i=i+1}
20 if dot<0{i=0;while i<4{hi[i]=0-hi[i];i=i+1}}
21 var left:i64=0;var right:i64=VM_Q30;var step:i64=0
22 while step<VM_Q30_BITS{
23 if t==left{i=0;while i<4{out[i]=lo[i];i=i+1};return 0}
24 if t==right{i=0;while i<4{out[i]=hi[i];i=i+1};return 0}
25 i=0;var sum:i64=0;while i<4{mid[i]=(lo[i]+hi[i])/2;sum=sum+mid[i]*mid[i];i=i+1}
26 let length:i64=vm_isqrt(sum);if length<=0{return -2}
27 i=0;while i<4{mid[i]=mid[i]*VM_Q30/length;i=i+1}
28 let center:i64=(left+right)/2
29 if t==center{i=0;while i<4{out[i]=mid[i];i=i+1};return 0}
30 if t<center{i=0;while i<4{hi[i]=mid[i];i=i+1};right=center}else{i=0;while i<4{lo[i]=mid[i];i=i+1};left=center}
31 step=step+1
32 };return -3
33}
34
35
36const FBB_WORD: i64 = 8
37const FBB_MATRIX_WORDS: i64 = 16
38const FBB_Q: i64 = 1048576
39const FBB_I64_MAX: i64 = 9223372036854775807
40const FBB_BAD: i64 = 0 - 10
41const FBB_CONFLICT: i64 = 0 - 12
42const FBB_RANGE: i64 = 0 - 13
43func fbb_compose_into(a:*i64,b:*i64,out:*i64,tmp:*i64,tmp_words:i64)->i64 {
44 if (a as i64)<=0||(b as i64)<=0||(out as i64)<=0||(tmp as i64)<=0||tmp_words<FBB_MATRIX_WORDS{return FBB_BAD}
45 let bytes:i64=FBB_MATRIX_WORDS*FBB_WORD
46 let ta:i64=tmp as i64;let aa:i64=a as i64;let ba:i64=b as i64;let oa:i64=out as i64
47 if (ta>=aa&&ta-aa<bytes)||(aa>ta&&aa-ta<bytes){return FBB_CONFLICT}
48 if (ta>=ba&&ta-ba<bytes)||(ba>ta&&ba-ta<bytes){return FBB_CONFLICT}
49 if (ta>=oa&&ta-oa<bytes)||(oa>ta&&oa-ta<bytes){return FBB_CONFLICT}
50 var rc: i64 = 0
51 var col: i64 = 0
52 while col < 4 && rc == 0 {
53 var row: i64 = 0
54 while row < 4 && rc == 0 {
55 var sum: i64 = 0
56 var k: i64 = 0
57 while k < 4 && rc == 0 {
58 let x: i64 = a[k*4+row]
59 let y: i64 = b[col*4+k]
60 if x < (0-FBB_I64_MAX) || y < (0-FBB_I64_MAX) { rc = FBB_RANGE }
61 else {
62 var ax: i64 = x
63 var ay: i64 = y
64 if ax < 0 { ax = 0-ax }
65 if ay < 0 { ay = 0-ay }
66 if ay != 0 { if ax > FBB_I64_MAX/ay { rc = FBB_RANGE } }
67 if rc == 0 {
68 let term: i64 = (x*y)/FBB_Q
69 if term > 0 && sum > FBB_I64_MAX-term { rc = FBB_RANGE }
70 else {
71 if term < 0 && sum < (0-FBB_I64_MAX)-term { rc = FBB_RANGE }
72 else { sum = sum+term }
73 }
74 }
75 }
76 k = k+1
77 }
78 tmp[col*4+row] = sum
79 row = row+1
80 }
81 col = col+1
82 }
83 if rc == 0 {
84 var j: i64 = 0
85 while j < FBB_MATRIX_WORDS { out[j] = tmp[j]; j = j+1 }
86 }
87 return rc
88}
89
90func gld_identity(out:*i64)->i64 {var i:i64=0;while i<16{out[i]=0;i=i+1};out[0]=FBB_Q;out[5]=FBB_Q;out[10]=FBB_Q;out[15]=FBB_Q;return 0}