react-three-fiber: Importing .glb file with useGLTF on ReactNative Expo fails

It seems that I’m doing everything according to the documentation https://docs.pmnd.rs/react-three-fiber/tutorials/v8-migration-guide for React Native Expo.

image

I have the latest dependencies, just installed everything freshly and overall @react-three/fiber/native works great and renders my 3D stuff. It just fails to load .glb file. What am I doing wrong? Could it be something related to the way expo imports the .glb file? I have also configured my metro.config.js according to the documentation

metro.config.js

const { getDefaultConfig } = require('expo/metro-config');

const config = getDefaultConfig(__dirname);

config.resolver.assetExts.push('glb', 'gltf', 'png', 'jpg', 'svg');

config.resolver.sourceExts.push('js', 'jsx', 'json', 'ts', 'tsx', 'cjs');

module.exports = config;

My dependencies

{
  "name": "greatApp",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\""
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "dependencies": {
    "@react-three/drei": "^9.51.20",
    "@react-three/fiber": "^8.10.0",
    "expo": "~47.0.12",
    "expo-gl": "~12.0.1",
    "expo-status-bar": "~1.4.2",
    "expo-three": "^7.0.0",
    "immer": "^9.0.17",
    "r3f-native-orbitcontrols": "^1.0.5",
    "react": "18.1.0",
    "react-native": "0.70.5",
    "three": "^0.148.0",
    "three-noise": "^1.1.2",
    "three-stdlib": "^2.21.5",
    "typescript": "^4.6.3",
    "zustand": "^4.2.0"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@react-native-community/eslint-config": "^3.2.0",
    "@tsconfig/react-native": "^2.0.3",
    "@types/react-native": "^0.70.8",
    "@types/three": "^0.148.0",
    "@typescript-eslint/eslint-plugin": "^5.48.0",
    "@typescript-eslint/parser": "^5.48.0",
    "eslint": "^8.31.0",
    "eslint-config-prettier": "^8.6.0",
    "eslint-plugin-prettier": "^4.2.1",
    "jest": "^29.3.1",
    "prettier": "^2.8.2"
  },
  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ]
  },
  "private": true
}

Here’s a code example that fails

...
import { useGLTF } from '@react-three/drei/native'

const MyModel = () => {
   // Calling this line fails and gives me an error
   const { nodes } = useGLTF(require('./models/fancyModel.glb'))

   return (
      ...
   )
}

I do have a .glb file in the ./models/fancyModel.glb which works fine on the web app.

The error I’m getting image

Thanks

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 3
  • Comments: 16 (4 by maintainers)

Most upvoted comments

Having the same issue. Please let me know if there is any solution. Thank you so much!

Yes embedded textures load since R3F polyfills previously missing APIs needed to unpack textures from GLB, and I continued there WRT emulator not pushing frames. Unfortunately Apple has been breaking their OpenGL code path under XCode so the only option is to test on device until we move to Metal/WebGPU.

I updated it today from the cube example

I don’t follow this, what do you mean? Do you mean we no longer need to use gltfjsx?

Either way, I don’t think react-three-fiber works with React Native at all right now, regardless of gltf https://github.com/pmndrs/react-three-fiber/discussions/3064

Any solution found?? I’m also trying to use useGLTF but its not working code:: import React, { Suspense } from ‘react’; import { useFrame, Canvas } from ‘@react-three/fiber/native’; import { useGLTF } from ‘@react-three/drei/native’; import Bedmodelpath from ‘…/…/…/assets/Airmax/bed1.glb’; function Model({ url, …rest }) { const { scene } = useGLTF(url) useFrame(() => (scene.rotation.y += 0.01)) return <primitive {…rest} object={scene} /> } export default function Suggestions() { return ( <Canvas gl={{ physicallyCorrectLights: true }} camera={{ position: [-6, 0, 16], fov: 36 }}> <directionalLight intensity={1.1} position={[0.5, 0, 0.866]} /> <directionalLight intensity={0.8} position={[-6, 2, 2]} /> ) }

I solved this months ago, i am not sure if a remember right, but the reason should be something like the useGLTF(url) cannot locate the glb/glft file path correctly. What I do is that to import the model first, and then pass to the useGLTF() function directly instead of calling Model() to get th url.

import React, { useRef } from "react";
import { useGLTF, useFBX, useAnimations } from "@react-three/drei/native";
import xbot from "./assets/models/Xbot.glb"; // the model path in your directory

export default function CapmiAvatar(props) {
    const group = useRef();

    const { nodes, materials } = useGLTF(xbot);
    return (
        <group ref={group} {...props} dispose={null}>
            <group name='Scene'>
                <group name='Armature' scale={0.01}>
                    <primitive object={nodes.mixamorigHips} />
                    <skinnedMesh
                        name='Beta_Joints'
                        geometry={nodes.Beta_Joints.geometry}
                        material={materials.Beta_Joints_MAT}
                        skeleton={nodes.Beta_Joints.skeleton}
                    />
                    <skinnedMesh
                        name='Beta_Surface'
                        geometry={nodes.Beta_Surface.geometry}
                        material={materials["asdf1:Beta_HighLimbsGeoSG2"]}
                        skeleton={nodes.Beta_Surface.skeleton}
                    />
                </group>
            </group>
        </group>
    );

What versions are you using? I’m dealing with the same problem and this solution doesn’t work for me 😕

I found this issue resolves if the GLTF path is specified at the file-level instead of the component-level. For example in the migration guide (https://docs.pmnd.rs/react-three-fiber/tutorials/v8-migration-guide#react-native-support) it specifies the modelPath var which is consumed in the component.

import modelPath from './assets/model.glb'

function Model(props) {
  const { scene } = useGLTF(modelPath)
  return <primitive {...props} object={scene} />
}

I get the same error…

Hey @CodyJasonBennett , I’ve got a minimal reproduction here: https://github.com/thiagobrez/expo-useGLTF

Basic r3f scene works, but when trying to load a local model (either local or remote URL), useGLTF fails with

Possible Unhandled Promise Rejection (id: 0):
Error: Unable to download file: Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL"

Checklist:

  • Importing from @react-three/fiber/native, @react-three/drei/native
  • Configured metro according to docs
  • Tried loading model locally using Expo’s Asset.fromModule
  • Tried loading model from remote pmndrs’ market URL
  • Explicitly passing a meshStandardMaterial to prevent the material bug in expo-gl

Do you have any insights on this? Thank you in advance!

I’d be happy to contribute to the docs if there is any good practice that I’m missing. If you think this issue might be better suited for the drei repo, or even Expo, please let me know!