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

uri/localUri have no scheme on production apks #225

Open
jedahan opened this issue Aug 13, 2021 · 10 comments
Open

uri/localUri have no scheme on production apks #225

jedahan opened this issue Aug 13, 2021 · 10 comments

Comments

@jedahan
Copy link

jedahan commented Aug 13, 2021

Only on production build of apks. Expo Go shows https:// and file:// schemes for uri/localUri.

await new TextureLoader().load(
  require('../../assets/textures/globe-light-landmass-invert.png'),
  (texture) => void console.log({texture}),
  undefined,
  (error) => void console.error(error)
)
{ texture: 
   { uuid: '03552703-2025-4D1B-837E-AF99C2FB078F',
     name: '',
     image: 
      { data: 
         { hash: '73d4f645e59fdb0a189f747dc91001c6',
           localUri: 'assets_textures_globelightlandmassinvert',
           width: 2000,
           height: 1000,
           downloading: false,
           downloaded: true,
           _downloadCallbacks: [],
           name: 'globe-light-landmass-invert',
           type: 'png',
           uri: 'assets_textures_globelightlandmassinvert' },
    }
   }
}
@jedahan
Copy link
Author

jedahan commented Aug 13, 2021

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?

@jedahan
Copy link
Author

jedahan commented Aug 13, 2021

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' }

@kyaroru
Copy link

kyaroru commented Aug 24, 2021

Perhaps you can try to change extension of .png to .xpng as stated in #185 (comment) then the texture shall load on production APK.

Also you can refer to my findings for loading 3d models with texture here: #151 (comment)

@jedahan
Copy link
Author

jedahan commented Aug 24, 2021

Thank you for the comment and suggestion, I will try changing my app today to see if the fixes work.

@jedahan
Copy link
Author

jedahan commented Aug 24, 2021

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} />
}

@jedahan
Copy link
Author

jedahan commented Aug 24, 2021

Maybe loadAsync should be deprecated, or replaced with this hack...

@kyaroru
Copy link

kyaroru commented Aug 24, 2021

glad to know that it is working! 😜

@jedahan
Copy link
Author

jedahan commented Aug 24, 2021

Yeah I owe ya a bottle of 🥃 or kombucha or something

@jedahan
Copy link
Author

jedahan commented Jan 14, 2022

Short update; still need this workaround in SDK 44

@obasille
Copy link

obasille commented Jan 17, 2023

@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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants