Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(converter): support writing 3DTILES of version 1.1 #3054

Merged
merged 12 commits into from
Sep 16, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ NodeJS 14 or higher is required.
| tileset | \* | \* | "tileset.json" file (3DTiles) / "http://..../SceneServer/layers/0" resource (I3S) |
| output | \* | \* | Output folder. This folder will be created by converter if doesn't exist. It is relative to the converter path. Default: "./data" folder |
| name | \* | \* | Tileset name. This option is required for naming in the output json resouces and for the output `path/\*.slpk` file naming |
| output-version | | \* | Version of 3D Tiles format. This option is used for I3S to 3DTiles conversion only (optional). Possible values - "1.0", "1.1" (default). More information on the 3D Tiles revisions: https://github.com/CesiumGS/3d-tiles/blob/main/3d-tiles-reference-card-1.1.pdf|
| max-depth | \* | \* | Maximal depth of the hierarchical tiles tree traversal, default: infinity |
| slpk | \* | | Whether the converter generates \*.slpk (Scene Layer Package) I3S output files |
| 7zExe | \* | | location of 7z.exe archiver to create slpk on Windows OS, default: "C:\\Program Files\\7-Zip\\7z.exe" |
Expand Down
2 changes: 1 addition & 1 deletion modules/gltf/src/glb-writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const GLBWriter = {
} as const satisfies WriterWithEncoder<GLB, never, GLBWriterOptions>;

