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 • 14.7 kB
import {Extension,PropertyType,GLB_BUFFER}from'@gltf-transform/core';import {StructuralMetadata,Schema,Class,ClassProperty,Enum,EnumValue,PropertyTable,PropertyTableProperty,PropertyTexture,PropertyTextureProperty,PropertyAttribute,PropertyAttributeProperty,ElementStructuralMetadata,MeshPrimitiveStructuralMetadata}from'./StructuralMetadata.js';const f="EXT_structural_metadata";function m(g,b){return g==b?null:g}const h=class h extends Extension{constructor(){super(...arguments);this.extensionName=f;this.prewriteTypes=[PropertyType.BUFFER];}createStructuralMetadata(){return new StructuralMetadata(this.document.getGraph())}createSchema(){return new Schema(this.document.getGraph())}createClass(){return new Class(this.document.getGraph())}createClassProperty(){return new ClassProperty(this.document.getGraph())}createEnum(){return new Enum(this.document.getGraph())}createEnumValue(){return new EnumValue(this.document.getGraph())}createPropertyTable(){return new PropertyTable(this.document.getGraph())}createPropertyTableProperty(){return new PropertyTableProperty(this.document.getGraph())}createPropertyTexture(){return new PropertyTexture(this.document.getGraph())}createPropertyTextureProperty(){return new PropertyTextureProperty(this.document.getGraph())}createPropertyAttribute(){return new PropertyAttribute(this.document.getGraph())}createPropertyAttributeProperty(){return new PropertyAttributeProperty(this.document.getGraph())}createElementStructuralMetadata(){return new ElementStructuralMetadata(this.document.getGraph())}createMeshPrimitiveStructuralMetadata(){return new MeshPrimitiveStructuralMetadata(this.document.getGraph())}createSchemaFrom(t){const e=this.createSchema();return this.readSchema(e,t),e}createClassFrom(t){const e=this.createClass();return this.readClass(e,t),e}createClassPropertyFrom(t){const e=this.createClassProperty();return this.readClassProperty(e,t),e}createEnumFrom(t){const e=this.createEnum();return this.readEnum(e,t),e}createEnumValueFrom(t){const e=this.createEnumValue();return this.readEnumValue(e,t),e}read(t){const e=this.createTopLevelStructuralMetadata(t);if(!e)return this;const n=t.jsonDoc.json;return (n.meshes||[]).forEach((o,a)=>{const d=t.meshes[a].listPrimitives();(o.primitives||[]).forEach((p,l)=>{const y=d[l];this.readPrimitive(e,y,p);});}),(n.nodes||[]).forEach((o,a)=>{const u=t.nodes[a];this.readNode(e,u,o);}),this}createTopLevelStructuralMetadata(t){const r=t.jsonDoc.json;if(!r.extensions||!r.extensions[f])return;const n=r.extensions[f],s=this.createStructuralMetadata();return this.readStructuralMetadata(t,s,n),this.document.getRoot().setExtension(f,s),s}readStructuralMetadata(t,e,r){if(r.schema!==void 0){const o=r.schema,a=this.createSchemaFrom(o);e.setSchema(a);}else if(r.schemaUri!==void 0){const o=r.schemaUri;e.setSchemaUri(o);}const n=r.propertyTextures||[];for(const o of n){const a=this.createPropertyTexture();this.readPropertyTexture(t,a,o),e.addPropertyTexture(a);}const s=r.propertyTables||[];for(const o of s){const a=this.createPropertyTable();this.readPropertyTable(t,a,o),e.addPropertyTable(a);}const i=r.propertyAttributes||[];for(const o of i){const a=this.createPropertyAttribute();this.readPropertyAttribute(a,o),e.addPropertyAttribute(a);}}readSchema(t,e){if(e.id!==void 0)t.setId(e.id);else throw new Error(`${f}: The schema.id is required`);e.name!==void 0&&t.setObjectName(e.name),e.description!==void 0&&t.setDescription(e.description),e.version!==void 0&&t.setVersion(e.version);const r=e.classes||{};for(const s of Object.keys(r)){const i=r[s],o=this.createClassFrom(i);t.setClass(s,o);}const n=e.enums||{};for(const s of Object.keys(n)){const i=n[s],o=this.createEnumFrom(i);t.setEnum(s,o);}}readClass(t,e){e.name!==void 0&&t.setObjectName(e.name),e.description!==void 0&&t.setDescription(e.description);const r=e.properties||{};for(const n of Object.keys(r)){const s=r[n],i=this.createClassPropertyFrom(s);t.setProperty(n,i);}}readClassProperty(t,e){if(e.name!==void 0&&t.setObjectName(e.name),e.description!==void 0&&t.setDescription(e.description),e.type!==void 0)t.setType(e.type);else throw new Error(`${f}: The classProperty.type is required`);e.componentType!==void 0&&t.setComponentType(e.componentType),e.enumType!==void 0&&t.setEnumType(e.enumType),e.array!==void 0&&t.setArray(e.array),e.count!==void 0&&t.setCount(e.count),e.normalized!==void 0&&t.setNormalized(e.normalized),e.offset!==void 0&&t.setOffset(e.offset),e.scale!==void 0&&t.setScale(e.scale),e.max!==void 0&&t.setMax(e.max),e.min!==void 0&&t.setMin(e.min),e.required!==void 0&&t.setRequired(e.required),e.noData!==void 0&&t.setNoData(e.noData),e.default!==void 0&&t.setDefault(e.default);}readEnum(t,e){e.name!==void 0&&t.setObjectName(e.name),e.description!==void 0&&t.setDescription(e.description),e.valueType!==void 0&&t.setValueType(e.valueType);const r=e.values||{};for(const n of r){const s=this.createEnumValueFrom(n);t.addEnumValue(s);}}readEnumValue(t,e){e.name!==void 0&&t.setObjectName(e.name),e.description!==void 0&&t.setDescription(e.description),e.value!==void 0&&t.setValue(e.value);}readPropertyTexture(t,e,r){e.setClass(r.class),r.name!==void 0&&e.setName(r.name);const n=r.properties||{};for(const s of Object.keys(n)){const i=n[s],o=this.createPropertyTextureProperty();this.readPropertyTextureProperty(t,o,i),e.setProperty(s,o);}}readPropertyTextureProperty(t,e,r){const s=t.jsonDoc.json.textures||[];r.channels&&e.setChannels(r.channels);const i=s[r.index].source;if(i!==void 0){const o=t.textures[i];e.setTexture(o);const a=e.getTextureInfo();a&&t.setTextureInfo(a,r);}r.offset!==void 0&&e.setOffset(r.offset),r.scale!==void 0&&e.setScale(r.scale),r.max!==void 0&&e.setMax(r.max),r.min!==void 0&&e.setMin(r.min);}readPropertyTable(t,e,r){e.setClass(r.class),r.name!==void 0&&e.setName(r.name),e.setCount(r.count);const n=r.properties||{};for(const s of Object.keys(n)){const i=n[s],o=this.createPropertyTableProperty();this.readPropertyTableProperty(t,o,i),e.setProperty(s,o);}}readPropertyTableProperty(t,e,r){const n=h.obtainBufferViewData(t,r.values);if(e.setValues(n),r.arrayOffsets!=null){const s=h.obtainBufferViewData(t,r.arrayOffsets);e.setArrayOffsets(s);}if(r.stringOffsets!=null){const s=h.obtainBufferViewData(t,r.stringOffsets);e.setStringOffsets(s);}r.arrayOffsetType!==void 0&&e.setArrayOffsetType(r.arrayOffsetType),r.stringOffsetType!==void 0&&e.setStringOffsetType(r.stringOffsetType),r.offset!==void 0&&e.setOffset(r.offset),r.scale!==void 0&&e.setScale(r.scale),r.max!==void 0&&e.setMax(r.max),r.min!==void 0&&e.setMin(r.min);}readPropertyAttribute(t,e){t.setClass(e.class),e.name!==void 0&&t.setName(e.name);const r=e.properties||{};for(const n of Object.keys(r)){const s=r[n],i=this.createPropertyAttributeProperty();this.readPropertyAttributeProperty(i,s),t.setProperty(n,i);}}readPropertyAttributeProperty(t,e){t.setAttribute(e.attribute),e.offset!==void 0&&t.setOffset(e.offset),e.scale!==void 0&&t.setScale(e.scale),e.max!==void 0&&t.setMax(e.max),e.min!==void 0&&t.setMin(e.min);}readPrimitive(t,e,r){if(!r.extensions||!r.extensions[f])return;const n=this.createMeshPrimitiveStructuralMetadata(),i=r.extensions[f],o=t.listPropertyTextures(),a=i.propertyTextures||[];for(const c of a){const p=o[c];n.addPropertyTexture(p);}const u=t.listPropertyAttributes(),d=i.propertyAttributes||[];for(const c of d){const p=u[c];n.addPropertyAttribute(p);}e.setExtension(f,n);}readNode(t,e,r){if(!r.extensions||!r.extensions[f])return;const n=this.createElementStructuralMetadata(),i=r.extensions[f],o=t.listPropertyTables(),a=i.propertyTable,u=i.index;if(a===void 0)throw new Error(`${f}: No property table index in structural metadata`);if(u===void 0)throw new Error(`${f}: No index in structural metadata`);const d=o[a];n.setPropertyTable(d),n.setIndex(u),e.setExtension(f,n);}static obtainBufferViewData(t,e){const r=t.jsonDoc,n=r.json.buffers||[],i=(r.json.bufferViews||[])[e],o=n[i.buffer],a=o.uri?r.resources[o.uri]:r.resources[GLB_BUFFER],u=i.byteOffset||0,d=i.byteLength;return a.slice(u,u+d)}write(t){const e=this.document.getRoot(),r=e.getExtension(f);if(!r)return this;const s=t.jsonDoc.json,i=this.createStructuralMetadataDef(t,r);s.extensions=s.extensions||{},s.extensions[f]=i;const o=e.listMeshes(),a=s.meshes;if(a)for(const c of o){const p=t.meshIndexMap.get(c);if(p===void 0)continue;const l=a[p];c.listPrimitives().forEach((y,D)=>{const P=l.primitives[D];this.writePrimitive(r,y,P);});}const u=e.listNodes(),d=s.nodes;if(d)for(const c of u){const p=t.nodeIndexMap.get(c);if(p===void 0)continue;const l=d[p];this.writeNode(r,c,l);}return this}writePrimitive(t,e,r){const n=e.getExtension(f);if(!n)return;const s=t.listPropertyTextures(),i=t.listPropertyAttributes();let o,a;const u=n.listPropertyTextures();if(u.length>0){o=[];for(const p of u){const l=s.indexOf(p);if(l>=0)o.push(l);else throw new Error(`${f}: Invalid property texture in mesh primitive`)}}const d=n.listPropertyAttributes();if(d.length>0){a=[];for(const p of d){const l=i.indexOf(p);if(l>=0)a.push(l);else throw new Error(`${f}: Invalid property attribute in mesh primitive`)}}const c={propertyTextures:o,propertyAttributes:a};r.extensions=r.extensions||{},r.extensions[f]=c;}writeNode(t,e,r){const n=e.getExtension(f);if(!n)return;const s=t.listPropertyTables(),i=n.getPropertyTable();if(i){const o=s.indexOf(i);if(o>=0){const a={propertyTable:o,index:n.getIndex()??void 0};r.extensions=r.extensions||{},r.extensions[f]=a;}else throw new Error(`${f}: Invalid property tavle in node`)}}createStructuralMetadataDef(t,e){const r={},n=e.getSchema();if(n){const u=this.createSchemaDef(n);r.schema=u;}const s=e.getSchemaUri();s!==null&&(r.schemaUri=s);const i=e.listPropertyTables();if(i.length>0){const u=[];for(const d of i){const c=this.createPropertyTableDef(t,d);u.push(c);}r.propertyTables=u;}const o=e.listPropertyTextures();if(o.length>0){const u=[];for(const d of o){const c=this.createPropertyTextureDef(t,d);u.push(c);}r.propertyTextures=u;}const a=e.listPropertyAttributes();if(a.length>0){const u=[];for(const d of a){const c=this.createPropertyAttributeDef(d);u.push(c);}r.propertyAttributes=u;}return r}createSchemaDef(t){let e,r;const n=t.listClassKeys();if(n.length>0){e={};for(const o of n){const a=t.getClass(o);if(a){const u=this.createClassDef(a);e[o]=u;}}}const s=t.listEnumKeys();if(s.length>0){r={};for(const o of s){const a=t.getEnum(o);if(a){const u=this.createEnumDef(a);r[o]=u;}}}return {id:t.getId(),name:t.getObjectName()??void 0,description:t.getDescription()??void 0,version:t.getVersion()??void 0,classes:e,enums:r}}createClassDef(t){let e;const r=t.listPropertyKeys();if(r.length>0){e={};for(const s of r){const i=t.getProperty(s);if(i){const o=this.createClassPropertyDef(i);e[s]=o;}}}return {name:t.getObjectName()??void 0,description:t.getDescription()??void 0,properties:e}}createClassPropertyDef(t){return {name:t.getObjectName()??void 0,description:t.getDescription()??void 0,type:t.getType(),componentType:t.getComponentType()??void 0,enumType:t.getEnumType()??void 0,array:m(t.getArray(),false)??void 0,count:t.getCount()??void 0,normalized:m(t.getNormalized(),false)??void 0,offset:t.getOffset()??void 0,scale:t.getScale()??void 0,max:t.getMax()??void 0,min:t.getMin()??void 0,required:m(t.getRequired(),false)??void 0,noData:t.getNoData()??void 0,default:t.getDefault()??void 0}}createEnumDef(t){const e=[],r=t.listValues();for(const s of r){const i=this.createEnumValueDef(s);e.push(i);}return {name:t.getObjectName()??void 0,description:t.getDescription()??void 0,valueType:m(t.getValueType(),"UINT16")??void 0,values:e}}createEnumValueDef(t){return {name:t.getObjectName(),description:t.getDescription()??void 0,value:t.getValue()}}createPropertyTableDef(t,e){let r;const n=e.listPropertyKeys();if(n.length>0){r={};for(const i of n){const o=e.getProperty(i);if(o){const a=this.createPropertyTablePropertyDef(t,i,o);r[i]=a;}}}return {name:e.getObjectName()??void 0,class:e.getClass(),count:e.getCount(),properties:r}}createPropertyTablePropertyDef(t,e,r){const n=r.getValues(),s=t.otherBufferViewsIndexMap.get(n);if(s===void 0)throw new Error(`${f}: No values for property table property ${e}`);let i;const o=r.getArrayOffsets();if(o&&(i=t.otherBufferViewsIndexMap.get(o),i===void 0))throw new Error(`${f}: No arrayOffsets for property table property ${e}`);let a;const u=r.getStringOffsets();if(u&&(a=t.otherBufferViewsIndexMap.get(u),a===void 0))throw new Error(`${f}: No stringOffsets for property table property ${e}`);return {values:s,arrayOffsets:i,stringOffsets:a,arrayOffsetType:m(r.getArrayOffsetType(),"UINT32")??void 0,stringOffsetType:m(r.getStringOffsetType(),"UINT32")??void 0,offset:r.getOffset()??void 0,scale:r.getScale()??void 0,max:r.getMax()??void 0,min:r.getMin()??void 0}}createPropertyTextureDef(t,e){let r;const n=e.listPropertyKeys();if(n.length>0){r={};for(const i of n){const o=e.getProperty(i);if(o){const a=this.createPropertyTexturePropertyDef(t,i,o);r[i]=a;}}}return {name:e.getObjectName()??void 0,class:e.getClass(),properties:r}}createPropertyTexturePropertyDef(t,e,r){const n=r.getTexture(),s=r.getTextureInfo();if(!n)throw new Error(`${f}: No texture for property texture property ${e}`);if(!s)throw new Error(`${f}: No textureInfo for property texture property ${e}`);const i=t.createTextureInfoDef(n,s);return {channels:m(r.getChannels(),[0])??void 0,index:i.index,texCoord:i.texCoord,offset:r.getOffset()??void 0,scale:r.getScale()??void 0,max:r.getMax()??void 0,min:r.getMin()??void 0}}createPropertyAttributeDef(t){let e;const r=t.listPropertyKeys();if(r.length>0){e={};for(const s of r){const i=t.getProperty(s);if(i){const o=this.createPropertyAttributePropertyDef(i);e[s]=o;}}}return {name:t.getObjectName()??void 0,class:t.getClass(),properties:e}}createPropertyAttributePropertyDef(t){return {attribute:t.getAttribute(),offset:t.getOffset()??void 0,scale:t.getScale()??void 0,max:t.getMax()??void 0,min:t.getMin()??void 0}}prewrite(t,e){return e===PropertyType.BUFFER&&this._prewriteBuffers(t),this}_prewriteBuffers(t){const r=this.document.getRoot().getExtension(f);if(!r)return;const s=t.jsonDoc.json;let i=s.bufferViews;i||(i=[],s.bufferViews=i);const o=r.listPropertyTables();for(const a of o){const u=a.listPropertyValues();for(const d of u){const c=this.obtainOtherBufferViews(t),p=d.getValues();c.push(p);const l=d.getArrayOffsets();l&&c.push(l);const y=d.getStringOffsets();y&&c.push(y);}}}obtainOtherBufferViews(t){const r=this.document.getRoot().listBuffers()[0];let n=t.otherBufferViews.get(r);return n||(n=[],t.otherBufferViews.set(r,n)),n}};h.EXTENSION_NAME=f;let x=h;export{x as EXTStructuralMetadata};//# sourceMappingURL=EXTStructuralMetadata.js.map //# sourceMappingURL=EXTStructuralMetadata.js.map