maps icon indicating copy to clipboard operation
maps copied to clipboard

[Bug]: RNMBXModels.models.getter not implemented (Expo Project)

Open rodrigo4635 opened this issue 1 year ago • 8 comments

Mapbox Implementation

Mapbox

Mapbox Version

11.1.0

React Native Version

0.73.4

Platform

iOS

@rnmapbox/maps version

10.1.17

Standalone component to reproduce

metro.config.js:

const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
config.resolver.assetExts.push("gltf", "glb");
module.exports = config;

app.json:

{
  "expo": {
    "name": "my-app",
    "plugins": [
      [
        "@rnmapbox/maps",
        {
          "RNMapboxMapsVersion": "11.1.0",
          "RNMapboxMapsDownloadToken": "token..."
        }
      ]
    ]
  }
}

package.json

{
  "dependencies": {
    "@rnmapbox/maps": "^10.1.17",
    "expo": "~50.0.6",
    "expo-asset": "~9.0.2",
    "expo-gl": "^13.6.0",
    "expo-three": "^7.0.0",
    "react": "18.2.0",
    "react-native": "0.73.4",
    "three": "^0.162.0"
  }
}

src/screens/explore/Main/Main.tsx

import React from 'react';
import {View} from 'react-native';
import MapboxGL from '@rnmapbox/maps';
import {FeatureCollection, GeoJsonProperties, Geometry} from 'geojson';

MapboxGL.setAccessToken(
  'token...',
);

const features = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      id: 'a-feature',
      properties: {
        icon: 'example',
        text: 'example-icon-and-label',
      },
      geometry: {
        type: 'Point',
        coordinates: [-74.00597, 40.71427],
      },
    },
    {
      type: 'Feature',
      id: 'b-feature',
      properties: {
        text: 'just-label',
      },
      geometry: {
        type: 'Point',
        coordinates: [-74.001097, 40.71527],
      },
    },
    {
      type: 'Feature',
      id: 'c-feature',
      properties: {
        shown: 'visible',
        icon: 'example',
      },
      geometry: {
        type: 'Point',
        coordinates: [-74.00697, 40.72427],
      },
    },
  ],
} as FeatureCollection<Geometry, GeoJsonProperties>;

const models = {
  car: require('./model.glb'),
};

const MainContainer = () => {
  return (
    <View style={{flex: 1}}>
      <MapboxGL.MapView
        projection="globe"
        style={{flex: 1}}
        logoEnabled={false}
        compassEnabled
        compassFadeWhenNorth
        scaleBarEnabled={false}
        pitchEnabled>
        <MapboxGL.Models models={models} />
        <MapboxGL.Camera
          zoomLevel={14}
          centerCoordinate={[-74.00597, 40.71427]}
        />
        <MapboxGL.ShapeSource id={'shape-source-id-0'} shape={features}>
          <MapboxGL.ModelLayer
            existing
            id="model-layer-id"
            style={{
              modelId: 'car',
              modelScale: [5, 5, 5],
            }}
          />
        </MapboxGL.ShapeSource>
      </MapboxGL.MapView>
    </View>
  );
};

export default MainContainer;

Use this model to test: model.glb.zip

Observed behavior and steps to reproduce

I'm trying to use 3D models in Mapbox, and for that I'm using the new ModelLayer

I installed the packages and ran the npx expo prebuild command to generate the native code

I installed the App on my iOS phone using the expo run:ios --device command

The app loads and the map renders normally, but I get the following error

Mapbox [error] RNMBXModels.models.getter not implemented

I also tried using the Expo Asset to load the model and replace the require in the Models component with the asset uri or localUri, but I got the same error

const [assets, error] = useAssets([require("./model.glb")]);
console.log(assets)
// Log:
const log = [{
  "_downloadCallbacks": [],
  "downloaded": true,
  "downloading": false,
  "hash": "c34a01e8c2a282dc923835a1383c9e50",
  "height": null,
  "localUri": "file:///var/mobile/Containers/Data/Application/8100310E-954B-4F8E-B21F-058F887252C9/Library/Caches/ExponentAsset-c34a01e8c2a282dc923835a1383c9e50.glb",
  "name": "model",
  "type": "glb",
  "uri": "http://192.168.1.244:8081/assets/?unstable_path=.%2Fsrc%2Fscreens%2Fexplore%2FMain/model.glb?platform=ios&hash=c34a01e8c2a282dc923835a1383c9e50",
  "width": null
}]

Expected behavior

Render the 3D model on the map

Notes / preliminary analysis

Using the <MapboxGL.Images images={{ example: require("./image.png") }} /> with a SymbolLayer works and I can see the images on the map.

Using @react-three/fiber/native and @react-three/drei/native to render the model on the screen works normally, I used the following code for this:

import React, { Suspense } from "react";
import { View } from "react-native";
import { useFrame, Canvas } from "@react-three/fiber/native";
import { useGLTF, Environment } from "@react-three/drei/native";
import modelPath from "./model.glb";

function Model({ url, ...rest }) {
  const { scene } = useGLTF(url);
  useFrame(() => (scene.rotation.y += 0.01));
  return <primitive {...rest} object={scene} />;
}

const MainContainer = () => {
  return (
    <View style={{ flex: 1, backgroundColor: "red" }}>
      <Canvas gl={{ physicallyCorrectLights: true }} camera={{ position: [-6, 0, 16], fov: 36 }}>
        <color attach="background" args={[0xe2f4df]} />
        <ambientLight />
        <directionalLight intensity={1.1} position={[0.5, 0, 0.866]} />
        <directionalLight intensity={0.8} position={[-6, 2, 2]} />
        <Suspense>
          <Environment preset="park" />
          <Model url={modelPath} />
        </Suspense>
      </Canvas>
    </View>
  );
};

rodrigo4635 avatar Mar 01 '24 04:03 rodrigo4635

I'm sorry this is not a component that I can copy&paste to try out. Pls fix that

mfazekas avatar Mar 03 '24 07:03 mfazekas

          <MapboxGL.ModelLayer
            existing
            id="model-layer-id"
            style={{
              modelId: 'car',
              modelScale: [5, 5, 5],
            }}
          />

the existing attribute means that the layer is expected to be in the style already. Which is don't think the case here.

mfazekas avatar Mar 04 '24 11:03 mfazekas

Hi @mfazekas, I did the change #3406 in my project and removed the existing property, but after testing the model still don't load in my expo project, only in a CLI RN project, can you check?

rodrigo4635 avatar Mar 05 '24 05:03 rodrigo4635

@rodrigo4635 so it works in an RN project, but not in an expo project?

mfazekas avatar Mar 05 '24 07:03 mfazekas

@mfazekas Exactly, I copied the code from this issue and placed it in an Expo project and a CLI project, with the same libraries and tokens, running on a real iOS device (iPhone 12).

rodrigo4635 avatar Mar 05 '24 10:03 rodrigo4635

@mfazekas Hello, any news about this issue? Also, I noticed that ShapeSource's onPress event does not fire when you click on a ModelLayer. Using the same component as this example, if I add an onPress to the ShapeSource it doesn't fire when I click on a model layer, but it does if I use any other type (SymbolLayer for example)

rodrigo4635 avatar Mar 12 '24 08:03 rodrigo4635

Hello @mfazekas any update about this ?

kbvac avatar Jun 18 '24 10:06 kbvac

Same issue here @mfazekas . Can't seem to render the 3D model on the map with expo using ModelLayer. "expo": "~52.0.20", "react-native": "0.76.5", a bit stuck here, any help is much appreciated.

bvur avatar Dec 22 '24 22:12 bvur