function encodeSync(glb, options) {
const {byteOffset = 0} = options || {};
const {byteOffset = 0} = options ?? {};

// Calculate length and allocate buffer
const byteLength = encodeGLBSync(glb, null, byteOffset, options);
Expand Down
1 change: 1 addition & 0 deletions modules/i3s/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ export {SLPKArchive} from './lib/parsers/parse-slpk/slpk-archieve';
export {parseSLPKArchive} from './lib/parsers/parse-slpk/parse-slpk';
export {LayerError} from './lib/parsers/parse-arcgis-webscene';
export {customizeColors} from './lib/utils/customize-colors';
export {type I3STileAttributes} from './lib/parsers/parse-i3s-attribute';
54 changes: 40 additions & 14 deletions modules/tile-converter/src/3d-tiles-converter/3d-tiles-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import type {
AttributeStorageInfo,
FeatureAttribute,
NodeReference,
I3STilesetHeader
I3STilesetHeader,
I3STileAttributes
} from '@loaders.gl/i3s';
import type {Tile3DBoundingVolume, Tiles3DTileJSON} from '@loaders.gl/3d-tiles';

Expand All @@ -22,7 +23,10 @@ import {TILESET as tilesetTemplate} from './json-templates/tileset';
import {createObbFromMbs} from '../i3s-converter/helpers/coordinate-converter';
import {WorkerFarm} from '@loaders.gl/worker-utils';
import {BROWSER_ERROR_MESSAGE} from '../constants';
import B3dmConverter, {I3SAttributesData} from './helpers/b3dm-converter';
import {
Tiles3DContentConverter,
type I3SAttributesData
} from './helpers/3d-tiles-content-converter';
import {I3STileHeader} from '@loaders.gl/i3s/src/types';
import {getNodeCount, loadFromArchive, loadI3SContent, openSLPK} from './helpers/load-i3s';
import {I3SLoaderOptions} from '@loaders.gl/i3s/src/i3s-loader';
Expand Down Expand Up @@ -59,6 +63,7 @@ export default class Tiles3DConverter {
};
conversionDump: ConversionDump;
progress: Progress;
fileExt: string;

constructor() {
this.options = {};
Expand All @@ -71,13 +76,15 @@ export default class Tiles3DConverter {
this.workerSource = {};
this.conversionDump = new ConversionDump();
this.progress = new Progress();
this.fileExt = '';
}

/**
* Convert i3s format data to 3dTiles
* @param options
* @param options.inputUrl the url to read the tileset from
* @param options.outputPath the output filename
* @param options.outputVersion the version of 3DTiles
* @param options.tilesetName the output name of the tileset
* @param options.egmFilePath location of *.pgm file to convert heights from ellipsoidal to gravity-related format
* @param options.maxDepth The max tree depth of conversion
Expand All @@ -87,6 +94,7 @@ export default class Tiles3DConverter {
inputUrl: string;
outputPath: string;
tilesetName: string;
outputVersion?: string;
maxDepth?: number;
egmFilePath: string;
inquirer?: {prompt: PromptModule};
Expand All @@ -96,9 +104,19 @@ export default class Tiles3DConverter {
console.log(BROWSER_ERROR_MESSAGE); // eslint-disable-line no-console
return BROWSER_ERROR_MESSAGE;
}
const {inputUrl, outputPath, tilesetName, maxDepth, egmFilePath, inquirer, analyze} = options;
const {
inputUrl,
outputPath,
outputVersion,
tilesetName,
maxDepth,
egmFilePath,
inquirer,
analyze
} = options;
this.conversionStartTime = process.hrtime();
this.options = {maxDepth, inquirer};
this.options = {maxDepth, inquirer, outputVersion};
this.fileExt = this.options.outputVersion === '1.0' ? 'b3dm' : 'glb';

console.log('Loading egm file...'); // eslint-disable-line
this.geoidHeightModel = await load(egmFilePath, PGMLoader);
Expand Down Expand Up @@ -173,7 +191,7 @@ export default class Tiles3DConverter {

await this._addChildren(rootNode, rootTile, 1);

const tileset = transform({root: rootTile}, tilesetTemplate());
const tileset = transform({asset: {version: outputVersion}, root: rootTile}, tilesetTemplate());
await writeFile(this.tilesetPath, JSON.stringify(tileset), 'tileset.json');
await this.conversionDump.deleteDumpFile();

Expand Down Expand Up @@ -244,7 +262,7 @@ export default class Tiles3DConverter {
if (sourceChild.contentUrl) {
if (
this.conversionDump.restored &&
this.conversionDump.isFileConversionComplete(`${sourceChild.id}.b3dm`) &&
this.conversionDump.isFileConversionComplete(`${sourceChild.id}.${this.fileExt}`) &&
(sourceChild.obb || sourceChild.mbs)
) {
const {child} = this._createChildAndBoundingVolume(sourceChild);
Expand All @@ -266,7 +284,7 @@ export default class Tiles3DConverter {

this.vertexCounter += content?.vertexCount || 0;

let featureAttributes: FeatureAttribute | null = null;
let featureAttributes: I3STileAttributes | null = null;
if (this.attributeStorageInfo) {
featureAttributes = await this._loadChildAttributes(sourceChild, this.attributeStorageInfo);
}
Expand All @@ -279,13 +297,21 @@ export default class Tiles3DConverter {
textureFormat: sourceChild.textureFormat
};

const b3dmConverter = new B3dmConverter();
const b3dm = await b3dmConverter.convert(i3sAttributesData, featureAttributes);
const converter = new Tiles3DContentConverter({outputVersion: this.options.outputVersion});
const contentData = await converter.convert(
i3sAttributesData,
featureAttributes,
this.attributeStorageInfo
);

await this.conversionDump.addNode(`${sourceChild.id}.b3dm`, sourceChild.id);
await writeFile(this.tilesetPath, new Uint8Array(b3dm), `${sourceChild.id}.b3dm`);
await this.conversionDump.addNode(`${sourceChild.id}.${this.fileExt}`, sourceChild.id);
await writeFile(
this.tilesetPath,
new Uint8Array(contentData),
`${sourceChild.id}.${this.fileExt}`
);
await this.conversionDump.updateConvertedNodesDumpFile(
`${sourceChild.id}.b3dm`,
`${sourceChild.id}.${this.fileExt}`,
sourceChild.id,
true
);
Expand Down Expand Up @@ -379,7 +405,7 @@ export default class Tiles3DConverter {
geometricError: convertScreenThresholdToGeometricError(sourceChild),
children: [],
content: {
uri: `${sourceChild.id}.b3dm`,
uri: `${sourceChild.id}.${this.fileExt}`,
boundingVolume
}
};
Expand Down Expand Up @@ -417,7 +443,7 @@ export default class Tiles3DConverter {
private async _loadChildAttributes(
sourceChild: I3STileHeader,
attributeStorageInfo: AttributeStorageInfo[]
): Promise<FeatureAttribute> {
): Promise<I3STileAttributes> {
const promises: any[] = [];
const {attributeUrls = []} = sourceChild;

Expand Down
Loading
Loading