尝试在 React Native 中使用 Three.js 加载 obj 和 mtl 文件

Adi*_*tya 5 three.js react-native

主要目标:将从 Maya 导出的动画模型加载到 React Native 应用程序中 导出的文件: obj、mtl 和 png 文件

我已经在我的 React Native 项目中设置了https://github.com/react-community/react-native-webgl并且它工作正常。

现在,当我尝试使用 MTLLoader 加载 MTL 文件时,出现以下错误:

Can't find variable: document

显然,MTLLoader 正在调用TextureLoader,后者在内部调用一些具有“文档”引用的加载函数。那么解决这个问题的方法是什么?

这是我正在使用的两个文件:

三.js

const THREE = require("three");
global.THREE = THREE;
if (!window.addEventListener)
    window.addEventListener = () => { };
// require("three/examples/js/renderers/Projector");
require("three/examples/js/loaders/MTLLoader");
require("three/examples/js/loaders/OBJLoader");
export default THREE;
Run Code Online (Sandbox Code Playgroud)

ThreeView.js

import React, { Component } from "react";
import { StyleSheet, View } from "react-native";
import { WebGLView } from "react-native-webgl";
import THREE from "./three";
import { image } from "src/res/image";

export default class ThreeView extends Component {
    requestId: *;
    componentWillUnmount() {
    cancelAnimationFrame(this.requestId);
}
onContextCreate = (gl: WebGLRenderingContext) => {
    const rngl = gl.getExtension("RN");

    const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
    const renderer = new THREE.WebGLRenderer({
        canvas: {
            width,
            height,
            style: {},
            addEventListener: () => { },
            removeEventListener: () => { },
            clientHeight: height
        },
        context: gl
    });
    renderer.setSize(width, height);
    renderer.setClearColor(0xffffff, 1);

    let camera, scene;
    let cube;

    function init() {
        camera = new THREE.PerspectiveCamera(75, width / height, 1, 1100);
        camera.position.y = 150;
        camera.position.z = 500;
        scene = new THREE.Scene();

        var mtlLoader = new THREE.MTLLoader();
        mtlLoader.load('female-croupier-2013-03-26.mtl', function (materials) {
            materials.preload();

            var objLoader = new THREE.OBJLoader();
            objLoader.setMaterials(materials);
            objLoader.load('female-croupier-2013-03-26.obj', function (object) {
                scene.add(object);
            }, onLoading, onErrorLoading);
        }, onLoading, onErrorLoading);
    }
    const onLoading = (xhr) => {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
    };
    const onErrorLoading = (error) => {
        console.log('An error happened', error);
    };
    const animate = () => {
        this.requestId = requestAnimationFrame(animate);
        renderer.render(scene, camera);

        // cube.rotation.y += 0.05;

        gl.flush();
        rngl.endFrame();
    };

    init();
    animate();
};
render() {
    return (
        <View style={styles.container}>
            <WebGLView
                style={styles.webglView}
                onContextCreate={this.onContextCreate}
            />
        </View>
    );
}
}

const styles = StyleSheet.create({
container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center"
},
webglView: {
    width: 300,
    height: 300
}
});
Run Code Online (Sandbox Code Playgroud)

kbc*_*ool 5

正如其他人所说,这个错误是由 Threejs 尝试使用浏览器中的 React-Native 不具备的功能引起的。

我已经能够通过猴子修补纹理加载器以在react-native-webgl中使用加载器来加载纹理(这是您收到错误的阶段)。将其添加到您的 init 函数中(最好位于顶部附近)。

//make sure you have defined renderer and rngl

/*

const renderer = new THREE.WebGLRenderer(...)

const rngl = gl.getExtension("RN");

*/

const loadTexture = async function(url, onLoad, onProgress, onError) {
      let textureObject = new THREE.Texture();
      console.log("loading",url,'with fancy texture loader');
      let properties = renderer.properties.get(textureObject);


      var texture = await rngl.loadTexture({yflip: false, image: url});

      /*
      rngl.loadTexture({ image: url })
        .then(({ texture }) => {
        */
          console.log("Texture [" + url + "] Loaded!")
          texture.needsUpdate = true;
          properties.__webglTexture = texture;
          properties.__webglInit = true;
          console.log(texture);
              
          
          if (onLoad !== undefined) {
            //console.warn('loaded tex', texture);
            onLoad(textureObject);
          }
          
  
      //});

    
      return textureObject;
  
  }
  
  THREE.TextureLoader.prototype.load = loadTexture;   
Run Code Online (Sandbox Code Playgroud)

这解决了加载纹理的问题,我可以看到它们在 Charles 中加载,但它们仍然没有在模型上渲染,所以我陷入了这一点。从技术上讲,这是一个正确的答案,但一旦实施,您就会陷入困境。我希望您能发表评论并告诉我您已经取得了进一步的进展。


Wil*_*iam 1

我有类似的设置并遇到了同样的问题。我的选择是切换到 JSONLoader,它不需要文档在 React-Native 中渲染。因此,我只是使用三个 js 插件将模型加载到 Blender 中,然后将其导出为 json。只需查看向 Blender 添加 3-js adon 的过程

\n\n

https://www.youtube.com/watch?v=mqjwgTAGQRY

\n\n

一切顺利

\n