expo/expo-three

View obj in App react native with expo

Closed this issue · 3 comments

Hi everyone,
I want to view 3d model in app react native by obj or fbx file
How to do it?

I using code

import { View as GraphicsView } from 'expo-graphics';
import ExpoTHREE, { THREE } from 'expo-three';
import React from 'react';
import {Text, View, TouchableOpacity} from 'react-native'

import ExpoGraphics from 'expo-graphics';


console.disableYellowBox = true;

export default class App extends React.Component {

  render() {
      return (
          <ExpoGraphics.View
            onContextCreate={this.onContextCreate}
            onRender={this.onRender}
          />
      )
  }
  onContextCreate = async ({
    gl,
    width,
    height,
    scale: pixelRatio,
  }) => {
    this.renderer = new ExpoTHREE.Renderer({ gl, pixelRatio, width, height });
    this.renderer.setClearColor(0x000000)
    this.renderer.capabilities.maxVertexUniforms = 52502;


    this.camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 1000);
    this.camera.position.set(0,6,12);
    this.camera.lookAt(0,0,0);

    this.setupScene();
    await this.loadModelsAsync();
  };

  setupScene = () => {
    // scene
    this.scene = new THREE.Scene();
    this.setupLights();
  };

  setupLights = () => {
    // lights
    const directionalLightA = new THREE.DirectionalLight(0xffffff);
    directionalLightA.position.set(1, 1, 1);
    this.scene.add(directionalLightA);

    const directionalLightB = new THREE.DirectionalLight(0xffeedd);
    directionalLightB.position.set(-1, -1, -1);
    this.scene.add(directionalLightB);

    const ambientLight = new THREE.AmbientLight(0x222222);
    this.scene.add(ambientLight);
  };

  loadModelsAsync = async () => {
    const model = {
      '3d.obj': require('./assets/chopper.obj'),
      '3d.mtl': require('./assets/chopper.mtl'),
    };

    const mesh = await ExpoTHREE.loadAsync(
      [model['3d.obj']],
      null,
      name => model[name],
    );

    ExpoTHREE.utils.scaleLongestSideToSize(mesh, 5);
    ExpoTHREE.utils.alignMesh(mesh, { x: 0.5 });

    this.scene.add(mesh);
    this.mesh = mesh;
  };

  onRender = delta => {
    this.mesh.rotation.y += 0.3 * delta;
    this.renderer.render(this.scene, this.camera);
  };
}

when using

const mesh = await ExpoTHREE.loadAsync(
      [model['3d.obj']],
      null,
      name => model[name],
    );

93835518_847840199062200_4858376789447147520_n

when

const mesh = await ExpoTHREE.loadAsync(
      [model['3d.obj'], model['3d.mtl']],
      null,
      name => model[name],
);

93721833_253757159137823_4724786925536280576_n

Why the colors cannot be displayed?
Helicopter

Please use triple back ticks followed by a coding language (```tsx) to format your code blocks in the future.

I imagine there are images involved in the model texture that the mtl file is referencing. Those images need to be passed in the callback:

const mesh = await ExpoTHREE.loadAsync(
      [model['3d.obj'], model['3d.mtl']],
      null,
      name => {
        // `name` must be a loaded image and already existing in the model object.
        return model[name]
      },
);

Unfortunately this API is really awkward to use but it's a limitation of the bundler React Native is using (Metro bundler).