I'm trying to use 3D models in Mapbox, and for that I'm using the new ModelLayer component
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
I tried with 2 different model extensions: GLB and GLTF, which are attached below:
Mapbox Version: 11.1.0
React Native Version: 0.73.4
Platform: iOS
@rnmapbox/maps Version: 10.1.17
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";
const MainContainer = () => {
return (
<View style={{ flex: 1 }}>
<MapboxGL.MapView
projection="globe"
style={{ flex: 1 }}
logoEnabled={false}
compassEnabled
compassFadeWhenNorth
scaleBarEnabled={false}
pitchEnabled
>
<MapboxGL.Models models={{ car: require("./model.glb") }} />
<MapboxGL.Camera zoomLevel={1} animationDuration={1.5} />
<MapboxGL.ShapeSource key={chunk.id} shape={chunk} id={chunk.id}>
<MapboxGL.ModelLayer
id={`example-id`}
style={{
modelId: "car",
}}
/>
</MapboxGL.ShapeSource>
</MapboxGL.MapView>
</View>
);
};
export default MainContainer;
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>
);
};