Open jedahan opened 2 years ago
https://github.com/expo/expo-three/blob/master/src/loadAsync.ts#L55-L86
Do you know where I could find out how asset uris get built, and the differences in a prod build and expo go bundle? Ran into this issue with expo-three, which I think uses an old format of requires?
loadAsync
fails on guessing what format uri: 'assets_textures_globelightlandmassinvert'
should be, since there is no extension anymore. We are loading with require('../assets/textures/globe-light-land-mass-invert')
. The interesting thing is that there is a type: 'png' in the object. Maybe expo-three's loadAsync
should look for the type
key and work off of that?
And the error you will get if you use loadAsync
:
ReactNativeJS: { [Error: ExpoTHREE.loaderClassForExtension(): Unrecognized file type assets_textures_globelightlandmassinvert] line: 2969, column: 541, sourceURL: 'index.android.bundle' }
Perhaps you can try to change extension of .png to .xpng as stated in https://github.com/expo/expo-three/issues/185#issuecomment-732161813 then the texture shall load on production APK.
Also you can refer to my findings for loading 3d models with texture here: https://github.com/expo/expo-three/issues/151#issuecomment-904532776
Thank you for the comment and suggestion, I will try changing my app today to see if the fixes work.
Tentatively, it works! I am going to do more testing, but if it does, thank you so much @kyaroru !
This is roughly what we had to do:
// metro.config.js
const { getDefaultConfig } = require('@expo/metro-config')
const defaultConfig = getDefaultConfig(__dirname)
defaultConfig.resolver.assetExts.push('xpng')
module.exports = defaultConfig
// getEarth.tsx
import { loadTextureAsync } from 'expo-three'
import { Mesh, SphereGeometry, MeshPhongMaterial } from 'three'
export const getEarth = async (radius=100, resolution=128): Promise<Mesh> => {
const map = await loadTextureAsync({ asset: require('./assets/globe.xpng') })
return new Mesh(
new SphereGeometry(radius, resolution, resolution),
new MeshPhongMaterial({ map }),
)
}
// globe.tsx
import React from 'react'
import { GLView, ExpoWebGLRenderingContext } from 'expo-gl'
import { Renderer } from 'expo-three'
import { PerspectiveCamera, Scene, FogExp2, DirectionalLight } from 'three'
import { getEarth } from './getEarth.tsx'
export const Globe = (): React.ReactElement => {
// stop rendering when navigating away
let timeout; useEffect(() => () => clearTimeout(timeout), [])
const onContextCreate = async (gl: ExpoWebGLRenderingContext): Promise<void> => {
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl
const renderer = new Renderer({ gl })
renderer.setSize(width, height)
// camera
const aspect = width / height
const { fov, near, far } = { fov: 90, near: 0.1, far: 900 }
const camera = new PerspectiveCamera(fov, aspect, near, far)
const scene = new Scene()
scene.fog = new FogExp2(0xffffff, 0.001)
const earth = await getEarth()
scene.add(earth)
const spotlight = new DirectionalLight(0xffffff, 1.2)
spotlight.position.set(10, -10, 1)
camera.add(spotlight)
scene.add(camera)
// Setup an animation loop
const render = (time: number) => {
timeout = requestAnimationFrame(render)
renderer.render(scene, camera)
gl.endFrameEXP()
}
render(0)
}
return <GLView style={{ flex: 1 }} onContextCreate={onContextCreate} />
}
Maybe loadAsync
should be deprecated, or replaced with this hack...
glad to know that it is working! 😜
Yeah I owe ya a bottle of 🥃 or kombucha or something
Short update; still need this workaround in SDK 44
@keith-kurak is this something can be addressed for the next release? This issue breaks loadAsync/loadTextureAsync for loading textures when using production APKs. Thanks!
Only on production build of apks. Expo Go shows
https://
andfile://
schemes for uri/localUri.