expo / expo-three

Utilities for using THREE.js on Expo
MIT License
750 stars 92 forks source link

loadAsync -> THREE.Loader #171

Open drcmda opened 4 years ago

drcmda commented 4 years ago

Would it be possible for Expo to support the THREE.Loader signature like all other loaders?

class ExpoLoader {
  load (url: string, onLoad: function, onProgress: function, onError: function) {
    // ..
    // async fetching, processing, etc
    // ..
    onLoad(asset)
new ExpoLoader().load(url, data => console.log(data))

If that were the case react-three-fiber users could have useLoader and suspense:

function Model(url) {
  const { scene } = useLoader(ExpoLoader, url)
  return <primitve object={scene} />
}

<Suspense fallback={<SomethingElseWhileLoading />}>
  <Model url="/model.gltf" />
</Suspense>

As well as declarative GLTF: https://github.com/react-spring/gltfjsx this one especially is a pitty and i get lots of requests because people just expect it to work, which it could in theory if loadAsync is a loader. Traversing and mutating assets would be a thing of the past.

EvanBacon commented 4 years ago

I'll investigate further

EvanBacon commented 4 years ago

I've updated the docs a bit to reflect how Expo + Three.js works in regards to asset loading. I'm not sure what an ExpoLoader would look like. All loading utilities provided by this package are hacks to workaround how Metro bundler loads assets.

I'm going to mostly be deprecating methods in favor of loading the local URI and passing it to the loader as-is.

I think something that could improve this could be a native API like a service worker that caches assets from the server, then the bundler would simply transform asset requires into URLs. Of course it would also need to handle the case of local asset files from other origins like file:// and asset-library://.

I suppose for now something that could improve the holistic workflow would be a hook in expo-asset that resolves the local sandboxed URI asynchronously.

Another approach could be to add a .native or .expo file to react-three-fiber which delegates loading to expo-asset before invoking the three.js loader.

I'd love to hear your thoughts.

drcmda commented 4 years ago

THREE.Loader is just a class with a load function that receives an argument and returns the assets, when they are ready, as a callback.

class ExpoLoader extends THREE.Loader {
  load(url, onLoad, onProgress, onError) {
    ExpoTHREE.loadAsync(url, onProgress).then(onLoad).catch(onError)
  }
}

the metro hacks would still be needed. but now you could use suspense in r3f. and i think plain three users will also have an easier time because they're used to loaders functioning like that.

drcmda commented 4 years ago

Another approach could be to add a .native or .expo file to react-three-fiber which delegates loading to expo-asset before invoking the three.js loader.

not sure what this means, im still a beginner when it comes to RN, but i would certainly merge everything that helps in the process

santiagofm commented 4 years ago

i think he means defining a native-specific extension—r3f already does this with the canvas implementation— to resolve the actual url of the asset before proceeding with loading it.

I’d love to help if you need any!

drcmda commented 4 years ago

sure, could need all the help i can get!