繁体   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