code wiki / (root) / nx_uv_adaptive_prepare_candidate_t280.nx

nx_uv_adaptive_prepare_candidate_t280.nx source

↩ module page · 114 lines · 11378 B

1// nx_uv_adaptive_prepare_candidate_t280.nx -- Analyzes UV charts to count zero, positive, and negative areas in seam calculations. 2import "nx_uv_harmonic_candidate_t280.nx" 3import "nx_gate_verdict.nx" 4import "nx_uv_dual_partition_candidate_t280.nx" 5func ucp_budget(s:*u8)->i64{ 6 var i:i64=0;var v:i64=0 7 while s[i]!=(0 as u8){let c:i64=(s[i] as i64)-48;if c<0{return 0-1};if c>9{return 0-1};if v>(NCP_MAX-c)/10{return 0-1};v=v*10+c;i=i+1} 8 if v<1{return 0-1};return v 9} 10 11func ug_time(clock:*i64)->i64{sys_clock_gettime_mono(clock);return clock[0]*1000000+clock[1]/1000} 12func ug_float_areas(s:*UvGramSolve)->i64{ 13 var t:i64=0;var zero:i64=0;var pos:i64=0;var neg:i64=0;var tiny:f64=0.0;var largest:f64=0.0 14 while t<s.nt{let a:i64=s.corners[t*3];let b:i64=s.corners[t*3+1];let c:i64=s.corners[t*3+2];let area:f64=(s.x[b]-s.x[a])*(s.x[s.n+c]-s.x[s.n+a])-(s.x[s.n+b]-s.x[s.n+a])*(s.x[c]-s.x[a]);if area==0.0{zero=zero+1};if area>0.0{pos=pos+1};if area<0.0{neg=neg+1};var mag:f64=area;if mag<0.0{mag=0.0-mag};if mag>largest{largest=mag};if mag>0.0{if tiny==0.0{tiny=mag};if mag<tiny{tiny=mag}};t=t+1} 15 gv_puts("HARMONIC rawAreas chart=");gv_num(s.c);gv_puts(" exactZero=");gv_num(zero);gv_puts(" positive=");gv_num(pos);gv_puts(" negative=");gv_num(neg);gv_puts(" minPositiveRawF64Bits=");let bits:*i64=(&tiny) as *i64;gv_num(bits[0]);gv_puts(" maxRawF64Bits=");let largebits:*i64=(&largest) as *i64;gv_num(largebits[0]);gv_puts("\n");return zero 16} 17func ug_work_areas(m:*i64,c:i64)->i64{ 18 var p:i64=m[m[UV_O_CSTART]+c];let end:i64=m[m[UV_O_CSTART]+c+1];var zero:i64=0;var neg:i64=0;var pos:i64=0;var minArea:i64=0;var maxArea:i64=0 19 while p<end{let t:i64=m[m[UV_O_CORDER]+p];let a:i64=uv_corner_class(m,t,0);let b:i64=uv_corner_class(m,t,1);let cc:i64=uv_corner_class(m,t,2);let u:i64=m[UV_O_WU];let v:i64=m[UV_O_WV];let area:i64=(m[u+b]-m[u+a])*(m[v+cc]-m[v+a])-(m[v+b]-m[v+a])*(m[u+cc]-m[u+a]);if area==0{zero=zero+1};if area>0{pos=pos+1};if area<0{neg=neg+1};var magnitude:i64=area;if magnitude<0{magnitude=0-magnitude};if magnitude>0{if minArea==0{minArea=magnitude};if magnitude<minArea{minArea=magnitude}};if magnitude>maxArea{maxArea=magnitude};p=p+1} 20 gv_puts("HARMONIC workAreas chart=");gv_num(c);gv_puts(" zero=");gv_num(zero);gv_puts(" positive=");gv_num(pos);gv_puts(" negative=");gv_num(neg);gv_puts(" minPositiveAreaWork2=");gv_num(minArea);gv_puts(" maxAreaWork2=");gv_num(maxArea);gv_puts("\n");return zero 21} 22func ua_clone_seams(src:*u8,bytes:i64,m:*i64)->*i64{ 23 let next:*i64=ncp_model_nxa(src,bytes);if next==(0 as *i64){return next};var i:i64=0 24 while i<m[UV_H_SCAP]{let o:i64=m[UV_O_STAB]+i*UV_SREC;if m[o+UV_SM_USED]!=0{if uv_seam_set(next,m[o+UV_SM_LO],m[o+UV_SM_HI])!=UV_OK{ncp_model_free(next);return 0 as *i64}};i=i+1};return next 25} 26func ua_worst(m:*i64)->i64{ 27 var c:i64=0;var worst:i64=0-1;var count:i64=0 28 while c<uv_chart_count(m){var p:i64=m[m[UV_O_CSTART]+c];let end:i64=m[m[UV_O_CSTART]+c+1];var zero:i64=0;var pos:i64=0;var neg:i64=0;var minArea:i64=0;var maxArea:i64=0 29 while p<end{let t:i64=m[m[UV_O_CORDER]+p];let ax:i64=uv_corner_u(m,t,0);let ay:i64=uv_corner_v(m,t,0);let bx:i64=uv_corner_u(m,t,1);let by:i64=uv_corner_v(m,t,1);let cx:i64=uv_corner_u(m,t,2);let cy:i64=uv_corner_v(m,t,2);let area:i64=(bx-ax)*(cy-ay)-(by-ay)*(cx-ax);if area==0{zero=zero+1};if area>0{pos=pos+1};if area<0{neg=neg+1};var magnitude:i64=area;if magnitude<0{magnitude=0-magnitude};if magnitude>0{if minArea==0{minArea=magnitude};if magnitude<minArea{minArea=magnitude}};if magnitude>maxArea{maxArea=magnitude};p=p+1} 30 var flips:i64=neg;if pos<neg{flips=pos};let bad:i64=zero+flips 31 gv_puts("ADAPT chart=");gv_num(c);gv_puts(" faces=");gv_num(end-m[m[UV_O_CSTART]+c]);gv_puts(" zero=");gv_num(zero);gv_puts(" minoritySign=");gv_num(flips);gv_puts(" minPositiveAreaQ32=");gv_num(minArea);gv_puts(" maxAreaQ32=");gv_num(maxArea);gv_puts(" angleMeanPermil=");gv_num(uv_chart_angle_mean(m,c));gv_puts(" angleMaxPermil=");gv_num(uv_chart_angle_max(m,c));gv_puts(" areaDistMeanPermil=");gv_num(uv_chart_area_mean(m,c));gv_puts(" areaDistMaxPermil=");gv_num(uv_chart_area_max(m,c));gv_puts("\n") 32 if bad>count{count=bad;worst=c};c=c+1};return worst 33} 34// Reuse only complete unchanged source-face sets with identical cut-corner 35// equivalence. Packing is recomputed; these are solver work coordinates. 36// Existing uvi_atlas quantizes WU/WV in place. Preserve solver-domain 37// coordinates explicitly so later reuse cannot apply quantization twice. 38func ua_measure_preserving_work(m:*i64)->i64{ 39 let n:i64=m[UV_H_NUV];let held:*i64=sys_mmap_try(n*2*UV_I64) as *i64 40 if (held as i64)<=0{return UV_E_ARGS} 41 var i:i64=0;while i<n{held[i]=m[m[UV_O_WU]+i];held[n+i]=m[m[UV_O_WV]+i];i=i+1} 42 var rc:i64=uvi_atlas(m) 43 if rc==UV_OK{m[UV_H_STAGE]=UV_ST_SOLVED;m[UV_H_ERR]=UV_OK;rc=uv_distortion(m);if rc==UV_OK{rc=uv_overlap_check(m)}} 44 i=0;while i<n{m[m[UV_O_WU]+i]=held[i];m[m[UV_O_WV]+i]=held[n+i];i=i+1} 45 sys_munmap_direct(held as *u8,n*2*UV_I64);return rc 46} 47func ua_reuse(old:*i64,next:*i64,changed:i64)->*i64{ 48 let nc:i64=uv_chart_count(next);let nuv:i64=next[UV_H_NUV] 49 let ready:*i64=sys_mmap_try(nc*UV_I64) as *i64 50 let map:*i64=sys_mmap_try((nuv+old[UV_H_NUV])*UV_I64) as *i64 51 if (ready as i64)<=0{if (map as i64)>0{sys_munmap_direct(map as *u8,(nuv+old[UV_H_NUV])*UV_I64)};return 0 as *i64} 52 if (map as i64)<=0{sys_munmap_direct(ready as *u8,nc*UV_I64);return 0 as *i64} 53 if uv_stage(old)<UV_ST_SOLVED{sys_munmap_direct(map as *u8,(nuv+old[UV_H_NUV])*UV_I64);return ready} 54 if old[UV_H_NV]!=next[UV_H_NV]{sys_munmap_direct(map as *u8,(nuv+old[UV_H_NUV])*UV_I64);return ready} 55 if old[UV_H_NT]!=next[UV_H_NT]{sys_munmap_direct(map as *u8,(nuv+old[UV_H_NUV])*UV_I64);return ready} 56 let reverse:*i64=((map as i64)+nuv*UV_I64) as *i64 57 var c:i64=0 58 while c<nc{ 59 let begin:i64=next[next[UV_O_CSTART]+c];let end:i64=next[next[UV_O_CSTART]+c+1] 60 let t0:i64=next[next[UV_O_CORDER]+begin];let oc:i64=uv_chart_of_tri(old,t0);var valid:i64=1 61 if oc==changed{valid=0};if end-begin!=uv_chart_tris(old,oc){valid=0} 62 var p:i64=begin 63 while p<end{ 64 let t:i64=next[next[UV_O_CORDER]+p];if uv_chart_of_tri(old,t)!=oc{valid=0} 65 var k:i64=0;while k<3{ 66 let sv:i64=uv_ti(next,t,k);if sv!=uv_ti(old,t,k){valid=0} 67 if uv_vx(next,sv)!=uv_vx(old,sv){valid=0};if uv_vy(next,sv)!=uv_vy(old,sv){valid=0};if uv_vz(next,sv)!=uv_vz(old,sv){valid=0} 68 let a:i64=uv_corner_class(next,t,k);let b:i64=uv_corner_class(old,t,k)+1 69 if map[a]!=0{if map[a]!=b{valid=0}}else{map[a]=b} 70 if reverse[b-1]!=0{if reverse[b-1]!=a+1{valid=0}}else{reverse[b-1]=a+1};k=k+1 71 };p=p+1 72 } 73 if valid==1{ready[c]=1;p=begin;while p<end{let t:i64=next[next[UV_O_CORDER]+p];var k:i64=0;while k<3{let a:i64=uv_corner_class(next,t,k);let b:i64=map[a]-1;next[next[UV_O_WU]+a]=old[old[UV_O_WU]+b];next[next[UV_O_WV]+a]=old[old[UV_O_WV]+b];k=k+1};p=p+1}} 74 c=c+1 75 };sys_munmap_direct(map as *u8,(nuv+old[UV_H_NUV])*UV_I64);return ready 76} 77func main(argc:i64,argv:*i64)->i64{ 78 if argc!=7{return 2};let budget:i64=ucp_budget(argv[4] as *u8);let rounds:i64=ucp_budget(argv[5] as *u8);if budget<1{return 3};if rounds<1{return 3};let toleranceDenominator:i64=ucp_budget(argv[6] as *u8);if toleranceDenominator<=1{return 3};let tolerance:f64=1.0/__f64_from_i64(toleranceDenominator) 79 gv_puts("ADAPT policy maxChartIterations=");gv_num(budget);gv_puts(" maxRefinements=");gv_num(rounds);gv_puts(" relativeResidualToleranceDenominator=");gv_num(toleranceDenominator);gv_puts("\n") 80 let lens:*i64=sys_mmap_try(16) as *i64;let clock:*i64=sys_mmap_try(16) as *i64;let receipt:*i64=sys_mmap_try(48) as *i64 81 let src:*u8=sys_read_file(argv[1] as *u8,lens);if src==(0 as *u8){return 4};let bytes:i64=lens[0] 82 var m:*i64=ncp_model_nxa(src,bytes);if m==(0 as *i64){return 5} 83 let seams:*u8=sys_read_file(argv[2] as *u8,lens);if seams==(0 as *u8){return 6};if lens[0]%8!=0{return 6};if ncp_seams(m,seams as *i64,lens[0]/8)!=UV_OK{return 7};if uv_chart_build(m)!=UV_OK{return 8} 84 var cached:*i64=sys_mmap_try(uv_chart_count(m)*UV_I64) as *i64;if (cached as i64)<=0{return 17} 85 var round:i64=0;var all:i64=UV_E_NOTRUN;var elapsedAll:i64=0;var totalMatvec:i64=0 86 while round<=rounds{ 87 let q:*i64=uds_prepare(m);if q==(0 as *i64){return 14};var c:i64=0;all=UV_OK 88 let started:i64=ug_time(clock) 89 while c<uv_chart_count(m){ 90 if cached[c]==1{gv_puts("ADAPT reused chart=");gv_num(c);gv_puts(" faces=");gv_num(uv_chart_tris(m,c));gv_puts("\n");c=c+1;continue} 91 let s:*UvGramSolve=ulh_begin(m,q,c,tolerance);if s==(0 as *UvGramSolve){return 9};var rc:i64=s.result;if rc==UV_E_NOTRUN{rc=uls_step(s,budget)};totalMatvec=totalMatvec+s.matvecs 92 if rc==UV_OK{ug_float_areas(s);rc=uls_export(s);ug_work_areas(m,c)};if rc!=UV_OK{all=rc};uls_free(s);c=c+1 93 };ncp_model_free(q);elapsedAll=elapsedAll+ug_time(clock)-started 94 if all!=UV_OK{gv_puts("ADAPT solver unresolved result=");gv_num(all);gv_puts("\n");break} 95 all=ua_measure_preserving_work(m);if uv_stage(m)<UV_ST_SOLVED{break} 96 gv_puts("ADAPT round=");gv_num(round);gv_puts(" charts=");gv_num(uv_chart_count(m));gv_puts(" result=");gv_num(all);gv_puts(" zeros=");gv_num(uv_uvdegen(m));gv_puts(" flips=");gv_num(uv_flipped(m));gv_puts(" accumulatedSolveUs=");gv_num(elapsedAll);gv_puts(" matvecs=");gv_num(totalMatvec);gv_puts("\n") 97 let worst:i64=ua_worst(m) 98 if all==UV_OK{break};if worst<0{break};if round==rounds{gv_puts("ADAPT refinement budget exhausted\n");break} 99 let next:*i64=ua_clone_seams(src,bytes,m);if next==(0 as *i64){return 15} 100 let cut:*i64=uvd_partition(m,worst,next,receipt);if cut==(0 as *i64){ncp_model_free(next);gv_puts("ADAPT partition refused\n");break} 101 let oldCharts:i64=uv_chart_count(m);let build:i64=uv_chart_build(next);if build!=UV_OK{sys_munmap_direct(cut as *u8,receipt[0]*8);ncp_model_free(next);return 16} 102 if uv_chart_count(next)!=oldCharts+1{sys_munmap_direct(cut as *u8,receipt[0]*8);ncp_model_free(next);gv_puts("ADAPT extra chart fragments refused\n");break} 103 let topology:*i64=uds_prepare(next);if topology==(0 as *i64){sys_munmap_direct(cut as *u8,receipt[0]*8);ncp_model_free(next);gv_puts("ADAPT nondisk split refused\n");break};ncp_model_free(topology) 104 gv_puts("ADAPT split chart=");gv_num(worst);gv_puts(" edges=");gv_num(cut[0]);gv_puts(" facesA=");gv_num(receipt[3]);gv_puts(" facesB=");gv_num(receipt[4]);gv_puts("\n") 105 let reuse:*i64=ua_reuse(m,next,worst);if reuse==(0 as *i64){sys_munmap_direct(cut as *u8,receipt[0]*8);ncp_model_free(next);return 17} 106 sys_munmap_direct(cached as *u8,uv_chart_count(m)*UV_I64);cached=reuse 107 sys_munmap_direct(cut as *u8,receipt[0]*8);ncp_model_free(m);m=next;round=round+1 108 } 109 let packet:*u8=ncp_emit(m,src,bytes,all,lens);if packet==(0 as *u8){return 10} 110 if uv_stage(m)>=UV_ST_SOLVED{let rows:*i64=packet as *i64;var t:i64=0;while t<m[UV_H_NT]{var k:i64=0;while k<3{let o:i64=NCP_HEADER+(t*3+k)*NCP_ROW;rows[o+5]=uv_corner_u(m,t,k);rows[o+6]=uv_corner_v(m,t,k);k=k+1};t=t+1}} 111 let fd:i64=sys_openat_exclusive(argv[3] as *u8,MODE_0600);if fd<0{return 11};var written:i64=0;while written<lens[0]{let k:i64=sys_write(fd,((packet as i64)+written) as *u8,lens[0]-written);if k<=0{return 12};written=written+k};sys_close(fd) 112 sys_munmap_direct(packet,lens[0]);sys_munmap_direct(cached as *u8,uv_chart_count(m)*UV_I64);ncp_model_free(m);sys_munmap_direct(lens as *u8,16);sys_munmap_direct(clock as *u8,16);sys_munmap_direct(receipt as *u8,48) 113 if all!=UV_OK{return 13};return 0 114}