nx_nxa_corner_prepare_candidate_t280.nx source
↩ module page · 114 lines · 6377 B
1// nx_nxa_corner_prepare_candidate_t280.nx -- Prepares candidate data for corner processing by extracting vertex and triangle information from an NXA file.
2import "nx_uvunwrap_lib.nx"
3import "nx_nxa.nx"
4import "nx_sha256.nx"
5
6// NCP1 v1 is an inspection/preparation packet, not TEXC and not an anatomical chart.
7// Source bytes remain immutable; source SHA plus corner indices preserve every original attribute.
8const NCP_MAGIC:i64=0x3150434e
9const NCP_VERSION:i64=1
10const NCP_HEADER:i64=36
11const NCP_ROW:i64=8
12const NCP_HASH_WORD:i64=32
13const NCP_MAX:i64=9223372036854775807
14
15func ncp_model_new(nv:i64,nt:i64)->*i64{
16 if nv<3{return 0 as *i64};if nt<1{return 0 as *i64}
17 // The existing layout is affine in vertex, triangle and hash-table counts.
18 // Derive its coefficients through that owner, then check each extent before allocation.
19 if nt>NCP_MAX/2/MV_LOAD_NUM/UV_TRI{return 0 as *i64}
20 let h:*i64=sys_mmap_try(UV_HDR*UV_I64) as *i64;if (h as i64)<=0{return 0 as *i64}
21 let base:i64=uv_layout(h)
22 h[UV_H_NV]=1;let vc:i64=uv_layout(h)-base;h[UV_H_NV]=0
23 h[UV_H_NT]=1;let tc:i64=uv_layout(h)-base;h[UV_H_NT]=0
24 h[UV_H_ECAP]=1;h[UV_H_SCAP]=1;let ec:i64=uv_layout(h)-base
25 let cap:i64=mv_cap_for(nt*UV_TRI)
26 var words:i64=base;let maxwords:i64=NCP_MAX/UV_I64
27 if nv>(maxwords-words)/vc{sys_munmap_direct(h as *u8,UV_HDR*UV_I64);return 0 as *i64};words=words+nv*vc
28 if nt>(maxwords-words)/tc{sys_munmap_direct(h as *u8,UV_HDR*UV_I64);return 0 as *i64};words=words+nt*tc
29 if cap>(maxwords-words)/ec{sys_munmap_direct(h as *u8,UV_HDR*UV_I64);return 0 as *i64};words=words+cap*ec
30 h[UV_H_NV]=nv;h[UV_H_NT]=nt;h[UV_H_ECAP]=cap;h[UV_H_SCAP]=cap
31 if uv_layout(h)!=words{sys_munmap_direct(h as *u8,UV_HDR*UV_I64);return 0 as *i64}
32 let m:*i64=sys_mmap_try(words*UV_I64) as *i64
33 if (m as i64)>0{
34 m[UV_H_NV]=nv;m[UV_H_NT]=nt;m[UV_H_ECAP]=cap;m[UV_H_SCAP]=cap
35 uv_layout(m);m[UV_H_ERR]=UV_E_NOTRUN;m[UV_H_STAGE]=UV_ST_NEW;m[UV_H_MVERR]=MV_E_NOTRUN;m[UV_H_MVCLOSED]=0-1
36 }
37 sys_munmap_direct(h as *u8,UV_HDR*UV_I64)
38 if (m as i64)<=0{return 0 as *i64};return m
39}
40func ncp_model_free(m:*i64)->i64{
41 if m==(0 as *i64){return 0};return sys_munmap_direct(m as *u8,uv_words_used(m)*UV_I64)
42}
43func ncp_model_nxa(b:*u8,n:i64)->*i64{
44 if b==(0 as *u8){return 0 as *i64}
45 let ve:i64=nxa_section_entry(b,n,nxa_tag4("VERT"));if ve<0{return 0 as *i64}
46 let te:i64=nxa_section_entry(b,n,nxa_tag4("TRIS"));if te<0{return 0 as *i64}
47 let w:*i64=b as *i64
48 if w[ve+2]<1{return 0 as *i64};if w[te+2]<1{return 0 as *i64}
49 let v:i64=w[ve+1]/8;let t:i64=w[te+1]/8
50 let nv:i64=w[v];let nt:i64=w[t]
51 if nv<3{return 0 as *i64};if nt<1{return 0 as *i64}
52 if nv>(w[ve+2]-1)/3{return 0 as *i64};if nt>(w[te+2]-1)/3{return 0 as *i64}
53 let m:*i64=ncp_model_new(nv,nt);if m==(0 as *i64){return m}
54 var i:i64=0;while i<nv{uv_set_vert(m,i,w[v+1+i*3],w[v+2+i*3],w[v+3+i*3]);i=i+1}
55 i=0;while i<nt{
56 let a:i64=w[t+1+i*3];let bb:i64=w[t+2+i*3];let c:i64=w[t+3+i*3]
57 if a<0{ncp_model_free(m);return 0 as *i64};if bb<0{ncp_model_free(m);return 0 as *i64};if c<0{ncp_model_free(m);return 0 as *i64}
58 if a>=nv{ncp_model_free(m);return 0 as *i64};if bb>=nv{ncp_model_free(m);return 0 as *i64};if c>=nv{ncp_model_free(m);return 0 as *i64}
59 uv_set_tri(m,i,a,bb,c);i=i+1
60 };return m
61}
62// Explicit seam input: packed i64 [count, vertexA, vertexB, ...]. Unknown edges
63// are rejected before modifying the model; chart IDs never substitute for bone IDs.
64func ncp_seams(m:*i64,s:*i64,words:i64)->i64{
65 if m==(0 as *i64){return UV_E_ARGS};if s==(0 as *i64){return UV_E_ARGS}
66 if words<1{return UV_E_ARGS};let count:i64=s[0]
67 if count<0{return UV_E_ARGS};if count>(words-1)/2{return UV_E_ARGS}
68 if count*2+1!=words{return UV_E_ARGS}
69 var i:i64=0
70 while i<count{
71 let a:i64=s[1+i*2];let b:i64=s[2+i*2]
72 if a<0{return UV_E_ARGS};if b<0{return UV_E_ARGS};if a>=m[UV_H_NV]{return UV_E_ARGS};if b>=m[UV_H_NV]{return UV_E_ARGS};if a==b{return UV_E_ARGS}
73 var found:i64=0;var t:i64=0
74 while t<m[UV_H_NT]{var k:i64=0;while k<3{
75 let x:i64=uv_ti(m,t,k);let y:i64=uv_ti(m,t,(k+1)%3)
76 if x==a{if y==b{found=1}};if x==b{if y==a{found=1}};k=k+1
77 };if found==1{break};t=t+1}
78 if found==0{return UV_E_ARGS};i=i+1
79 }
80 i=0;while i<count{let rc:i64=uv_seam_set(m,s[1+i*2],s[2+i*2]);if rc!=UV_OK{return rc};i=i+1};return UV_OK
81}
82// Header words: magic,version,header,row,nv,nt,ncorn,stage,verdict,ncharts,
83// validCorners,metricsAvailable,mvVerdict,closed,angleMean,angleMax,areaMean,
84// areaMax,flipped,uvDegenerate,overlap,sourceBytes,seams,grid,
85// allocationWords,overlapScope(1=chart-box),physicalScaleKnown(0),
86// anatomicalAssignmentKnown(0),reserved*4,sourceSHA256[32 raw bytes].
87// Row: triangle,corner,sourceVertex,chart,class,uQ16,vQ16,uvValid.
88func ncp_emit(m:*i64,b:*u8,n:i64,result:i64,outbytes:*i64)->*u8{
89 if outbytes==(0 as *i64){return 0 as *u8};outbytes[0]=0
90 if m==(0 as *i64){return 0 as *u8};if b==(0 as *u8){return 0 as *u8};if n<0{return 0 as *u8}
91 let corners:i64=m[UV_H_NCORN]
92 if corners>(NCP_MAX/8-NCP_HEADER)/NCP_ROW{return 0 as *u8}
93 let words:i64=NCP_HEADER+corners*NCP_ROW
94 let p:*i64=sys_mmap_try(words*8) as *i64;if (p as i64)<=0{return 0 as *u8}
95 p[0]=NCP_MAGIC;p[1]=NCP_VERSION;p[2]=NCP_HEADER;p[3]=NCP_ROW
96 p[4]=m[UV_H_NV];p[5]=m[UV_H_NT];p[6]=corners;p[7]=uv_stage(m);p[8]=result;p[9]=uv_chart_count(m)
97 var valid:i64=0;if result==UV_OK{if uv_stage(m)>=UV_ST_SOLVED{valid=1}}
98 p[10]=corners*valid;p[11]=0;if uv_stage(m)>=UV_ST_MEASURED{p[11]=1}
99 p[12]=uv_mv_verdict(m);p[13]=uv_mv_closed(m)
100 var k:i64=14;while k<=20{p[k]=0-1;k=k+1}
101 if p[11]==1{p[14]=uv_angle_mean(m);p[15]=uv_angle_max(m);p[16]=uv_area_mean(m);p[17]=uv_area_max(m);p[18]=uv_flipped(m);p[19]=uv_uvdegen(m)}
102 if uv_stage(m)>=UV_ST_MEASURED{if result==UV_OK{p[20]=uv_overlaps(m)};if result==UV_E_OVERLAP{p[20]=uv_overlaps(m)}}
103 p[21]=n;p[22]=uv_seam_count(m);p[23]=uv_grid(m);p[24]=words;p[25]=1
104 let hr:i64=sha256_digest_checked_native(b,n,((p as i64)+NCP_HASH_WORD*8) as *u8)
105 if hr!=0{sys_munmap_direct(p as *u8,words*8);return 0 as *u8}
106 var t:i64=0;while t<m[UV_H_NT]{k=0;while k<3{
107 let o:i64=NCP_HEADER+(t*3+k)*NCP_ROW
108 p[o]=t;p[o+1]=k;p[o+2]=uv_ti(m,t,k);p[o+3]=0-1;p[o+4]=0-1;p[o+5]=0;p[o+6]=0;p[o+7]=valid
109 if uv_stage(m)>=UV_ST_CHARTS{p[o+3]=uv_chart_of_tri(m,t);p[o+4]=uv_corner_class(m,t,k)}
110 if valid==1{p[o+5]=uv_corner_u(m,t,k);p[o+6]=uv_corner_v(m,t,k)}
111 k=k+1
112 };t=t+1}
113 outbytes[0]=words*8;return p as *u8
114}