2

In my react app, I am trying to make a view page which shows 3d-mesh exported from pix4d. This mesh consists of three types of files, (.obj, .mtl, .jpg) pix4d.com.

I am new, with react-three-fiber, which I suppose is best way to achieve my solution to my problem.

Below is whole code of react component used to load and render 3D-Model.

code

Thanks in Advance!

I want to understand how to attach texture & material to my obj rendered model.

Ajit T Stephen
  • 431
  • 1
  • 8
  • 21
  • I've never used React-Three-fiber before, but it looks like you're creating a mesh with an `image` attribute. Are you sure it shouldn't be [`.map`](https://threejs.org/docs/#api/en/materials/MeshStandardMaterial.map) instead? – M - Apr 07 '20 at 01:08
  • Yeah tried all Mesh Materials: No changes in results I see. meshStandardMaterial has alphaMap, map, normalMap, displacementMap, tried all :( – Ajit T Stephen Apr 07 '20 at 06:35
  • never seen that before, to my knowledge that property does not exist in threejs https://threejs.org/docs/index.html#api/en/objects/Mesh ---> this will do nothing because it's missing attach="material" – hpalu Apr 07 '20 at 08:39
  • @hpalu can you give full example? Did somebody have a solution? – otto Apr 29 '20 at 14:37
  • @wwwwwwwwwwww I have to yet convert this to RTF solution, this task got moved to my backlog at the moment. Last I worked, I was able to load my OBJ in here. So all you need to worry is to use .obj & .mtl files, loaded from RTF, but JPG file should be at that place as it is referenced from .mtl. use this: https://threejsfundamentals.org/threejs/lessons/threejs-load-obj.html – Ajit T Stephen Apr 29 '20 at 16:01
  • what do you mean loaded with RTF? i have loaded the .obj with useLoader from react three fiber but I dont know how to add texture – otto Apr 29 '20 at 17:50
  • here's one https://codesandbox.io/s/three-fiber-useloader-rohv5 – hpalu Apr 30 '20 at 20:59

2 Answers2

0

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.

Cosmitar
  • 984
  • 12
  • 18
0

Another way to load model with texture is by specifying the path where your texture has been stored. In one case, mtl + obj + texture files are stored in your react project's directory 'public/models/'. So you can specify the path by calling setPath() function prior loading your material or object file and it should load your texture on the material. You may also want to make sure that in ./mtl file the texture name is correct. It should be called following by map_Kd in .mtl file.

const Model = () => {
  const materialLoader = new MTLLoader().setPath('./model/').load(MaterialFile);
  const objLoader = new OBJLoader().setMaterials(materialLoader).load(OojectFile);
  return <primitive object={objLoader} />;
};