nx_hairdyn_pose_gate_t263.nx source
↩ module page · 51 lines · 3300 B
1// Real HSTR guide0 from SHA31778134b5167258b05b18ae9ae062c073fd03fb3f46d212e3512d28660c4fed.
2// Numerical tests use mesh units promoted to solver Q8; no world-frame claim.
3import "nx_hairdyn_pose_candidate_t263.nx"
4import "nx_hairdyn_lib.nx"
5import "nx_gate_verdict.nx"
6func hp_seat(st:*i64,rest:*i64,n:i64)->i64 {
7 var i:i64=0
8 while i<n {
9 let b:i64=i*SD_STRIDE;let r:i64=(i+1)*3
10 st[b]=rest[r];st[b+1]=rest[r+1];st[b+2]=rest[r+2]
11 st[b+3]=0;st[b+4]=0;st[b+5]=0;i=i+1
12 }
13 return 0
14}
15func main()->i64 {
16 let ctr:*i64=gv_ctr();gv_head("posed authored hair guide" as *u8)
17 let rest:*i64=sys_mmap(24*8) as *i64
18 rest[0]=5937*SD_Q8;rest[1]=5160*SD_Q8;rest[2]=159683*SD_Q8;rest[3]=4851*SD_Q8;rest[4]=5818*SD_Q8;rest[5]=157344*SD_Q8;rest[6]=4320*SD_Q8;rest[7]=6311*SD_Q8;rest[8]=153526*SD_Q8;rest[9]=4376*SD_Q8;rest[10]=6311*SD_Q8;rest[11]=148302*SD_Q8;rest[12]=3917*SD_Q8;rest[13]=6311*SD_Q8;rest[14]=141772*SD_Q8;rest[15]=4138*SD_Q8;rest[16]=6311*SD_Q8;rest[17]=133936*SD_Q8;rest[18]=4414*SD_Q8;rest[19]=6311*SD_Q8;rest[20]=124794*SD_Q8;rest[21]=3700*SD_Q8;rest[22]=6311*SD_Q8;rest[23]=114346*SD_Q8
19 let st:*i64=hd_alloc(7);let scratch:*i64=sys_mmap(24) as *i64
20 hp_seat(st,rest,7)
21 let c:i64=hd_tick_posed_collide(st,7,rest,SB_K_HAIR,SB_C_HAIR,SB_MAXD_HAIR,0 as *i64,0,scratch)
22 gv_check_eq("no collider no contacts" as *u8,c,0,ctr)
23 var err:i64=0;var i:i64=0
24 while i<7 {var a:i64=0;while a<3 {if st[i*SD_STRIDE+a]!=rest[(i+1)*3+a] {err=err+1};a=a+1};i=i+1}
25 gv_check_eq("all authored coordinates remain at rest" as *u8,err,0,ctr)
26 // Exact quarter turn around source Z and translation; deformation targets
27 // and state must transform together, rather than falling into a Y-up chain.
28 let rotated:*i64=sys_mmap(24*8) as *i64
29 i=0
30 while i<8 {rotated[i*3]=0-rest[i*3+1]+rest[0];rotated[i*3+1]=rest[i*3]+rest[1];rotated[i*3+2]=rest[i*3+2];i=i+1}
31 hp_seat(st,rotated,7)
32 hd_tick_posed_collide(st,7,rotated,SB_K_HAIR,SB_C_HAIR,SB_MAXD_HAIR,0 as *i64,0,scratch)
33 err=0;i=0
34 while i<7 {var a:i64=0;while a<3 {if st[i*SD_STRIDE+a]!=rotated[(i+1)*3+a] {err=err+1};a=a+1};i=i+1}
35 gv_check_eq("posed quarter turn preserves authored contour" as *u8,err,0,ctr)
36 // Collision against a sphere centered on the first authored node.
37 // Radius is one quarter of actual root-to-node length.
38 let dx:i64=rest[3]-rest[0];let dy:i64=rest[4]-rest[1];let dz:i64=rest[5]-rest[2]
39 let radius:i64=vm_isqrt(dx*dx+dy*dy+dz*dz)/4
40 let caps:*i64=sys_mmap(7*8) as *i64
41 caps[0]=rest[3];caps[1]=rest[4];caps[2]=rest[5];caps[3]=rest[3];caps[4]=rest[4];caps[5]=rest[5];caps[6]=radius
42 hp_seat(st,rest,7)
43 let contacts:i64=hd_tick_posed_collide(st,1,rest,SB_K_HAIR,SB_C_HAIR,SB_MAXD_HAIR,caps,1,scratch)
44 gv_check_eq("entered node reports contact" as *u8,contacts,1,ctr)
45 let px:i64=st[0]-caps[0];let py:i64=st[1]-caps[1];let pz:i64=st[2]-caps[2]
46 gv_check_eq("entered node is on fixture sphere" as *u8,vm_isqrt(px*px+py*py+pz*pz),radius,ctr)
47 hp_seat(st,rest,7)
48 hd_tick_posed_collide(st,1,rest,SB_K_HAIR,SB_C_HAIR,SB_MAXD_HAIR,caps,0,scratch)
49 gv_check_eq("no collision control remains inside fixture" as *u8,st[0],caps[0],ctr)
50 return gv_verdict("nx_hairdyn_pose_gate_t263" as *u8,ctr,"authored rest and transformed rest preserved; entered-node collision and disabled control; not runtime or ribbon-width qualification" as *u8)
51}