code wiki / (root) / nx_body_skin_cut_consumer_t345.nx

nx_body_skin_cut_consumer_t345.nx source

↩ module page · 89 lines · 8449 B

1// Versioned attachment consumer for the existing body loft. Source positions remain in its emitted world frame. 2// This first consumer joins two declared end cuts; it does not infer anatomy or repair unrelated defects. 3import "nx_body_skin_junction_candidate_t345.nx" 4import "nx_body_rest_registration_candidate_t345.nx" 5const BJC_JOIN_WORDS:i64=19 6const BJC_JOIN_BYTES:i64=152 7struct BgCutJoin { part_a:i64, side_a:i64, station_a:i64, keep_a:i64, part_b:i64, side_b:i64, station_b:i64, keep_b:i64, radial:i64, vertices:*NxBufOwned, faces:*NxBufOwned, normals:*i64, seen_a:i64, seen_b:i64, error:i64, removed:i64, added:i64, max_bytes:i64, reserved:i64 } 8func bjc_words(p:*i64,offset:i64)->*i64{return ((p as i64)+offset*8) as *i64} 9func bjc_init(j:*BgCutJoin,rs:i64,np:i64,counts:*i64,mirrors:*i64,sub:i64)->i64{ 10 if (j as i64)==0{return 0} 11 if (j.vertices as i64)!=0||(j.faces as i64)!=0||(j.normals as i64)!=0||j.reserved!=0{return BJ_INVALID} 12 if rs<3||rs>NX_BO_I64_MAX/48||sub<1||j.max_bytes<0||np<=0||(counts as i64)<=0||(mirrors as i64)<=0{return BJ_INVALID} 13 if j.part_a<0||j.part_a>=np||j.part_b<0||j.part_b>=np||j.part_a==j.part_b{return BJ_INVALID} 14 let ca:i64=counts[j.part_a];let cb:i64=counts[j.part_b] 15 if ca<2||cb<2||ca-1>NX_BO_I64_MAX/sub||cb-1>NX_BO_I64_MAX/sub{return BJ_DOMAIN} 16 if mirrors[j.part_a]<0||mirrors[j.part_a]>1||mirrors[j.part_b]<0||mirrors[j.part_b]>1{return BJ_INVALID} 17 if j.side_a<0||j.side_a>mirrors[j.part_a]||j.side_b<0||j.side_b>mirrors[j.part_b]{return BJ_INVALID} 18 if j.keep_a!=1&&j.keep_a!=-1{return BJ_INVALID};if j.keep_b!=1&&j.keep_b!=-1{return BJ_INVALID} 19 let ma:i64=(ca-1)*sub;let mb:i64=(cb-1)*sub 20 if j.station_a<0||j.station_a>ma||j.station_b<0||j.station_b>mb{return BJ_INVALID} 21 if j.keep_a==-1&&j.station_a==0||j.keep_a==1&&j.station_a==ma{return BJ_INVALID} 22 if j.keep_b==-1&&j.station_b==0||j.keep_b==1&&j.station_b==mb{return BJ_INVALID} 23 if j.max_bytes>0&&rs>j.max_bytes/48{return NX_BO_CAPACITY} 24 j.radial=rs;j.seen_a=0;j.seen_b=0;j.removed=0;j.added=0 25 j.vertices=sys_mmap_try(NX_BO_BYTES) as *NxBufOwned;j.faces=sys_mmap_try(NX_BO_BYTES) as *NxBufOwned;j.normals=sys_mmap_try(rs*48) as *i64;j.reserved=sys_mmap_try(24) as i64 26 var rc:i64=0 27 if (j.vertices as i64)<=0||(j.faces as i64)<=0||(j.normals as i64)<=0||j.reserved<=0{rc=NX_BO_ALLOCATION}else{rc=nx_bo_append(j.vertices,j.normals as *u8,rs*48,j.max_bytes)} 28 if rc<0{let released:i64=bjc_release(j);if released<0{return released}};return rc 29} 30func bjc_slot(j:*BgCutJoin,p:i64,side:i64)->i64{if p==j.part_a&&side==j.side_a{return 0};if p==j.part_b&&side==j.side_b{return 1};return -1} 31func bjc_keep(j:*BgCutJoin,p:i64,side:i64,st:i64,cap:i64)->i64{ 32 if (j as i64)==0{return 1};let slot:i64=bjc_slot(j,p,side);if slot<0{return 1} 33 var cut:i64=j.station_a;var dir:i64=j.keep_a;if slot==1{cut=j.station_b;dir=j.keep_b} 34 if cap==0{if dir==-1&&st>cut{return 0};if dir==1&&st<=cut{return 0};return 1} 35 if dir==-1{if cap==2||st>cut{return 0}}else{if cap==1||st<cut{return 0}};return 1 36} 37func bjc_ring(j:*BgCutJoin,p:i64,side:i64,st:i64,x:*i64,y:*i64,z:*i64,nx:*i64,ny:*i64,nz:*i64)->i64{ 38 if (j as i64)==0{return 0};let slot:i64=bjc_slot(j,p,side);if slot<0{return 0};var cut:i64=j.station_a;if slot==1{cut=j.station_b};if st!=cut{return 0} 39 let v:*i64=j.vertices.buf as *i64;var i:i64=0;while i<j.radial{let o:i64=(slot*j.radial+i)*3;v[o]=x[i];v[o+1]=y[i];v[o+2]=z[i];j.normals[o]=nx[i];j.normals[o+1]=ny[i];j.normals[o+2]=nz[i];var k:i64=0;while k<i{let q:i64=(slot*j.radial+k)*3;if v[q]==x[i]&&v[q+1]==y[i]&&v[q+2]==z[i]{return BJ_DEGENERATE};k=k+1};i=i+1} 40 if slot==0{j.seen_a=j.seen_a+1}else{j.seen_b=j.seen_b+1};return 0 41} 42// Only actual retained generator faces may witness a port boundary. Third vertices retain their actual coordinates. 43func bjc_face(j:*BgCutJoin,p:i64,side:i64,t:*i64)->i64{ 44 if (j as i64)==0{return 0};let slot:i64=bjc_slot(j,p,side);if slot<0{return 0};if slot==0&&j.seen_a!=1{return 0};if slot==1&&j.seen_b!=1{return 0} 45 let ids:*i64=j.reserved as *i64;var matched:i64=0;var k:i64=0 46 while k<3{ids[k]=-1;var i:i64=0;let v:*i64=j.vertices.buf as *i64;while i<j.radial{let ix:i64=slot*j.radial+i;if v[ix*3]==t[k*3]&&v[ix*3+1]==t[k*3+1]&&v[ix*3+2]==t[k*3+2]{ids[k]=ix;matched=matched+1};i=i+1};k=k+1} 47 var rc:i64=0;if matched>=2{k=0;while k<3&&rc==0{if ids[k]<0{ids[k]=j.vertices.len/24;rc=nx_bo_append(j.vertices,bjc_words(t,k*3) as *u8,24,j.max_bytes)};k=k+1};if rc==0{rc=nx_bo_append(j.faces,ids as *u8,24,j.max_bytes)}} 48 return rc 49} 50func bjc_finish(j:*BgCutJoin,tri:*i64,cr:*i64,cg:*i64,cb:*i64,nt:i64,cap:i64,r:i64,g:i64,b:i64)->i64{ 51 if (j as i64)==0{return nt};if j.seen_a!=1||j.seen_b!=1{return BJ_BOUNDARY} 52 if j.radial<3||j.radial>(NX_BO_I64_MAX-88)/16||nt<0||cap<0||cap>NX_BO_I64_MAX/168||nt>cap||j.radial>(cap-nt)/2{return NX_BO_CAPACITY} 53 let scratch_bytes:i64=j.radial*16+88;let scratch:*u8=sys_mmap_try(scratch_bytes);if (scratch as i64)<=0{return NX_BO_ALLOCATION} 54 let pp:*i64=scratch as *i64;let a:*BgSkinPort=((scratch as i64)+j.radial*16) as *BgSkinPort;let z:*BgSkinPort=((scratch as i64)+j.radial*16+32) as *BgSkinPort;let out:*NxBufOwned=((scratch as i64)+j.radial*16+64) as *NxBufOwned 55 let f:*i64=j.faces.buf as *i64;var slot:i64=0;while slot<2{var dir:i64=1;let base:i64=slot*j.radial;if bj_edge_owner(f,j.faces.len/24,base,base+1)<0{dir=-1};var i:i64=0;while i<j.radial{var at:i64=i;if dir<0{at=(j.radial-i)%j.radial};pp[base+i]=base+at;i=i+1};slot=slot+1} 56 a.indices=pp;a.count=j.radial;a.region=j.part_a;a.frame=0;z.indices=bjc_words(pp,j.radial);z.count=j.radial;z.region=j.part_b;z.frame=0 57 var rc:i64=bj_bridge(j.vertices.buf as *i64,j.vertices.len/24,f,j.faces.len/24,a,z,j.max_bytes,out) 58 if rc==0{let ids:*i64=out.buf as *i64;let v:*i64=j.vertices.buf as *i64;var t:i64=0;while t<out.len/24{var k:i64=0;while k<3{let ix:i64=ids[t*3+k];var c:i64=0;while c<3{tri[(nt+t)*21+k*3+c]=v[ix*3+c];tri[(nt+t)*21+9+k*3+c]=j.normals[ix*3+c];c=c+1};k=k+1};cr[nt+t]=r;cg[nt+t]=g;cb[nt+t]=b;t=t+1};j.added=out.len/24;rc=nt+j.added} 59 let released:i64=nx_bo_release(out);if released<0{return released};let freed:i64=sys_munmap_direct(scratch,scratch_bytes);if freed<0{return NX_BO_RELEASE};return rc 60} 61func bjc_release(j:*BgCutJoin)->i64{ 62 if (j as i64)==0{return 0};var rc:i64=0 63 if (j.vertices as i64)>0{rc=nx_bo_release(j.vertices);if rc<0{return rc};rc=sys_munmap_direct(j.vertices as *u8,NX_BO_BYTES);if rc<0{return NX_BO_RELEASE}};j.vertices=0 as *NxBufOwned 64 if (j.faces as i64)>0{rc=nx_bo_release(j.faces);if rc<0{return rc};rc=sys_munmap_direct(j.faces as *u8,NX_BO_BYTES);if rc<0{return NX_BO_RELEASE}};j.faces=0 as *NxBufOwned 65 if (j.normals as i64)>0{rc=sys_munmap_direct(j.normals as *u8,j.radial*48);if rc<0{return NX_BO_RELEASE}};j.normals=0 as *i64 66 if j.reserved>0{rc=sys_munmap_direct(j.reserved as *u8,24);if rc<0{return NX_BO_RELEASE}};j.reserved=0;return 0 67} 68 69const BJC_RECIPE_VERSION:i64=1 70const BJC_RECIPE_TOKENS:i64=10 71const BJC_RECIPE_CAP:i64=211 72const BJC_ERROR_WORDS:i64=5 73// Error: code, token index (zero based), byte offset, observed version, input bytes. 74// Commit recipe fields only after all ten tokens are parsed; previous recipe remains intact on refusal. 75func bjc_recipe_parse(data:*u8,n:i64,j:*BgCutJoin,error:*i64)->i64{ 76 if (error as i64)<=0{return BR_INVALID};var k:i64=0;while k<BJC_ERROR_WORDS{error[k]=0;k=k+1};error[3]=-1;error[4]=n 77 if (data as i64)<=0||(j as i64)<=0||n<=0||n>BJC_RECIPE_CAP{error[0]=BR_SCHEMA;return BR_SCHEMA} 78 let bytes:i64=BJC_JOIN_BYTES+16;let arena:*u8=sys_mmap_try(bytes);if (arena as i64)<=0{error[0]=NX_BO_ALLOCATION;return NX_BO_ALLOCATION} 79 let temp:*BgCutJoin=arena as *BgCutJoin;let row:*i64=arena as *i64;let cursor:*i64=((arena as i64)+BJC_JOIN_BYTES) as *i64 80 var end:i64=n;if data[end-1]==10 as u8{end=end-1} 81 var rc:i64=br_integer(data,end,cursor,bjc_words(cursor,1));error[3]=cursor[1] 82 if rc==0&&cursor[1]!=BJC_RECIPE_VERSION{rc=BR_SCHEMA} 83 var i:i64=0;while i<8&&rc==0{error[1]=i+1;rc=br_integer(data,end,cursor,bjc_words(row,i));i=i+1} 84 if rc==0{error[1]=9;rc=br_integer(data,end,cursor,bjc_words(cursor,1));temp.max_bytes=cursor[1]} 85 while cursor[0]<end&&br_space(data[cursor[0]] as i64)==1{cursor[0]=cursor[0]+1} 86 if rc==0&&cursor[0]!=end{error[1]=10;rc=BR_SCHEMA};error[2]=cursor[0];error[0]=rc 87 if rc==0{let dst:*i64=j as *i64;i=0;while i<8{dst[i]=row[i];i=i+1};j.max_bytes=temp.max_bytes} 88 let freed:i64=sys_munmap_direct(arena,bytes);if freed<0{error[0]=NX_BO_RELEASE;return NX_BO_RELEASE};return rc 89}