1

I'm trying to dynamically load a user-loaded gltf model and have that model be placed on top of a map. The second part would be doing the same thing but with IFC model. I'm working with react-map-gl to create a map and I've been able to place a 3D model on top of the map just like the one described in this example: just by simply putting a gltf url like this one inside deck.gl's scenegraph layer. However what I'm having a hard time doing is placing a user-loaded IFC or GLTF model on top of the map. All the example I've seen uses a GLTF url, or some url that comes from arcgis but is there a way to place a user loaded model inside of the scenegraph layer in deck.gl?

This is my best attempt at placing a user-uploaded GLTF model which gives me the error message: deck: loading scenegraph of ScenegraphLayer({id: 'scenegraph-layer'}): No valid loader found (0f3e4b8a-f7d4-4cbd-868e-c4c463552bca, MIME type: not provided, first bytes: not available)

import { useState } from 'react';
import { Map } from 'react-map-gl';
import { ScenegraphLayer } from '@deck.gl/mesh-layers';
import { DeckGL } from 'deck.gl';
import maplibreGl from 'maplibre-gl';

function App() {
  const [gltfUrl, setGltfUrl] = useState();

  const gltfUpload = (e) => {
    const file = e.target.files[0];
    const url = URL.createObjectURL(file);
    setGltfUrl(url);
  };

  const layer = new ScenegraphLayer({
    id: 'scenegraph-layer',
    pickable: true,
    data: [
      {
        name: 'Colma (COLM)',
        address: '365 D Street, Colma CA 94014',
        exits: 4214,
        coordinates: [148.9819, -35.39847],
      },
    ],
    scenegraph: gltfUrl,
    getPosition: (d) => d.coordinates,
    getOrientation: (d) => [0, Math.random() * 180, 90],
    sizeScale: 1,
    _lighting: 'pbr',
  });

  return (
    <>
      <input
        type='file'
        onChange={gltfUpload}
        style={{ zIndex: 10, position: 'fixed' }}
      />
      <DeckGL
        initialViewState={{
          longitude: 148.9819,
          latitude: -35.39847,
          zoom: 18,
          pitch: 60,
        }}
        controller={true}
        layers={[layer]}
      >
        <Map
          mapLib={maplibreGl}
          mapStyle='https://api.maptiler.com/maps/basic/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL'
        />
      </DeckGL>
    </>
  );
}

export default App;

And this is my best attempt at placing an IFC model using I3SLoader and web-ifc-three and this code gives me the error: Uncaught (in promise) Error: Cannot convert supplied data type at getArrayBufferOrStringFromData

import { useState } from 'react';
import maplibregl from 'maplibre-gl';
import DeckGL from '@deck.gl/react';
import { Map } from 'react-map-gl';
import { Tile3DLayer } from '@deck.gl/geo-layers';
import { I3SLoader } from '@loaders.gl/i3s';
import { IFCLoader } from 'web-ifc-three';

function App() {
  const [ifcObject, setIfcObject] = useState();

  const ifcLoader = new IFCLoader();
  const ifcUpload = (e) => {
    const file = e.target.files[0];
    const url = URL.createObjectURL(file);
    ifcLoader.loadAsync(url).then((res) => {
      setIfcObject(res);
    });
  };

  const layer = new Tile3DLayer({
    id: 'tile-3d-layer',
    // Tileset entry point: Indexed 3D layer file url
    data: ifcObject,
    loader: I3SLoader,
  });

  return (
    <>
      <input
        type='file'
        onChange={ifcUpload}
        style={{ zIndex: 10, position: 'fixed' }}
      />
      <DeckGL
        initialViewState={{
          longitude: 148.9819,
          latitude: -35.39847,
          zoom: 18,
          pitch: 60,
        }}
        controller={true}
        layers={[layer]}
      >
        <Map
          mapLib={maplibregl}
          mapStyle='https://api.maptiler.com/maps/basic/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL'
        />
      </DeckGL>
    </>
  );
}

I honestly have no clue what I'm even doing at this point. I'm pretty lost and I appreciate all the help that I can get. Thanks in advance!

Hillzkred
  • 11
  • 2

0 Answers0