UNPKG

@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.83 kB
import {Document}from'@gltf-transform/core';import {prune,dedup,flatten,weld,join,normals}from'@gltf-transform/functions';import {readFile}from'fs/promises';import le from'path';import ue from'proj4';import {Vector3}from'three';import {getIO}from'../3dtiles/io.js';import {mergeTextures}from'../functions/mergeTextures.js';import {padTextures}from'../functions/padTextures.js';import {buildGeometryInstance}from'./buildGeometryInstance.js';import {triangulate3DPolygon,getBBoxesFromMeshes}from'./helpers.js';async function Ve({appearance:w,cityJson:i,dest:R,folderPath:G,geometry:N,id:O,src:Y,vertices:Z,noTransform:V,dbInstance:_}){if(!N)return [];const F=await getIO(),H=ue(Y,R);let s=null;const v=[];for(let t of N){if(t.type==="GeometryInstance"){v.push(...await buildGeometryInstance(O,i,R,t,F,_));continue}switch(t.type){case "CompositeSolid":throw new Error("CompositeSolid not implemented yet!");case "MultiLineString":throw new Error("MultiLineString not implemented yet!");case "MultiPoint":throw new Error("MultiPoint not implemented yet!");case "MultiSolid":throw new Error("MultiSolid not implemented yet!");case "CompositeSurface":case "MultiSurface":case "Solid":{if(t.type==="Solid"&&t.boundaries.length>1)continue;const b=t.texture?.[w]!==void 0,C=[],P=new Set;let D=[],y=[],u=null,x=null,m=null;t.type==="Solid"&&(y=t.boundaries[0],b&&(u=t?.texture?.[w].values[0]),t.semantics&&(x=t.semantics.values[0],m=t.semantics.surfaces)),t.type==="MultiSurface"&&(y=t.boundaries,b&&(u=t.texture?.[w].values),t.semantics&&(x=t.semantics.values,m=t.semantics.surfaces)),t.type==="CompositeSurface"&&(y=t.boundaries,b&&(u=t.texture?.[w].values),t.semantics&&(x=t.semantics.values,m=t.semantics.surfaces));const r=new Document,q=r.getRoot(),k=r.createScene();q.setDefaultScene(k);const A=r.createBuffer(),I=r.createNode();k.addChild(I);const z=r.createMesh();I.setMesh(z);for(let o=0;o<y.length;o++){let c=null;const T=y[o],B=[],p=[];let U=false;if(x&&m){const e=x[o];e!=null&&m[e]&&m[e].type==="RoofSurface"&&(U=true);}for(let e=0;e<T.length;e++){const S=T[e],h=[];for(const g of S){const M=Z[g];h.push(M);}if(b&&(u[o][e]??[]).length>1){c=u[o][e][0],P.add(c);for(const g of u[o][e].slice(1)){const M=i.appearance?.["vertices-texture"][g];p.push(M[0],1-M[1]);}}B.push(h);}const E=triangulate3DPolygon(B),n=B.flat().flatMap(e=>V?e:[e[0]*i.transform.scale[0]+i.transform.translate[0],e[1]*i.transform.scale[1]+i.transform.translate[1],e[2]*i.transform.scale[2]+i.transform.translate[2]]);if(!E)continue;const a=new Array(n.length);if(V)for(let e=0;e<n.length;e+=3)s||(s=new Vector3(n[0],n[1],n[2])),a[e+0]=n[e+0]-s.x,a[e+1]=n[e+1]-s.y,a[e+2]=n[e+2]-s.z;else for(let e=0;e<n.length;e+=3){const[S,h,g]=H.forward([n[e+0],n[e+1],n[e+2]]);s||(s=new Vector3(S,h,g)),a[e+0]=S-s.x,a[e+1]=g-s.z,a[e+2]=-(h-s.y);}const W=a.length/3,l=new Float32Array(W*3),Q=U&&c===null;for(let e=0;e<W;e++)Q?(l[e*3+0]=1,l[e*3+1]=0,l[e*3+2]=0):(l[e*3+0]=1,l[e*3+1]=1,l[e*3+2]=1);const X=r.createMaterial("UNTEXTURED"),d=r.createPrimitive();d.setMaterial(X),C.push({indices:new Int16Array(E),position:new Float32Array(a),uvs:new Float32Array(p),colors:l});const $=r.createAccessor().setBuffer(A).setArray(new Float32Array(a)).setType("VEC3"),J=r.createAccessor().setBuffer(A).setArray(l).setType("VEC3");if(d.setAttribute("COLOR_0",J),p.length!==0){const e=r.createAccessor().setBuffer(A).setArray(new Float32Array(p)).setType("VEC2");d.setAttribute("TEXCOORD_0",e);}else {const e=r.createMaterial();e.setName("UNTEXTURED"),d.setMaterial(e);}const ee=r.createAccessor().setBuffer(A).setArray(new Int16Array(E)).setType("SCALAR");if(d.setAttribute("POSITION",$).setIndices(ee).setMode(4),c!==null){const e=i.appearance?.textures[c];X.setName(e.image),D.push(e.image);}if(z.addPrimitive(d),p.length!==0&&a.length/3!==p.length/2)throw new Error("!!!!")}if(!s){if(C.length!==0)throw new Error("FISHY");return []}I.setTranslation([s.x,s.z,-s.y]);let j=[];if(P.size>1){for(const o of r.getRoot().listMaterials()){if(o.getName()==="UNTEXTURED")continue;const c=await readFile(le.join(G,o.getName())),T=r.createTexture().setImage(c).setMimeType("image/png");o.setBaseColorTexture(T);}await padTextures(r,4),j=await mergeTextures(r,void 0,void 0,true,false),await r.transform(prune());}await r.transform(dedup(),flatten(),weld({}),join(),normals());const{cartographicBox:f}=getBBoxesFromMeshes(C,s),K=await F.writeBinary(r);v.push({cartographicBoxMaxX:f.max.x,cartographicBoxMaxY:f.max.y,cartographicBoxMaxZ:f.max.z,cartographicBoxMinX:f.min.x,cartographicBoxMinY:f.min.y,cartographicBoxMinZ:f.min.z,id:O,serializedDoc:K,isInstanced:false,texturePaths:D,collectedTextures:j.map(({texture:o,name:c})=>({buffer:o.getImage(),name:c}))});break}}}return v}export{Ve as buildGeometry};//# sourceMappingURL=buildGeometry.js.map //# sourceMappingURL=buildGeometry.js.map