Как использовать .obj файлы в expo three.js без модуля AR? [React Native Expo] - PullRequest
0 голосов
/ 22 апреля 2019

Моя проблема в том, как я могу использовать файлы .mtl и .obj с expo three.js, но я не хочу использовать AR, я только хочу использовать простой холст / вид с вращающимся объектом.Этот код - то, что я хочу, но с моим файлом obj, а не для создания куба.

 import { View as GraphicsView } from 'expo-graphics';
 import ExpoTHREE, { THREE } from 'expo-three';
 import React from 'react';
 import Assets from './Assets.js';
 import ThreeStage from './ThreeStage.js';
 export default class App extends React.Component {
   componentWillMount() {
     THREE.suppressExpoWarnings();
   }

   render() {
     return (
      <GraphicsView
        onContextCreate={this.onContextCreate}
         onRender={this.onRender}
       />
     );
   }

   async setupModels() {
     await super.setupModels();

     const model = Assets.models.obj.ninja;

     const SCALE = 2.436143; // from original model
     const BIAS = -0.428408; // from original model


     const object = await ExpoTHREE.loadObjAsync({
       asset: require('ninja.obj'),
     });

     const materialStandard = new THREE.MeshStandardMaterial({
       color: 0xffffff,
       metalness: 0.5,
       roughness: 0.6,
       displacementScale: SCALE,
       displacementBias: BIAS,
      normalScale: new THREE.Vector2(1, -1),
       //flatShading: true,
       side: THREE.DoubleSide,
     });

     const geometry = object.children[0].geometry;
    geometry.attributes.uv2 = geometry.attributes.uv;
     geometry.center();
     const mesh = new THREE.Mesh(geometry, materialStandard);
     mesh.scale.multiplyScalar(0.25);

    ExpoTHREE.utils.scaleLongestSideToSize(mesh, 1);
     ExpoTHREE.utils.alignMesh(mesh, { y: 1 });
     this.scene.add(mesh);
     this.mesh = mesh;
   }

   onRender(delta) {
     super.onRender(delta);
     this.mesh.rotation.y += 0.5 * delta;
   }

 }

Мой файл assets.js, который содержит путь к моему 3D-модалу в .obj

export default {

    obj: {


            "museu.obj": require('../Conteudos_AV/museu1.obj'),

    }
};

И мой файл threeStage.js, который содержится в импорте 3DModal.js

import ExpoTHREE, { THREE } from 'expo-three';

class ThreeStage {
  constructor() {
    this.onRender = this.onRender.bind(this);
    this.setupControls = this.setupControls.bind(this);
    this.onResize = this.onResize.bind(this);
    this.setupCamera = this.setupCamera.bind(this);
    this.setupScene = this.setupScene.bind(this);
  }
  onContextCreate = async ({
    gl,
    canvas,
    width,
    height,
    scale: pixelRatio,
  }) => {
    this.gl = gl;
    this.canvas = canvas;
    this.width = width;
    this.height = height;
    this.pixelRatio = pixelRatio;
    await this.setupAsync();
  };

  setupAsync = async () => {
    const { gl, canvas, width, height, pixelRatio } = this;
    await this.setupRenderer({ gl, canvas, width, height, pixelRatio });
    await this.setupScene();
    await this.setupCamera({ width, height });
    await this.setupLights();
    await this.setupModels();
    await this.setupControls();
  };

  setupControls() {
    new THREE.OrbitControls(this.camera);
  }

  setupRenderer = props => {
    this.renderer = new ExpoTHREE.Renderer(props);
    this.renderer.capabilities.maxVertexUniforms = 52502;
  };

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

  setupScene() {
    this.scene = new THREE.Scene();

    this.scene.background = new THREE.Color(0x999999);
    this.scene.fog = new THREE.FogExp2(0xcccccc, 0.002);

    this.scene.add(new THREE.GridHelper(50, 50, 0xffffff, 0x555555));
  }

