-
Notifications
You must be signed in to change notification settings - Fork 92
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
loadAsync not working with FBX [Android] #151
Comments
Hi ! Thanks |
@enzopoeta I encourtered the same issue. After checking source code, I find that expo use Here is the source code diff, hope this can temporary help you. Also wait for expo give us the final solution. |
@XHMM This worked for me as well! Should we create a PR @EvanBacon ? Thanks :) |
The @XHMM fix above does work for local assets, but remote URLs (OBJ or FBX) are failing with
Debugging and will update here if I find a fix. Edit: The following is what the response from resolveAsset looks like for a static asset.
Notice the uri is
So extracting the |
Finally figured it out. The issue comes from if (Platform.OS === 'web') {
return await new Promise((resolve, reject) => loader.load(uri, resolve, () => { }, reject));
}
return loadFileContentsAsync(loader, uri, 'loadObjAsync'); Hence, the else if (type.match(/\.fbx$/i)) {
// const arrayBuffer = await loadArrayBufferAsync({uri: url, onProgress});
const base64 = await FileSystem.readAsStringAsync(url, {
encoding: FileSystem.EncodingType.Base64,
});
const arrayBuffer = decode(base64);
const FBXLoader = loaderClassForExtension('fbx');
const loader = new FBXLoader();
return loader.parse(arrayBuffer, onAssetRequested);
} To my testing this works on iOS and Android, remote and local files. It allows you to use |
Same for glTF file loader, I made a fix, maybe it can help |
Hey I found another workaround not using expo-three loader and I started to use three.js GTLFLoader
|
Hi @giorgioma |
@XHMM the diff you provided is not valid anymore. Could you show where you changed the code? |
stuck on this issue as well, hopefully can patch this somehow... |
I am facing this issue for .obj file too in android. my code is given below. Please help me to solve this
|
After going through so many googling & github issues or even three.js forum (from 0 exp in 3d rendering few weeks back until today), I'm finally able to load these 3 types of models: To learn three.js, I created https://github.com/kyaroru/ShibaThree & https://github.com/kyaroru/ReactShibaThree and finally trying out on mobile app using Not until today! Argh! So I'm going to share my findings for the newbies out there who are just like me (this might not be an official solution but it just works) My "base64-arraybuffer": "^1.0.1", // this is needed at the end! (for FBX and GLTF)
"expo-gl": "^10.4.2",
"expo-gl-cpp": "^10.4.1",
"expo-three": "^5.7.0",
"react-native-unimodules": "^0.14.6",
"three": "^0.131.2" Using eg. import import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; And load using const loaderFbx = new FBXLoader();
const loaderObj = new OBJLoader();
const loaderGlb = new GLTFLoader();
const model = Asset.fromModule(require('../models/bear/model.obj'));
await model.downloadAsync();
const loader = loaderObj;
loader.load(
model.uri || '', // .uri / .localUri will not work in release mode on android!
result => { scene.add(model) },
onLoad => {},
onError => {},
); The above works fine on iOS (even in release mode) but not on android release mode (the APK). Then I tried with import {loadObjAsync} from 'expo-three';
const obj = await loadObjAsync({
asset: require('../models/bear/model.obj')
}); But import {loadObjAsync} from 'expo-three';
const obj = await loadObjAsync({
asset: require('../models/bear/model.obj'),
assetMtl: require('../models/bear/material.mtl')
}); Then, I tried to look for texture issues & I found this => #185 (comment) (What he explained just strike me in the head.. hmmm) So I renamed all my textures image file extension to prefix with 'x', and it became : Take note also we have to update module.exports = {
...
resolver: {
assetExts: [
...,
'xpng',
'xjpg',
'xjpeg',
],
},
}; Then I can finally load import {loadObjAsync, loadTextureAsync} from 'expo-three';
const texture = await loadTextureAsync({
asset: require('../models/bear/textures.xpng'),
});
const obj = await loadObjAsync({
asset: require('../models/bear/model.obj')
});
// to map texture to model (in case some newbie like me doesn't know how ><)
obj.traverse(function(object) {
if (object instanceof THREE.Mesh) {
object.material.map = texture;
}
});
scene.add(obj); OBJ is down, how about FBX & GLTF? To know how things work, I look into I found out it was actually calling So I attempted to do similar approach for FBX and GLTF models after referring to #151 (comment) First, install
Then. In wherever file that you wanted to load fbx or gltf model, add the following codes: (of course we can also fork import { loadObjAsync, loadTextureAsync } from 'expo-three';
import { resolveAsync } from 'expo-asset-utils';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { FileSystem } from 'react-native-unimodules';
import { decode } from 'base64-arraybuffer';
// this was actually copied from node_modules\expo-three\build\loaders\loadModelsAsync.js
async function loadFileAsync({ asset, funcName }) {
if (!asset) {
throw new Error(`ExpoTHREE.${funcName}: Cannot parse a null asset`);
}
return (await resolveAsync(asset)).localUri ?? null;
}
// newly added method
export async function loadFbxAsync({ asset, onAssetRequested }) {
const uri = await loadFileAsync({
asset,
funcName: 'loadFbxAsync',
});
if (!uri) return;
const base64 = await FileSystem.readAsStringAsync(uri, {
encoding: FileSystem.EncodingType.Base64,
});
const arrayBuffer = decode(base64);
const loader = new FBXLoader();
return loader.parse(arrayBuffer, onAssetRequested);
}
// newly added method
export async function loadGLTFAsync({ asset, onAssetRequested }) {
const uri = await loadFileAsync({
asset,
funcName: 'loadGLTFAsync',
});
if (!uri) return;
const base64 = await FileSystem.readAsStringAsync(uri, {
encoding: FileSystem.EncodingType.Base64,
});
const arrayBuffer = decode(base64);
const loader = new GLTFLoader();
return new Promise((resolve, reject) => {
loader.parse(
arrayBuffer,
onAssetRequested,
result => {
resolve(result);
},
err => {
reject(err);
},
);
});
} And that's all! We can now load OBJ, FBX, GLTF models proudly inside Barebone RN app!
For more info, can refer to my gist:
or clone this example app that I created: Programmer life is tough.. 😉 |
@kyaroru thank you for the example project! |
@kyaroru Thank you for your example. |
Hey @kyaroru, I also didn't know how to load To solve it (hack it), I converted my {
"asset": { "generator": "", "version": "2.0"},
"scene": 0,
// other props...
"buffers": [
{
"uri": "data:application/octet-stream;base64,yC9gQ2PFtkKT2BPC..."
},
{
"uri": "data:application/octet-stream;base64,yC9gQ2PFtkKT2BPC..."
}
// more uri...
]
} Thank you very much for your solution, it was very helpful 🚀 |
How to consume this functions ? |
This is not working anymore |
I like this idea so I tried it, but with ~25MB in textures for my moddel I seem to have run into a GLTFLoader bug where it can't load such a large uri: |
Hi @sadevn & anyone who need this, I have updated the example using Expo Latest SDK (v51) at https://github.com/kyaroru/RNExpoThree & renamed the old one to https://github.com/kyaroru/RNExpoThreeOld Hope it helps those who are struggling a lot! Btw, it's been 3 years! Life has changed but passion never dies! |
Hello! I'm trying to render a FBX file on Android but am running into an error. It renders an OBJ file fine on Android and the OBJ and FBX fine on iOS. I think the issue is related to #85 and #93 . Same issue as here. Is there any workaround? I've copied the offending error message below. Thanks.
Edit: I traced the issue to line 85 of
loadModelsAsync.js
, this promise always gets rejected on AndroidEdit 2: I've spent a few hours on this with no luck. GLView does not work with remote debugging which makes this especially difficult. Any suggestions appreciated.
NOTE: This works fine in IOS only having issue with Android.
The text was updated successfully, but these errors were encountered: