code wiki / (root) / nx_gltf_pose_math_t316.nx

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}