Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useGLTF does not work on React Native #3049

Closed
krzys-h opened this issue Oct 20, 2023 · 2 comments · Fixed by #3050
Closed

useGLTF does not work on React Native #3049

krzys-h opened this issue Oct 20, 2023 · 2 comments · Fixed by #3050
Labels
bug Something isn't working

Comments

@krzys-h
Copy link

krzys-h commented Oct 20, 2023

I'm trying to use useGLTF on React Native, on Android using the dev server, but it fails with Could not load 1: undefined. I see that there was discussion about this issue in
#2992 with a fix released in 8.14.6 (#3042), but the supposed fix does not seem to work for me (and yes, I triple checked I'm on the version that actually includes the fix)

The bug appears to be somewhere in the THREE.FileLoader.load polyfill here:

getAsset(url)
.then((localUri) => {
request.open('GET', localUri, true)

getAsset returns a local URI such as file:///data/user/0/[package name]/cache/ExponentAsset-2b9cf0b0c0fbce3e50f135af2855df6e.glb, but XMLHttpRequest does not seem to support file URLs and fails with Expected URL scheme 'http' or 'https' but was 'file' (and the error handling is messed up somehow causing the undefined message, you can see the error by logging the entire XMLHttpRequest object)

@krzys-h
Copy link
Author

krzys-h commented Oct 20, 2023

I temporarily hacked it myself by doing the following to avoid XMLHttpRequest entirely:

// Fix for https://github.com/pmndrs/react-three-fiber/issues/3049
if (Platform.OS !== 'web') {
  THREE.FileLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
    const asset = typeof url === 'string' ? Asset.fromURI(url) : Asset.fromModule(url)
    this.manager.itemStart(url)
    asset.downloadAsync()
        .then((asset) => {
          return FileSystem.readAsStringAsync(asset.localUri, { encoding: FileSystem.EncodingType.Base64 })
        })
        .then((content) => {
          const byteCharacters = atob(content)
          const byteNumbers = new Array(byteCharacters.length)
          for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i)
          }
          const byteArray = new Uint8Array(byteNumbers)
          onLoad?.(byteArray.buffer)
          this.manager.itemEnd(url)
        })
        .catch((e) => {
          onError?.(e as unknown as ErrorEvent)
          this.manager.itemError(url)
          this.manager.itemEnd(url)
        })
  }
}

But then I ran into another related issue, this time in the TextureLoader polyfill. In a built app (not using the dev server), it fails with

10-20 13:22:53.062 18031 18092 E AndroidRuntime: com.facebook.react.common.JavascriptException: Error: Could not load 2: Call to function 'ExponentFileSystem.copyAsync' has been rejected.
10-20 13:22:53.062 18031 18092 E AndroidRuntime: → Caused by: java.io.IOException: Source '/data/user/0/[package name]/cache/ExponentAsset-88e3b9e860e40a1d3a992dc42bf3d9aa.png' and destination '/data/user/0/[package name]/cache/ExponentAsset-88e3b9e860e40a1d3a992dc42bf3d9aa.png' are the same

this seems to be a bug in #3042, as it changed the code like this:

-    // Unpack assets in Android Release Mode
-    if (!uri.includes(':')) {
-      const file = `${fs.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`
-      await fs.copyAsync({ from: uri, to: file })
-      uri = file
-    }
+  // Unpack assets in Android Release Mode
+  if (!localUri.includes('://')) {
+    localUri = `${cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`
+    await copyAsync({ from: localUri, to: localUri })
+  }

note how the arguments to copyAsync are now the same

@CodyJasonBennett
Copy link
Member

Thanks. I've put out v8.14.7 which reverts #3042 and implements a similar fix for FileLoader (and incidentally TextureLoader).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants