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

LoadTextureAsync not working with standalone app #104

Open
Trancoso opened this issue May 30, 2019 · 15 comments
Open

LoadTextureAsync not working with standalone app #104

Trancoso opened this issue May 30, 2019 · 15 comments

Comments

@Trancoso
Copy link

Hi
I’m realizing a project where I have to realize a 3D earth with Expo-THREE but i would like to give a texture to my sphere . However, I only achieved this on development but with a standalone app (android) the texture doesn’t download. I have a black sphere. On IOS, everything goes well in development and with Testfligt app. I do like that to render my sphere :

const terre = require("../../../../assets/images/panorama.png")    
    scene = new THREE.Scene();
    const light = new THREE.DirectionalLight(new THREE.Color(0xffffff), 1);
    light.position.set(6, 6, 8);
    scene.add(light)
    camera = new THREE.PerspectiveCamera(
      75,
      gl.drawingBufferWidth / gl.drawingBufferHeight,
      0.1,
      1000
    );
    renderer = new ExpoTHREE.Renderer({ gl });
    renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);

    const texture = await ExpoTHREE.loadTextureAsync({asset: terre})
    const geometry = new THREE.SphereBufferGeometry(GLOBE_RADIUS, 128, 128);
    const material = await new THREE.MeshLambertMaterial({
      map: texture
    });
    const sphere = new THREE.Mesh(geometry, material);
    scene.add(sphere);
    camera.position.set(6, 6, 8);

I also tried to replace my local uri by a picture online but i had the same issue as before.

I also try to realize this issue :

but after tried this , the result was the same for the standalone app.

My config file :

App.json :
{
"expo": {
"name": "name",
"slug": "name-app",
"privacy": "public",
"sdkVersion": "32.0.0",
"platforms": [
"ios",
"android"
],
"version": "2.0.0",
"orientation": "portrait",
"icon": ./launcher.png",
"splash": {
"image": "./splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffdc00"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"/"
],
"android": {
"package": "org.
.***",
"versionCode": 23,
"googleServicesFile": "./google-services.json",
"permissions": [
"ACCESS_COARSE_LOCATION",
"ACCESS_FINE_LOCATION",
"CAMERA",
"READ_CONTACTS"
]
}
}
}

Mon Package.json :
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject"
},
"dependencies": {
"d3-geo": "^1.11.3",
"expo": "^32.0.0",
"expo-asset-utils": "^1.0.0",
"expo-face-detector": "^4.0.0",
"expo-graphics": "^1.0.3",
"expo-three": "^3.0.0-alpha.8",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"three": "^0.96.0"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0"
},
"private": true
}

Can you tell me what can I do ? Thanks a lot !

@Trancoso
Copy link
Author

Trancoso commented Jun 4, 2019

In prod with adb logcat i can see this error : "THREE.WebGLState exgl invalid pixel data argument for gl textImage2D()!". Could it be our problem ?

@bonbertr
Copy link

bonbertr commented Jun 5, 2019

Hello, I work with @Trancoso and was able to find a workaround for our problem. Using adb logcat with a production build and logging the texture returned by ExpoTHREE.loadAsync I noticed that the asset localUri started with asset://. Then using expo/expo#2693 (comment) to get a file:// uri for my asset, I overwrote the texture image localUri with the uri. So far it works fine.
Here is the code:

const uri =  await this.copyAssetToCacheAsync(require('../../../../assets/images/panorama.png'),'panorama.png');
  const texture = await ExpoTHREE.loadAsync(uri);
  texture.image.data.localUri = texture.image.data.uri;
  const material = new THREE.MeshBasicMaterial({
    map: texture
  });

  const geometry = new THREE.SphereBufferGeometry(GLOBE_RADIUS, 128, 128);
  const sphere = new THREE.Mesh(geometry, material);
  scene.add(sphere);

Where copyAssetToCacheAsync function is the one provided by adbl in the linked issue.

@danmaas
Copy link

danmaas commented Aug 21, 2019

Thanks @bonbertr for the work around!

After some more digging, I think the root cause could be here, the native C++ implementation of expo-gl:
https://github.com/expo/expo/blob/master/packages/expo-gl-cpp/cpp/UEXGL.cpp

The loadImage() function has a special case to handle Assets passed in the form of JavaScript objects with a .localUri property. However, it only handles the file:// prefix and fails to handle the asset:// prefix (which only appears for assets loaded in standalone Android builds).

