簡體   English   中英

沒有AR模塊的expo three.js中的.obj文件如何使用? [React Native Expo]

[英]How to use .obj files in expo three.js without AR module? [React Native Expo]

我的問題是關於如何在expo three.js中使用.mtl和.obj文件,但是我不想使用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文件,其中包含.obj中我的3D模態的路徑

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;

看起來提供的代碼創建了一個ThreeStage類,該類已導入,但從未被包含Expo GraphicsView的類使用。

在倉庫3中,為世博會提供的示例使用了一些深奧的結構,因為它們分別是通過具有集中式資產庫和抽象組件的react-navigation應用程序提供的。 對於僅嘗試在屏幕上顯示模型的簡單應用程序來說,這是很多額外的。

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);
  };
}

我從Evan的博覽會零食示例中改編了此代碼,由於它們在整個示例應用程序中沒有太多開銷,因此易於遵循。 您可以在他的博覽會零食頁面上找到更多信息: 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
    );

我建議您在開始時先看看使用expo-3而不是示例應用程序的expo快餐,因為處理示例中的所有復雜內容可能有點兒困惑。

我目前沒有方便使用的設備進行測試,但是請告訴我上述代碼是否有問題,當我回到手機和筆記本電腦旁邊時,我可以進行故障排除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM