@csi-foxbyte/cityjson-to-3d-tiles
Version:
A Node.js library that converts CityJSON files into Cesium 3D Tiles—complete with automatic texture atlas packing, Basis compression, three LOD levels, and customizable threading.
2 lines • 4.09 kB
JavaScript
import {Logger}from'@gltf-transform/core';import {cloneDocument,textureCompress}from'@gltf-transform/functions';import {PromisePool}from'@supercharge/promise-pool/dist/index.js';import {readFile}from'fs/promises';import {glob}from'glob';import k,{join}from'path';import j from'sharp';import {Worker}from'worker_threads';import {getIO}from'../3dtiles/io.js';import {createDatabase}from'../database/index.js';import {compressBasisUniversal}from'../functions/compressBasisUniversal.js';import {buildGeometry}from'./buildGeometry.js';import {convertEPSGFromCityJSONToProj4}from'./helpers.js';import {WorkerPool}from'./workerPool.js';Logger.DEFAULT_INSTANCE=new Logger(Logger.Verbosity.SILENT);async function fr(J,U,N,B,C={}){const{threadCount:b=4}=C,h=await glob("**/*.json",{absolute:true,cwd:J}),D=h.map(a=>({folderPath:k.dirname(a),inputFile:a})),w=k.join(U,"tmp-db.bin"),m=await createDatabase(w,true),T=new WorkerPool(()=>new Worker(new URL("./worker.js",import.meta.url)),b),d=await getIO(),I=new Set,x=new Set;let E=null,W=0;for(const{inputFile:a,folderPath:f}of D){const O=(await readFile(a)).toString(),c=JSON.parse(O);let i=E;try{i=convertEPSGFromCityJSONToProj4(c.metadata?.referenceSystem);}catch(t){console.error(t);}if(E??(E=i),!i)throw new Error("No valid src srs found please provide one!");const F=Object.entries(c.CityObjects),R=c["geometry-templates"]?.templates??[],v=c["geometry-templates"]?.["vertices-templates"]??[],u=await m.prepare("INSERT INTO instancedData (arrayIndex, srcSRS, doc0, doc1, doc2, id, filePath) VALUES (?, ?, ?, ?, ?, ?, ?)");for(let t=0;t<R.length;t++){const o=await buildGeometry({geometry:[R[t]],vertices:v,id:t.toString(),cityJson:c,src:i,dest:"+proj=geocent +datum=WGS84 +units=m +no_defs +type=crs",folderPath:f,appearance:N,noTransform:true,dbInstance:m});if(o.length!==1)throw new Error("Unexpected!");const n=await d.readBinary(o[0].serializedDoc),e=cloneDocument(n);await e.transform(textureCompress({encoder:j,resize:[256,256]})),await compressBasisUniversal(e);const r=cloneDocument(n);await r.transform(textureCompress({encoder:j,resize:[32,32]})),await compressBasisUniversal(r),await compressBasisUniversal(n),await u.bind({1:t.toString(),2:i,3:await d.writeBinary(n),4:await d.writeBinary(e),5:await d.writeBinary(r),6:[crypto.randomUUID(),crypto.randomUUID()].join("-"),7:a}),await u.run();}await u.finalize(),await T.messageWorkers({type:"init",data:{cityJsonRaw:O,src:i,dbFile:w,filePath:a}}),await PromisePool.withConcurrency(b).for(F).process(async([t,o])=>{const n=await T.run({type:"work",data:{id:t,folderPath:f,appearance:N}});try{const e=await m.prepare("INSERT INTO data (name, childrenIds, parentIds, address, attributes, type, bbMinX, bbMinY, bbMinZ, bbMaxX, bbMaxY, bbMaxZ, doc, isInstanced, refId, transformationMatrix) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");for(const r of n){const p=r.id??crypto.randomUUID();I.has(p)&&console.error("ERROR"+p),I.add(p),await e.bind({1:p,2:o.children?.join("_#,#_"),3:o.parents?.join("_#,#_"),4:JSON.stringify(o.address??{}),5:JSON.stringify(o.attributes??{}),6:o.type,7:r.cartographicBoxMinX,8:r.cartographicBoxMinY,9:r.cartographicBoxMinZ,10:r.cartographicBoxMaxX,11:r.cartographicBoxMaxY,12:r.cartographicBoxMaxZ,13:r.serializedDoc,14:r.isInstanced?1:0,15:r.refId,16:r.transformationMatrix?.join("@")}),await e.run();const l=await m.prepare("INSERT INTO textures (img, path) VALUES (?, ?)");for(const s of r.texturePaths){if(x.has(s))continue;x.add(s);const y=await readFile(join(f,s));await l.bind({1:y,2:s}),await l.run();}for(const{buffer:s,name:y}of r.collectedTextures)await l.bind({1:s,2:y}),await l.run();}await e.finalize();}catch(e){console.error("SOMETHING WENT WRONG!!!"),console.error("SOMETHING WENT WRONG!!!"),console.error("SOMETHING WENT WRONG!!!"),console.error(e),console.error("SOMETHING WENT WRONG!!!"),console.error("SOMETHING WENT WRONG!!!"),console.error("SOMETHING WENT WRONG!!!");}}),W++,B(W/h.length);}return {dbFilePath:w}}export{fr as generateTileDatabaseFromCityJSON};//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map