I am trying to use three js and expo-three to load 3D models in mobile apps. But every time I run a particular loader from " three/examples/jsm/loaders/ … " I get an error
[TypeError: undefined is not an object (evaluating ‘response.body.getReader’)]
and the 3d model fails to load. I have tried GLTFLoader ( import { GLTFLoader } from “three/examples/jsm/loaders/GLTFLoader” ) and also OBJLoader ( import { OBJLoader } from ‘three/examples/jsm/loaders/OBJLoader’) and others but all giving the same " TypeError: undefined is not an object " error.
Platforms tested on:
Mobile - iPhone
OS: iOS, MacOS
Three.js version 0.135.0
expo-three version 6.0.1
expo-gl version 11.0.3
expo version 43.0.2
react version 17.0.1
react-native version 0.64.3
the error:
Heres the App.js code:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { PixelRatio } from 'react-native';
import ExpoTHREE, { Renderer, THREE } from 'expo-three';
import { GLView } from 'expo-gl';
import { ExpoWebGLRenderingContext } from 'expo-gl';
import { PerspectiveCamera, AmbientLight, Scene, MeshPhongMaterial, MeshBasicMaterial } from 'three';
import { TextureLoader } from 'expo-three';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader';
import { Asset } from 'expo-asset';
import RNFetchBlob from 'rn-fetch-blob';
import * as RNFS from 'react-native-fs';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
import { decode, encode } from 'base-64';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
export default function App() {
return (
<View style={styles.container}>
{/* <Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" /> */}
<GLView style={{ width: 500, height: 500 }} onContextCreate={onContextCreat} />
</View>
);
}
const onContextCreat = async (gl) => {
const { drawingBufferWidth, drawingBufferHeight } = gl;
const scale = PixelRatio.get()
// Create a WebGLRenderer without a DOM element
const renderer = new Renderer({ gl });
renderer.setSize(drawingBufferWidth / scale, drawingBufferHeight / scale);
renderer.capabilities.maxVertexUniforms = 52502;
renderer.setPixelRatio(scale);
renderer.setClearColor(0x0c000);
const scene = new Scene();
const camera = new PerspectiveCamera(75, drawingBufferWidth / drawingBufferHeight, 0.1, 1000);
camera.position.set(0, 2, 5);
const ambientLight = new AmbientLight(0x101010);
scene.add(ambientLight);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const imageURI = Asset.fromModule(require('./assets/icon.png')).uri;
const material = new THREE.MeshBasicMaterial({
map: new TextureLoader().load(imageURI),
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
const asset = Asset.fromModule(
require("./assets/v_knife_karam/v_knife_karam.gltf")
);
await asset.downloadAsync();
const loader = new GLTFLoader();
loader.load(
asset.uri,
(gltf) => {
// model = gltf.scene;
scene.add(gltf.scene);
},
(xhr) => {
console.log(`${(xhr.loaded / xhr.total) * 100}% loaded`);
},
(error) => {
console.error("An error happened", error);
}
);
// const assets = Asset.fromModule(require('./assets/IronMan.obj'));
// await assets.downloadAsync();
// //instantiate a loader
// const loader = new OBJLoader();
// loader.loadAsync(assets.uri,function ( xhr ) {
// console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
// }).then((object)=> {
// console.log(`async load of 3d obj: ${object}`)
// }).catch((err) =>{
// console.log(`the async load object error: ${err}`)
// })
renderer.render(scene, camera)
gl.endFrameEXP()
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
</p>