code wiki / (root) / nx_texr_chart_candidate_t279.nx

nx_texr_chart_candidate_t279.nx source

↩ module page · 144 lines · 7362 B

1// nx_texr_chart_candidate_t279.nx -- Validates and initializes chart data structures for regional texture mapping in a 3D model. 2import "nx_nxa_texbake_region_lib.nx" 3 4// Candidate addition to the regional owner. Coordinates are Q16; micro UV is unwrapped 5// so interpolation precedes repeat addressing. Scale is the asset's declared model. 6struct NtrChartPoint { region:i64,joint:i64,u:i64,v:i64,micro_u:i64,micro_v:i64,micro_valid:i64 } 7struct NtrChartContext { w:*i64,x:i64,r:i64,t:i64,nv:i64,nt:i64,nj:i64,g:i64,res:i64,repeat_um:i64,sets:[4]i64 } 8const NTR_CHART_BAD:i64=0-3 9const NTR_CHART_LAYOUT:i64=0-4 10const NTR_CHART_STRADDLE:i64=0-5 11const NTR_CHART_SEAM:i64=0-6 12const NTR_CHART_OVERFLOW:i64=0-7 13const NTR_CHART_MAX:i64=9223372036854775807 14 15func ntr_chart_ranks(w:*i64,r:i64,c:*NtrChartContext,nj:i64)->i64{ 16 var total:i64=0;var region:i64=0 17 while region<NTR_REGIONS{let m:i64=c.sets[region];if m>=0{let n:i64=w[m+NTR_S_NJR];if n>nj-total{return NTR_CHART_BAD};total=total+n};region=region+1} 18 if total!=nj{return NTR_CHART_BAD} 19 let seen:*u8=sys_mmap_try(nj);if (seen as i64)<=0{return NTR_CHART_BAD} 20 var rc:i64=0;var j:i64=0 21 while j<nj{ 22 let jo:i64=r+NTR_HDR_WORDS+j*NTR_JOINT_WORDS 23 let reg:i64=w[jo];var base:i64=0;region=0 24 while region<reg{let m:i64=c.sets[region];if m>=0{base=base+w[m+NTR_S_NJR]};region=region+1} 25 let index:i64=base+w[jo+1] 26 if seen[index]!=(0 as u8){rc=NTR_CHART_BAD;break};seen[index]=1 as u8;j=j+1 27 } 28 sys_munmap_direct(seen,nj);return rc 29} 30func ntr_chart_init(b:*u8,flen:i64,c:*NtrChartContext)->i64{ 31 if c==(0 as *NtrChartContext){return NTR_CHART_BAD} 32 c.w=0 as *i64 33 if b==(0 as *u8){return NTR_CHART_BAD} 34 let r:i64=ntr_texr_find(b,flen);if r<0{return r} 35 let xe:i64=nxa_section_entry(b,flen,nxa_tag4("TEXC")) 36 let te:i64=nxa_section_entry(b,flen,nxa_tag4("TRIS")) 37 let ve:i64=nxa_section_entry(b,flen,nxa_tag4("VERT")) 38 let se:i64=nxa_section_entry(b,flen,nxa_tag4("SKEL")) 39 if xe<0{return xe};if te<0{return te};if ve<0{return ve};if se<0{return se} 40 let w:*i64=b as *i64 41 if w[xe+2]<NT_PHDR{return NTR_CHART_BAD} 42 if w[te+2]<1{return NTR_CHART_BAD};if w[ve+2]<1{return NTR_CHART_BAD};if w[se+2]<1{return NTR_CHART_BAD} 43 let x:i64=w[xe+1]/NTR_WORD;let t:i64=w[te+1]/NTR_WORD 44 let nv:i64=w[x];let nt:i64=w[t];let nj:i64=w[r+NTR_W_NJ] 45 if nv<=0{return NTR_CHART_BAD};if nt<0{return NTR_CHART_BAD};if nj<=0{return NTR_CHART_BAD} 46 if w[x+1]!=NT_STRIDE{return NTR_CHART_LAYOUT} 47 if w[x+3]!=0{return NTR_CHART_LAYOUT} 48 if nv>(w[xe+2]-NT_PHDR)/NT_STRIDE{return NTR_CHART_BAD} 49 if nt>(w[te+2]-1)/3{return NTR_CHART_BAD} 50 if w[w[ve+1]/NTR_WORD]!=nv{return NTR_CHART_BAD} 51 if w[w[se+1]/NTR_WORD]!=nj{return NTR_CHART_BAD} 52 let g:i64=w[x+2];if g<1{return NTR_CHART_BAD};if g>NTR_Q16{return NTR_CHART_BAD} 53 if nj/g>g{return NTR_CHART_BAD};if nj>g*g{return NTR_CHART_BAD} 54 let res:i64=w[r+NTR_W_RES] 55 if res>NTR_CHART_MAX/NTR_Q16/NTR_SUB{return NTR_CHART_OVERFLOW} 56 var k:i64=0;while k<NTR_REGIONS{c.sets[k]=NTR_MISS;k=k+1} 57 let ns:i64=w[r+NTR_W_NSETS] 58 k=0;while k<ns{ 59 let m:i64=r+NTR_HDR_WORDS+nj*NTR_JOINT_WORDS+k*w[r+NTR_W_SETW] 60 let region:i64=w[m+NTR_S_REGION];let gr:i64=w[m+NTR_S_GR];let tp:i64=w[m+NTR_S_TPX] 61 let count:i64=w[m+NTR_S_NJR] 62 if gr<1{return NTR_CHART_BAD};if gr>res{return NTR_CHART_BAD} 63 if tp<1{return NTR_CHART_BAD};if tp!=res/gr{return NTR_CHART_BAD} 64 if count<1{return NTR_CHART_BAD};if count>nj{return NTR_CHART_BAD} 65 if gr> NTR_CHART_MAX/gr{return NTR_CHART_OVERFLOW} 66 if count>gr*gr{return NTR_CHART_BAD} 67 c.sets[region]=m;k=k+1 68 } 69 k=0;while k<nj{ 70 let j:i64=r+NTR_HDR_WORDS+k*NTR_JOINT_WORDS 71 let region:i64=w[j];let rank:i64=w[j+1] 72 if region<0{return NTR_CHART_BAD};if region>=NTR_REGIONS{return NTR_CHART_BAD} 73 let m:i64=c.sets[region];if m<0{return NTR_CHART_LAYOUT} 74 if rank<0{return NTR_CHART_BAD};if rank>=w[m+NTR_S_NJR]{return NTR_CHART_BAD} 75 if w[j+2]<0{return NTR_CHART_BAD};if w[j+3]<0{return NTR_CHART_BAD} 76 k=k+1 77 } 78 let ranks:i64=ntr_chart_ranks(w,r,c,nj);if ranks!=0{return ranks} 79 c.x=x;c.r=r;c.t=t;c.nv=nv;c.nt=nt;c.nj=nj;c.g=g;c.res=res;c.repeat_um=w[r+NTR_W_MREP] 80 c.w=w 81 return 0 82} 83func ntr_chart_ratio_q16(n:i64,d:i64)->i64{ 84 if n<0{return NTR_CHART_BAD};if d<=0{return NTR_CHART_BAD} 85 let q:i64=n/d;let rem:i64=n%d 86 if q>NTR_CHART_MAX/NTR_Q16{return NTR_CHART_OVERFLOW} 87 if rem>NTR_CHART_MAX/NTR_Q16{return NTR_CHART_OVERFLOW} 88 let whole:i64=q*NTR_Q16;let frac:i64=rem*NTR_Q16/d 89 if frac>NTR_CHART_MAX-whole{return NTR_CHART_OVERFLOW} 90 return whole+frac 91} 92func ntr_chart_point(c:*NtrChartContext,i:i64,p:*NtrChartPoint)->i64{ 93 if p==(0 as *NtrChartPoint){return NTR_CHART_BAD} 94 p.region=NTR_MISS;p.joint=NTR_MISS;p.u=0;p.v=0;p.micro_u=0;p.micro_v=0;p.micro_valid=0 95 if c==(0 as *NtrChartContext){return NTR_CHART_BAD} 96 if c.w==(0 as *i64){return NTR_CHART_BAD} 97 if i<0{return NTR_CHART_BAD};if i>=c.nv{return NTR_CHART_BAD} 98 let w:*i64=c.w;let at:i64=c.x+NT_PHDR+i*NT_STRIDE 99 let j:i64=w[at+2];if j<0{return NTR_CHART_BAD};if j>=c.nj{return NTR_CHART_BAD} 100 let jo:i64=c.r+NTR_HDR_WORDS+j*NTR_JOINT_WORDS 101 let region:i64=w[jo];let rank:i64=w[jo+1];let m:i64=c.sets[region] 102 if w[at]<0{return NTR_CHART_LAYOUT};if w[at]>NTR_Q16{return NTR_CHART_LAYOUT} 103 if w[at+1]<0{return NTR_CHART_LAYOUT};if w[at+1]>NTR_Q16{return NTR_CHART_LAYOUT} 104 let tw:i64=NTR_Q16/c.g 105 let lu:i64=w[at]-(j%c.g)*tw;let lv:i64=w[at+1]-(j/c.g)*tw 106 if lu<0{return NTR_CHART_LAYOUT};if lu>tw{return NTR_CHART_LAYOUT} 107 if lv<0{return NTR_CHART_LAYOUT};if lv>tw{return NTR_CHART_LAYOUT} 108 let us:i64=ntr_px_sub(w[at],j,0,1,c.g,w[m+NTR_S_GR],w[m+NTR_S_TPX],rank,c.res) 109 let vs:i64=ntr_px_sub(w[at+1],j,1,1,c.g,w[m+NTR_S_GR],w[m+NTR_S_TPX],rank,c.res) 110 let u:i64=ntr_chart_ratio_q16(us,c.res*NTR_SUB);let v:i64=ntr_chart_ratio_q16(vs,c.res*NTR_SUB) 111 if u<0{return u};if v<0{return v} 112 var mu:i64=0;var mv:i64=0;var valid:i64=0 113 if w[jo+2]>0{if w[jo+3]>0{ 114 if w[jo+2]>NTR_CHART_MAX/tw{return NTR_CHART_OVERFLOW} 115 if w[jo+3]>NTR_CHART_MAX/tw{return NTR_CHART_OVERFLOW} 116 if c.repeat_um>NTR_CHART_MAX/tw{return NTR_CHART_OVERFLOW} 117 mu=ntr_chart_ratio_q16(lu*w[jo+2],tw*c.repeat_um);mv=ntr_chart_ratio_q16(lv*w[jo+3],tw*c.repeat_um) 118 if mu<0{return mu};if mv<0{return mv};valid=1 119 }} 120 p.region=region;p.joint=j;p.u=u;p.v=v;p.micro_u=mu;p.micro_v=mv;p.micro_valid=valid 121 return 0 122} 123// A triangle must remain in one chart. A cylindrical wrap seam is not a straight 124// interpolation of its endpoints; reject it until explicit seam topology exists. 125func ntr_chart_triangle(c:*NtrChartContext,t:i64,p:*NtrChartPoint)->i64{ 126 if c==(0 as *NtrChartContext){return NTR_CHART_BAD} 127 if c.w==(0 as *i64){return NTR_CHART_BAD} 128 if t<0{return NTR_CHART_BAD};if t>=c.nt{return NTR_CHART_BAD} 129 let w:*i64=c.w;let at:i64=c.t+1+t*3 130 var k:i64=0 131 while k<3{ 132 let rc:i64=ntr_chart_point(c,w[at+k],((p as i64)+k*__size_of(NtrChartPoint)) as *NtrChartPoint) 133 if rc!=0{return rc};k=k+1 134 } 135 let a:*NtrChartPoint=p 136 let b:*NtrChartPoint=((p as i64)+__size_of(NtrChartPoint)) as *NtrChartPoint 137 let d:*NtrChartPoint=((p as i64)+2*__size_of(NtrChartPoint)) as *NtrChartPoint 138 if a.joint!=b.joint{return NTR_CHART_STRADDLE};if a.joint!=d.joint{return NTR_CHART_STRADDLE} 139 let u0:i64=w[c.x+NT_PHDR+w[at]*NT_STRIDE] 140 let u1:i64=w[c.x+NT_PHDR+w[at+1]*NT_STRIDE] 141 let u2:i64=w[c.x+NT_PHDR+w[at+2]*NT_STRIDE] 142 if ntr_max(ntr_max(u0,u1),u2)-ntr_min(ntr_min(u0,u1),u2)>NTR_Q16/c.g/2{return NTR_CHART_SEAM} 143 return 0 144}