首页 > 解决方案 > 使用 Expo-three 加载 .obj 文件?

问题描述

我正在尝试将 .obj 文件插入使用 Expo 构建的 React Native 应用程序中。

从我发现成功运行的示例中,其中大多数似乎依赖于在渲染中构建球体或立方体。我还没有找到一个成功渲染本地文件的好例子,特别是.obj。

我正在使用 expo-three 文档,该文档描述了使用 obj 文件进行渲染,但没有工作示例。

这是我到目前为止所拥有的,它没有产生任何渲染的对象。但是想知道我是否在正确的轨道上,以及我缺少什么来渲染对象。

以下是当前文件代码。

import { Renderer, TextureLoader } from 'expo-three';
import * as React from 'react';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import {
  AmbientLight,
  Fog,
  GridHelper,
  PerspectiveCamera,
  PointLight,
  Scene,
  SpotLight,
} from 'three';
import { Asset } from 'expo-asset';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';

export default function ThreeDPhytosaur() {

  return (
    <GLView
      style={{ flex: 1 }}
      onContextCreate={async (gl) => {
        const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
        const sceneColor = 0x6ad6f0;

        const renderer = new Renderer({ gl });
        renderer.setSize(width, height);
        renderer.setClearColor(sceneColor);

        const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
        camera.position.set(2, 5, 5);

        const scene = new Scene();
        scene.fog = new Fog(sceneColor, 1, 10000);
        scene.add(new GridHelper(10, 10));

        const ambientLight = new AmbientLight(0x101010);
        scene.add(ambientLight);

        const pointLight = new PointLight(0xffffff, 2, 1000, 1);
        pointLight.position.set(0, 200, 200);
        scene.add(pointLight);

        const spotLight = new SpotLight(0xffffff, 0.5);
        spotLight.position.set(0, 500, 100);
        spotLight.lookAt(scene.position);
        scene.add(spotLight);

        const asset = Asset.fromModule(model['phytosaur']);
        await asset.downloadAsync();


        const objectLoader = new OBJLoader();


        const object = await objectLoader.loadAsync(asset.uri);

        object.scale.set(0.025, 0.025, 0.025);
        scene.add(object);
        camera.lookAt(object.position);

        const render = () => {
          timeout = requestAnimationFrame(render);
          renderer.render(scene, camera);
          gl.endFrameEXP();
        };
        render();
      }}
    />
  );
}

const model = {
  'phytosaur': require('../assets/phytosaur.obj'),
};

非常感谢!

标签: react-nativethree.jsexpo

解决方案


这是我渲染 obj 文件的代码。根据找到的其他一些示例更改了原始文件的结构。

但这可能对其他人有帮助!

import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { Asset } from 'expo-asset';
import { Renderer} from 'expo-three';
import * as React from 'react';
import {
  AmbientLight,
  Fog,
  PerspectiveCamera,
  PointLight,
  Scene,
  SpotLight,
} from 'three';

export default function ThreeDTwo() {

  let timeout;

  React.useEffect(() => {
    // Clear the animation loop when the component unmounts
    return () => clearTimeout(timeout);
  }, []);


  return (
    <GLView
      style={{ flex: 1 }}
      onContextCreate={async (gl) => {
        const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
        const sceneColor = 668096;

        // Create a WebGLRenderer without a DOM element
        const renderer = new Renderer({ gl });
        renderer.setSize(width, height);
        renderer.setClearColor(0x668096);

        const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
        camera.position.set(2, 5, 5);

        const scene = new Scene();
        scene.fog = new Fog(sceneColor, 1, 10000);

        const ambientLight = new AmbientLight(0x101010);
        scene.add(ambientLight);

        const pointLight = new PointLight(0xffffff, 2, 1000, 1);
        pointLight.position.set(0, 200, 200);
        scene.add(pointLight);

        const spotLight = new SpotLight(0xffffff, 0.5);
        spotLight.position.set(0, 500, 100);
        spotLight.lookAt(scene.position);
        scene.add(spotLight);
    
        const asset = Asset.fromModule(require("../assets/phytosaur_without_mtl.obj"));
        await asset.downloadAsync();

        // instantiate a loader
        const loader = new OBJLoader();

        // load a resource
        loader.load(
            // resource URL
            asset.localUri,
            // called when resource is loaded
            function ( object ) {
                object.scale.set(0.065, 0.065, 0.065)
                scene.add( object );
                camera.lookAt(object.position)
            //rotate my obj file
                function rotateObject(object, degreeX=0, degreeY=0, degreeZ=0) {
                    object.rotateX(THREE.Math.degToRad(degreeX));
                    object.rotateY(THREE.Math.degToRad(degreeY));
                    object.rotateZ(THREE.Math.degToRad(degreeZ));
                 }
                 
                 // usage:
                 rotateObject(object, 0, 0, 70);

                //animate rotation
                function update() {
                    object.rotation.x += 0.015
                }
                const render = () => {
                    timeout = requestAnimationFrame(render);
                    update();
                    renderer.render(scene, camera);
                    gl.endFrameEXP();
                  };
                render();
            },
           
            // called when loading is in progresses
            function ( xhr ) {

                console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

            },
            // called when loading has errors
            function ( error ) {

                console.log( error );

            }
        
        );   
      }}
    />
  );  
}

推荐阅读