BabylonReactNative: importing a .glb file fails if only local path is provided and not served through HTTP

Hi!

First of all, thanks for the great work for all maintainers.

I’ve just started using this library in my project for rendering .glb files.

When the .glb file is served from a local static server, SceneLoader.ImportMeshAsync and other similar methods used for importing assets, such as Append, AppendAsync, etc… work perfectly. However, when the file is not requested over HTTP, but rather the local path is provided to the above stated methods, the app just crashes without any easily traceable error (I wasn’t looking so hard for the error, but it didn’t appear in the terminal of the packager). Maybe it’s my uneducatedness but from the documentation available here, I expected the import to work with just a local path.

I was able to solve the issue by using expo-asset to load the .glb file instead and provide a local uri, and then passing that local uri to Babylon, described in the below way:

import '@babylonjs/loaders';
import { Asset } from 'expo-asset';
import { SceneLoader, ... } from '@babylonjs/core';
 
const [{ localUri }] = await Asset.loadAsync(
  require('/assets/3d/tesla-high.glb')
);

const { meshes } = await SceneLoader.ImportMeshAsync(
  '',
  localUri as string,
  '',
  scene
);

However, I’d expect the library to do something similar internally, making the user to be able to only provide a path to a local .glb file and it load it without issues. If this work is purposefully left for the user, it would be nice to have it stated in the main documentation, since I think it’s quite a common use-case.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 5
  • Comments: 21 (9 by maintainers)

Most upvoted comments

@f4z3k4s Sorry for the delay. I just tested this on iOS and figured out how to get it working with the help of your method as a starting point. This is how I got this working on iOS:

import { Image } from 'react-native';

// rootUrl being something like /assets/your-asset.glb 
const file = require(rootUrl);

const uri = Image.resolveAssetSource(file).uri;

SceneLoader.ImportMeshAsync(
  '',
  uri,
  '',
  scene
);

Thanks for the quick response guys.

I was thinking of something similar that you pasted. I just realised that require can not be handled internally by your package because it is resolved at build time from string literals, rather than variables.

So your proposal seems React-Native-y in my opinion, as it is really similar to how Image works. 😃

Inside the package you could handle this in several ways, the simplest being Image.resolveAssetSource(rootUrl).uri which doesn’t have external dependencies, but might have some trouble in release builds via this thread but I haven’t investigated deeper. A similar solution to expo-asset would be my safest bet. Also the documentation should include that users have to edit their metro.config.js and add the desired extension to resolver.assetExts in order to make this solution viable.

Thanks for the shout-out @ryantrem. I hadn’t logged an issue for my prior investigations because it was actually an issue with how React-Native bundles assets from outside the project folder. Loading the files into Babylon was working as I expected.

@f4z3k4s would you mind sharing a snippet of code on how you would expect the ImportMesh call to work inside the package? Are you talking about loading local assets like you would for an image? Like this:

SceneLoader.ImportMeshAsync(
  '',
  require('/assets/3d/tesla-high.glb`),
  '',
  scene
);

We don’t currently support loading local assets by just using the require('asset_path') syntax… but I think that would be a great improvement and is probably something many React-Native developers would expect.