code wiki / (root) / nx_gltf_scene.nx

nx_gltf_scene.nx source

↩ module page · 178 lines · 10158 B

1// nx_gltf_scene.nx -- ★MULTI-MESH glTF export: assemble MANY nx_trimesh meshes (one per anatomical system) into ONE .glb 2// scene -- each a named node/mesh/material -> a PEELABLE holistic being as a single standard 3D asset. Reuses the byte + 3// float encoders from nx_gltf_mesh. Flow: sc_reset() ; for each system { build mesh in trimesh ; sc_add_mesh(name) } ; 4// sc_finalize(out). Each system is tm_reset separately so its indices are already local/0-based per mesh. license_tier: ORIGINAL 5import "nx_syscalls.nx" 6import "nx_trimesh.nx" 7import "nx_gltf_mesh.nx" 8const SC_MAGIC_16777216: i64 = 16777216 9const SC_MAGIC_2000000000: i64 = 2000000000 10const SC_MAGIC_32767: i64 = 32767 11const SC_MAGIC_65535: i64 = 65535 12const SC_MAGIC_131072: i64 = 131072 13 14const SC_MAXM: i64 = 16 15static SC_BIN: i64 16static SC_BINLEN: i64 17static SC_M: i64 18static SC_POSOFF: i64 19static SC_NRMOFF: i64 20static SC_COLOFF: i64 21static SC_IDXOFF: i64 22static SC_VCNT: i64 23static SC_ICNT: i64 24static SC_NAME: i64 25static SC_MINX: i64 26static SC_MINY: i64 27static SC_MINZ: i64 28static SC_MAXX: i64 29static SC_MAXY: i64 30static SC_MAXZ: i64 31static SC_ROUGH: i64 // ★PBR per-material roughness (milli, 0..1000) 32static SC_METAL: i64 // ★PBR per-material metalness (milli, 0..1000) 33// write milli/1000 as a JSON decimal (e.g. 750 -> "0.750", 1000 -> "1.000") 34func sc_jfrac(o: *u8, at: i64, milli: i64) -> i64 { 35 var a: i64 = at 36 let whole: i64 = milli/1000 37 o[a] = (48+whole) as u8; a = a+1 38 o[a] = 46 as u8; a = a+1 // '.' 39 var f: i64 = milli%1000 40 o[a] = (48 + f/100) as u8; a = a+1 41 o[a] = (48 + (f/10)%10) as u8; a = a+1 42 o[a] = (48 + f%10) as u8; a = a+1 43 return a 44} 45 46func sc_reset() -> i64 { 47 if SC_BIN == 0 { 48 SC_BIN = sys_mmap(SC_MAGIC_16777216) // 16 MB bin 49 SC_POSOFF = sys_mmap(SC_MAXM*8) as i64; SC_NRMOFF = sys_mmap(SC_MAXM*8) as i64; SC_COLOFF = sys_mmap(SC_MAXM*8) as i64; SC_IDXOFF = sys_mmap(SC_MAXM*8) as i64 50 SC_VCNT = sys_mmap(SC_MAXM*8) as i64; SC_ICNT = sys_mmap(SC_MAXM*8) as i64; SC_NAME = sys_mmap(SC_MAXM*8) as i64 51 SC_MINX = sys_mmap(SC_MAXM*8) as i64; SC_MINY = sys_mmap(SC_MAXM*8) as i64; SC_MINZ = sys_mmap(SC_MAXM*8) as i64 52 SC_MAXX = sys_mmap(SC_MAXM*8) as i64; SC_MAXY = sys_mmap(SC_MAXM*8) as i64; SC_MAXZ = sys_mmap(SC_MAXM*8) as i64 53 SC_ROUGH = sys_mmap(SC_MAXM*8) as i64; SC_METAL = sys_mmap(SC_MAXM*8) as i64 54 } 55 SC_BINLEN = 0; SC_M = 0 56 return 0 57} 58// append the CURRENT trimesh as a named mesh in the scene 59func sc_add_mesh(name: *u8, rough: i64, metal: i64) -> i64 { 60 let NV: i64 = tm_nv(); let NT: i64 = tm_nt(); let NI: i64 = NT*3 61 if NV == 0 { return 0 } 62 if SC_M >= SC_MAXM { return 0 } 63 let bin: *u8 = SC_BIN as *u8 64 let vp: *i64 = sys_mmap(24) as *i64 65 let tt: *i64 = sys_mmap(24) as *i64 66 let posOff: i64 = SC_BINLEN 67 var minx: i64 = SC_MAGIC_2000000000; var miny: i64 = SC_MAGIC_2000000000; var minz: i64 = SC_MAGIC_2000000000 68 var maxx: i64 = 0-SC_MAGIC_2000000000; var maxy: i64 = 0-SC_MAGIC_2000000000; var maxz: i64 = 0-SC_MAGIC_2000000000 69 var a: i64 = 0; var at: i64 = posOff 70 while a < NV { 71 tm_vpos(a, vp) 72 at = gl_f32(bin, at, vp[0]); at = gl_f32(bin, at, vp[1]); at = gl_f32(bin, at, vp[2]) 73 if vp[0]<minx {minx=vp[0]} if vp[0]>maxx {maxx=vp[0]} 74 if vp[1]<miny {miny=vp[1]} if vp[1]>maxy {maxy=vp[1]} 75 if vp[2]<minz {minz=vp[2]} if vp[2]>maxz {maxz=vp[2]} 76 a = a + 1 77 } 78 let nrmOff: i64 = posOff + NV*12 79 a = 0; at = nrmOff 80 while a < NV { 81 tm_vnorm(a, vp) 82 var c: i64 = 0 83 while c < 3 { var s: i64 = vp[c]*8; if s>SC_MAGIC_32767 {s=SC_MAGIC_32767} if s<0-SC_MAGIC_32767 {s=0-SC_MAGIC_32767} at = gl_u16(bin, at, s & SC_MAGIC_65535); c = c+1 } 84 a = a + 1 85 } 86 let colOff: i64 = gl_align4(nrmOff + NV*6) 87 a = 0; at = colOff 88 while a < NV { 89 let col: i64 = tm_getvcol(a) 90 at = gl_u8(bin, at, col&255); at = gl_u8(bin, at, (col>>8)&255); at = gl_u8(bin, at, (col>>16)&255); at = gl_u8(bin, at, 255) 91 a = a + 1 92 } 93 let idxOff: i64 = colOff + NV*4 94 var tix: i64 = 0; at = idxOff 95 while tix < NT { tm_tget(tix, tt); at = gl_u32(bin, at, tt[0]); at = gl_u32(bin, at, tt[1]); at = gl_u32(bin, at, tt[2]); tix = tix+1 } 96 SC_BINLEN = gl_align4(idxOff + NI*4) 97 let m: i64 = SC_M 98 let PO: *i64=SC_POSOFF as *i64; let NO: *i64=SC_NRMOFF as *i64; let CO: *i64=SC_COLOFF as *i64; let IO: *i64=SC_IDXOFF as *i64 99 let VC: *i64=SC_VCNT as *i64; let IC: *i64=SC_ICNT as *i64; let NM: *i64=SC_NAME as *i64 100 let MNX: *i64=SC_MINX as *i64; let MNY: *i64=SC_MINY as *i64; let MNZ: *i64=SC_MINZ as *i64 101 let MXX: *i64=SC_MAXX as *i64; let MXY: *i64=SC_MAXY as *i64; let MXZ: *i64=SC_MAXZ as *i64 102 PO[m]=posOff; NO[m]=nrmOff; CO[m]=colOff; IO[m]=idxOff 103 VC[m]=NV; IC[m]=NI; NM[m]=name as i64 104 MNX[m]=minx; MNY[m]=miny; MNZ[m]=minz 105 MXX[m]=maxx; MXY[m]=maxy; MXZ[m]=maxz 106 let RG: *i64=SC_ROUGH as *i64; let MT: *i64=SC_METAL as *i64 107 RG[m]=rough; MT[m]=metal 108 SC_M = m + 1 109 return 0 110} 111func sc_mesh_count() -> i64 { return SC_M } 112 113func sc_finalize(out: *u8) -> i64 { 114 let PO: *i64=SC_POSOFF as *i64; let NO: *i64=SC_NRMOFF as *i64; let CO: *i64=SC_COLOFF as *i64; let IO: *i64=SC_IDXOFF as *i64 115 let VC: *i64=SC_VCNT as *i64; let IC: *i64=SC_ICNT as *i64; let NM: *i64=SC_NAME as *i64 116 let MNX: *i64=SC_MINX as *i64; let MNY: *i64=SC_MINY as *i64; let MNZ: *i64=SC_MINZ as *i64 117 let MXX: *i64=SC_MAXX as *i64; let MXY: *i64=SC_MAXY as *i64; let MXZ: *i64=SC_MAXZ as *i64 118 let json: *u8 = sys_mmap(SC_MAGIC_131072) 119 var j: i64 = 0 120 j = jcat(json, j, "{\"asset\":{\"version\":\"2.0\",\"generator\":\"nishi nx_gltf_scene\"},\"scene\":0,\"scenes\":[{\"nodes\":[" as *u8) 121 var m: i64 = 0 122 while m < SC_M { if m>0 { j=jcat(json,j,","as *u8) } j=jnum(json,j,m); m=m+1 } 123 j = jcat(json, j, "]}],\"nodes\":[" as *u8) 124 m = 0 125 while m < SC_M { if m>0 { j=jcat(json,j,","as *u8) } j=jcat(json,j,"{\"mesh\":"as *u8); j=jnum(json,j,m); j=jcat(json,j,",\"name\":\""as *u8); j=jcat(json,j,NM[m] as *u8); j=jcat(json,j,"\"}"as *u8); m=m+1 } 126 j = jcat(json, j, "],\"meshes\":[" as *u8) 127 m = 0 128 while m < SC_M { 129 if m>0 { j=jcat(json,j,","as *u8) } 130 j=jcat(json,j,"{\"primitives\":[{\"attributes\":{\"POSITION\":"as *u8); j=jnum(json,j,4*m); j=jcat(json,j,",\"NORMAL\":"as *u8); j=jnum(json,j,4*m+1); j=jcat(json,j,",\"COLOR_0\":"as *u8); j=jnum(json,j,4*m+2); j=jcat(json,j,"},\"indices\":"as *u8); j=jnum(json,j,4*m+3); j=jcat(json,j,",\"material\":"as *u8); j=jnum(json,j,m); j=jcat(json,j,"}]}"as *u8) 131 m=m+1 132 } 133 j = jcat(json, j, "],\"materials\":[" as *u8) 134 let RG2: *i64=SC_ROUGH as *i64; let MT2: *i64=SC_METAL as *i64 135 m = 0 136 while m < SC_M { 137 if m>0 { j=jcat(json,j,","as *u8) } 138 j=jcat(json,j,"{\"pbrMetallicRoughness\":{\"metallicFactor\":"as *u8); j=sc_jfrac(json,j,MT2[m]); j=jcat(json,j,",\"roughnessFactor\":"as *u8); j=sc_jfrac(json,j,RG2[m]); j=jcat(json,j,"},\"doubleSided\":true}"as *u8) 139 m=m+1 140 } 141 j = jcat(json, j, "],\"accessors\":[" as *u8) 142 m = 0 143 while m < SC_M { 144 if m>0 { j=jcat(json,j,","as *u8) } 145 j=jcat(json,j,"{\"bufferView\":"as *u8); j=jnum(json,j,4*m); j=jcat(json,j,",\"componentType\":5126,\"count\":"as *u8); j=jnum(json,j,VC[m]); j=jcat(json,j,",\"type\":\"VEC3\",\"min\":["as *u8); j=jnum(json,j,MNX[m]); j=jcat(json,j,","as *u8); j=jnum(json,j,MNY[m]); j=jcat(json,j,","as *u8); j=jnum(json,j,MNZ[m]); j=jcat(json,j,"],\"max\":["as *u8); j=jnum(json,j,MXX[m]); j=jcat(json,j,","as *u8); j=jnum(json,j,MXY[m]); j=jcat(json,j,","as *u8); j=jnum(json,j,MXZ[m]); j=jcat(json,j,"]},"as *u8) 146 j=jcat(json,j,"{\"bufferView\":"as *u8); j=jnum(json,j,4*m+1); j=jcat(json,j,",\"componentType\":5122,\"normalized\":true,\"count\":"as *u8); j=jnum(json,j,VC[m]); j=jcat(json,j,",\"type\":\"VEC3\"},"as *u8) 147 j=jcat(json,j,"{\"bufferView\":"as *u8); j=jnum(json,j,4*m+2); j=jcat(json,j,",\"componentType\":5121,\"normalized\":true,\"count\":"as *u8); j=jnum(json,j,VC[m]); j=jcat(json,j,",\"type\":\"VEC4\"},"as *u8) 148 j=jcat(json,j,"{\"bufferView\":"as *u8); j=jnum(json,j,4*m+3); j=jcat(json,j,",\"componentType\":5125,\"count\":"as *u8); j=jnum(json,j,IC[m]); j=jcat(json,j,",\"type\":\"SCALAR\"}"as *u8) 149 m=m+1 150 } 151 j = jcat(json, j, "],\"bufferViews\":[" as *u8) 152 m = 0 153 while m < SC_M { 154 if m>0 { j=jcat(json,j,","as *u8) } 155 j=jcat(json,j,"{\"buffer\":0,\"byteOffset\":"as *u8); j=jnum(json,j,PO[m]); j=jcat(json,j,",\"byteLength\":"as *u8); j=jnum(json,j,VC[m]*12); j=jcat(json,j,",\"target\":34962},"as *u8) 156 j=jcat(json,j,"{\"buffer\":0,\"byteOffset\":"as *u8); j=jnum(json,j,NO[m]); j=jcat(json,j,",\"byteLength\":"as *u8); j=jnum(json,j,VC[m]*6); j=jcat(json,j,",\"target\":34962},"as *u8) 157 j=jcat(json,j,"{\"buffer\":0,\"byteOffset\":"as *u8); j=jnum(json,j,CO[m]); j=jcat(json,j,",\"byteLength\":"as *u8); j=jnum(json,j,VC[m]*4); j=jcat(json,j,",\"target\":34962},"as *u8) 158 j=jcat(json,j,"{\"buffer\":0,\"byteOffset\":"as *u8); j=jnum(json,j,IO[m]); j=jcat(json,j,",\"byteLength\":"as *u8); j=jnum(json,j,IC[m]*4); j=jcat(json,j,",\"target\":34963}"as *u8) 159 m=m+1 160 } 161 j = jcat(json, j, "],\"buffers\":[{\"byteLength\":" as *u8); j = jnum(json, j, SC_BINLEN); j = jcat(json, j, "}]}" as *u8) 162 let jsonLen: i64 = j 163 let jsonPad: i64 = gl_align4(jsonLen) 164 // GLB 165 let bin: *u8 = SC_BIN as *u8 166 var o: i64 = 0 167 o = gl_str(out, o, "glTF" as *u8); o = gl_u32(out, o, 2) 168 let total: i64 = 12 + 8 + jsonPad + 8 + SC_BINLEN 169 o = gl_u32(out, o, total) 170 o = gl_u32(out, o, jsonPad); o = gl_str(out, o, "JSON" as *u8) 171 var q: i64 = 0 172 while q < jsonLen { out[o]=json[q]; o=o+1; q=q+1 } 173 while q < jsonPad { out[o]=32 as u8; o=o+1; q=q+1 } 174 o = gl_u32(out, o, SC_BINLEN); o = gl_u8(out, o, 66); o = gl_u8(out, o, 73); o = gl_u8(out, o, 78); o = gl_u8(out, o, 0) 175 q = 0 176 while q < SC_BINLEN { out[o]=bin[q]; o=o+1; q=q+1 } 177 return o 178}