visgl / loaders.gl

Loaders for big data visualization. Website:
https://loaders.gl
Other
690 stars 189 forks source link

[Bug] GLTF: Scenegraph json not iterable #2816

Open Krassnig opened 8 months ago

Krassnig commented 8 months ago

Hi,

this tileset of the city of Berlin crashes when loading its b3dm files.

image

I tried to debug it. In @loaders.gl\gltf\src\lib\extensions\EXT_texture_webp.ts in the function preprocess() (link) json.texture happens to be an object. Since it is an object and not null or undefined || [] will not be used and since that object is not iterable and an error is thrown.

Here is a minimal script to reproduce the error:

import { Tiles3DLoader } from "@loaders.gl/3d-tiles";
import { load } from "@loaders.gl/core";
import { Tileset3D } from "@loaders.gl/tiles";
import { WebMercatorViewport } from "@deck.gl/core/typed";

main();
async function main() {
    // tilset of berlin
    const tilesetJson = await load('https://www.businesslocationcenter.de/berlin3d-downloadportal/datasource-data/567c2cc6-9464-4a08-82b8-1034e39f3c9d/tileset.json', Tiles3DLoader);
    const tileset3d = new Tileset3D(tilesetJson, {
        onTileLoad: tile => {
            console.log('tile loaded: ', tile.content.type, tile);
        },
        onTileError: error => {
            console.info('tile erred: ', error);
        }
    });

    tileset3d.selectTiles(new WebMercatorViewport({
        width: 3000,
        height: 3000,
        latitude: 52.492897689422655,
        longitude: 13.387880635376609,
        zoom: 18
    }));

    await delay(2000);

    // Reichstag
    tileset3d.selectTiles(new WebMercatorViewport({
        width: 3000,
        height: 3000,
        latitude: 52.51861879676078,
        longitude: 13.376075388887253,
        zoom: 18
    }));

    await delay(2000);

    // Brandenburger Tor
    tileset3d.selectTiles(new WebMercatorViewport({
        width: 3000,
        height: 3000,
        latitude: 52.51624429971451,
        longitude: 13.377695171600305,
        zoom: 18
    }));
}

function delay(milliseconds: number) {
    return new Promise<void>(resolve => setTimeout(() => resolve(), milliseconds));
}

I don't know why exactly but it only starts loading b3dm files after the third call to selectTiles but that is not what this issue is about.

donmccurdy commented 5 months ago

The three warnings appearing before the final error are the important bits here — these are a glTF 1.0 files, embedded in an older version of the B3DM format. LoadersGL requires glTF 2.0. Perhaps also relevant, the EXT_texture_webp extension itself requires glTF 2.0, so there may be some issues with this tileset if it has combined glTF 1.0 with the EXT_texture_webp extension.

ibgreen commented 5 months ago

There is partial support for "auto-upconverting" glTF 1.0 files, but perhaps it requires enabling a GLTFLoader option, I don't recall... And it doesn't upconvert everything in glTF 1.0 so whether it works depends on the file. Looking at the error, it could be that a simple additional conversion step for textures would enable this particular file to load.