  setupLights = () => {
    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);
  };

  async setupModels() {}

  onResize({ width, height, scale }) {
    this.camera.aspect = width / height;
    this.camera.updateProjectionMatrix();
    this.renderer.setPixelRatio(scale);
    this.renderer.setSize(width, height);
    this.width = width;
    this.height = height;
    this.pixelRatio = scale;
  }

  onRender(delta) {
    this.renderer.render(this.scene, this.camera);
  }
}

export default ThreeStage;

1 Ответ

1 голос
/ 24 мая 2019

Похоже, что предоставленный код создает класс ThreeStage, который импортируется, но никогда не используется классом, содержащим Expo GraphicsView.

В примерах, представленных в репозитории для выставки-3, используется немного эзотерикиструктура, поскольку каждый из них предназначен для обслуживания через реагирующее навигационное приложение с централизованной библиотекой ресурсов и абстрактными компонентами.Это очень много для простого приложения, которое просто пытается отобразить модель на экране.

import React from 'react';
import ExpoTHREE, { THREE } from 'expo-three';
import { GraphicsView } from 'expo-graphics';

export default class App extends React.Component {

  componentDidMount() {
    THREE.suppressExpoWarnings();
  }

  render() {
    return (
      <GraphicsView
        onContextCreate={this.onContextCreate}
        onRender={this.onRender}
        onResize={this.onResize}
      />
    );
  }

  // When our context is built we can start coding 3D things.
  onContextCreate = async ({ gl, pixelRatio, width, height }) => {

    // Create a 3D renderer
    this.renderer = new ExpoTHREE.Renderer({
      gl,
      pixelRatio,
      width,
      height,
    });

    // We will add all of our meshes to this scene.
    this.scene = new THREE.Scene();

    this.scene.background = new THREE.Color(0xbebebe)

    this.camera = new THREE.PerspectiveCamera(45, width/height, 1, 1000)

    this.camera.position.set(3, 3, 3);

    this.camera.lookAt(0, 0, 0);

    this.scene.add(new THREE.AmbientLight(0xffffff));

    await this.loadModel();
  };

  loadModel = async () => {
    const obj = {
      "museu.obj": require('../Conteudos_AV/museu1.obj')
    }

    const model = await ExpoTHREE.loadAsync(
      obj['museu.obj'],
      null,
      obj
    );

    // this ensures the model will be small enough to be viewed properly
    ExpoTHREE.utils.scaleLongestSideToSize(model, 1);

    this.scene.add(model)

  };


  // When the phone rotates, or the view changes size, this method will be called.
  onResize = ({ x, y, scale, width, height }) => {
    // Let's stop the function if we haven't setup our scene yet
    if (!this.renderer) {
      return;
    }
    this.camera.aspect = width / height;
    this.camera.updateProjectionMatrix();
    this.renderer.setPixelRatio(scale);
    this.renderer.setSize(width, height);
  };

  // Called every frame.
  onRender = delta => {


    // Finally render the scene with the Camera
    this.renderer.render(this.scene, this.camera);
  };
}

Я адаптировал этот код из одного из примеров легких закусок Эвана, за которым немного легче следить, так каку них нет больших накладных расходов всего примера приложения.Вы можете найти больше на его странице с закусками: https://expo.io/snacks/@bacon.

Этот код должен отображать ваш объектный файл, но может столкнуться с проблемами, если ваш .obj использует дополнительные файлы материалов или текстур.Если это так, вам нужно добавить их в функцию loadModel следующим образом:

    const obj = {
      "museu.obj": require('../Conteudos_AV/museu1.obj'),
      "museu.mtl": require('../Conteudos_AV/museu1.mtl'),
      "museu.png": require('../Conteudos_AV/museu1.png'),
    }

    const model = await ExpoTHREE.loadAsync(
      [obj['museu.obj'], obj['museu.mtl']],
      null,
      obj
    );

Я бы порекомендовал взглянуть на закуски экспо, которые используют экспо-три, а не пример приложения, когдаВы начинаете, поскольку может быть немного затруднительно работать со всеми тонкостями примера.

У меня нет устройства, пригодного в данный момент для тестирования, но дайте мне знать, еслиу вас есть какие-либо проблемы с приведенным выше кодом, и я могу устранить неполадки, когда я снова рядом с телефоном и ноутбуком.

...