主要目标:将从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,它在内部调用一些带有'文件'参考。那可能是什么解决方案?
以下是我正在使用的两个文件:
three.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;
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
}
});
答案 0 :(得分:4)
正如其他人所说的那样,这个错误是由于三个人试图使用来自浏览器的功能而导致的,而本机没有这种功能。
我已经通过猴子修补纹理加载器以在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;
这解决了加载纹理的问题,我可以看到它们在Charles中加载但是它们仍然没有在模型上渲染,所以我已经过了那个点。从技术上讲,这是一个正确的答案,但是一旦你实施它就会被卡住。我希望你能回复一下,告诉我你已经进一步了。
答案 1 :(得分:1)
我有类似的设置并遇到了同样的问题。我的选择是切换到JSONLoader,它不需要在react-native中呈现文档。所以,我只是将我的模型加载到Blender中,带有一个3-js插件,然后将其导出为json。只需查看向Blender添加3-js adon的过程
https://www.youtube.com/watch?v=mqjwgTAGQRY
一切顺利
答案 2 :(得分:1)
这可能会让你更接近:
GLTF格式支持嵌入纹理图像(作为base64)。如果您的资产管道允许,您可以转换为GLTF,然后加载到三个/ react-native。
我必须为“decodeUriComponent”和“atob”提供一些“窗口”polyfill,因为GLTFLoader使用FileLoader来解析base64:
我已经成功加载了嵌入式缓冲区,但您需要更多的polyfill来加载纹理。 TextureLoader使用ImageLoader,它使用document.createElementNS
答案 3 :(得分:1)
您正在使用使用TextureLoader的MTLLoader,而TextureLoader使用ImageLoader。 图像加载器使用document.createElementNS()函数。
我要做的就是直接调用THREEjs TextureLoader:
<view extends linear layout>
<child-view extends relative layout>
<some content>
<relative-layout>
<progressbar> (align text view right, match parent)
<textview> (align parent right, wrap content) <- there's i have to make some changes
<relative-layout>
<child-view>
<...>
<view>
((使用纹理检查Texture documentation)
然后我使用了来自React native的Image类(而不是THREEjs Image,它需要构造DOM)将其作为属性提供给Texture:
let texture = new THREE.Texture(
url //URL = a base 64 JPEG string in this case
);
然后最终将纹理映射到目标材质上:
import { Image } from 'react-native';
var img = new Image(128, 128);
img.src = url;
texture.normal = img;
在 react native documentation中,它将说明如何使用react native图像元素,它支持base64编码的JPEG。
也许有一种方法可以让您选择需要TextureLoader的零件,并用此答案替换该零件。让我知道结果如何。
旁注,我尚未尝试在我的webGLView中显示此内容,但在日志中它看起来像普通的threejs对象,值得尝试