I was looking for this answer for a couple of weeks, finally I've found a way to make it work.
Material loader is not resolving by itself the import of remote files (it does on web, not in mobile, maybe in the future it will). So, I'm creating material and assigning it images by hand.
Something like this:
import { TextureLoader } from 'expo-three';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
// useThree is used to get scene reference
import { useThree } from 'react-three-fiber';
const textureLoader = new TextureLoader();
const mapImage = textureLoader.load(require('path/to/image1.png'))
const normalMapImage = textureLoader.load(require('path/to/image2.png'))
Note that TextureLoader
from expo-three
can handle the file resource returned from require()
const loaderObj = new OBJLoader();
const loaderMtl = new MTLLoader();
export default props => {
const { scene } = useThree();
loaderMtl.load(
'https://url_to/material.mtl',
mtl => {
mtl.preload();
loaderObj.setMaterials(mtl);
loaderObj.load(
'https://url_to/model.obj',
obj => {
// simple logic for an obj with single child
obj.children[0].material.map = mapImage;
obj.children[0].material.normalMap = normalMapImage;
scene.add(obj)
}
)
}
)
return null;
}
This is my first successful attempt to render an obj with mtl including a map and a normal map, so since it works, we can keep updating the code for improvements.
image
attribute. Are you sure it shouldn't be.map
instead? – Marquizzo