@tauanbinato
Copy link

Hey everyone.. i was having a lot of trouble with expo-three when trying to load an .obj
i will post here what me and my colleges have done to work around this.
Every time that i tried to load an .obj using loadAsync or loadObjAsync the require method to load static assets always resolve to undefined.

The solution was create a metro.config.js in your root project folder adding assetExtensions like obj and mtl like this:

module.exports = {
	resolver: {
		assetExts: ["db", "mp3", "ttf", "obj", "png", "jpg", "mtl"]
	}
};

and then in your app.json point to the new file

"packagerOpts": {
			"config": "metro.config.js"
}

I'm posting this in case anyone pass trough the same hell

@pehagg
Copy link

pehagg commented May 13, 2022

@bonbertr 's workaround is not working anymore after upgrading from Expo 43 to 45. End up with a black textured object. Non-textured objects render just fine. I was able to fix this by skipping the local cache thing and loading the texture from the module resource, but this doesn't obviously work on Android in production builds. Anyone else bumped into this? I've now spent two workdays trying to find the root cause to no avail. My current hypothesis is that TextureLoader cannot load from local URIs anymore.

@CodyJasonBennett
Copy link

Perhaps try one of my polyfills via expo-asset:

This is what https://github.com/pmndrs/react-three-fiber uses ATM to unify loaders with web.

@pehagg
Copy link

pehagg commented May 26, 2022

Off-topic: we ended up ditching expo-three altogether. Too frustrated with all the issues we had every time Expo was updated. Was never able to fix the texture loading issue, which was the last nail in the coffin.

@danmaas
Copy link

danmaas commented May 26, 2022

I know the feeling XD. Out of curiosity, are you still using React Native at all, and if so with what graphics API? Or did you go 100% native?

@pehagg
Copy link

pehagg commented May 27, 2022

I know the feeling XD. Out of curiosity, are you still using React Native at all, and if so with what graphics API? Or did you go 100% native?

We continue to use React Native. We just replaced the 3D content views with regular 2D views. The 3D views didn't sit well with the rest of the app's look and feel anyway.

@ssdenis00
Copy link

ssdenis00 commented Sep 15, 2022

you need to change the file resolution. For example "test1.png" to "test1.xpng" or "test2.jpg " on "test2.xjpg".

const texture = await ExpoTHREE.loadTextureAsync({asset: require('../../../../assets/images/panorama.xpng')});
const material = new THREE.MeshBasicMaterial({
map: texture
});

const geometry = new THREE.SphereBufferGeometry(GLOBE_RADIUS, 128, 128);
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);

work for me
sdk44
react-native 0.64.0

@DominicBartel
Copy link

Has anyone seen success on this workaround recently? I'm stuck on my android build, IOS works fine.

"expo": "^46.0.0",
"expo-asset": "^8.7.0",
 "expo-file-system": "^15.1.1",
 "expo-font": "~10.2.0",
 "expo-gl": "~11.4.0",
 "expo-three": "^7.0.0",
 "react": "18.0.0",
 "react-dom": "18.0.0",
 "react-native": "0.69.6",
 "react-native-fs": "^2.20.0",
 "react-native-web": "~0.18.7",
 "three": "0.124.0",

Using the workaround @bonbertr mentioned I hit an issue during the ExpoTHREE.loadAsync call
Error: Expected URL scheme 'http' or 'https' but was 'file'

I attempted downgrading three.js in hopes the loader lived there, but like @pehagg said it looks like the textureLoader is living in expo.

Any advice? I'm about three days in.

@obasille
Copy link

@DominicBartel you can try this:

const asset = Asset.fromURI(localPath);
asset.localUri = localPath;
const texture = await ExpoTHREE.loadAsync(asset);

@phantom-factotum
Copy link

I was having an issue where the model wouldnt load because "Expected URL scheme 'http' or 'https' but was 'file'". When I looked at the asset, I noticed that the localUri url scheme was file, but uri followed the http url scheme. Switching to that allowed me to load the model. There's probably a huge downside to this, but if you want the model to load on Android, there's this

@uakhundz
Copy link

uakhundz commented Mar 4, 2023

asset.localUri = localPath;

Doing this gave me the error: TypeError: Cannot read property 'elements' of undefined, js engine: hermes

Struggling so much with this bug

@earonesty
Copy link

in my case it's not a local path...

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