首页 > 解决方案 > 无法在 Expo 中渲染 3D 模型

问题描述

SDK 版本:37.0.0
平台(Android/iOS/web/all):Android/iOS。

我正在尝试在我的应用程序中加载 3D 对象并遵循许多教程。模型已成功加载并附加到场景变量,但它没有出现在视图中。这是我毕业项目的一部分,我在 2 个月的时间里搜索了很多答案,以寻找一个真正可行的解决方案,因为我发现的大多数解决方案都太旧并且不起作用。

我的组件如下所述:

import * as React from 'react';
import { Ionicons } from '@expo/vector-icons';
import { View, StyleSheet,PixelRatio ,TouchableOpacity} from 'react-native';


import { ExpoWebGLRenderingContext, GLView } from 'expo-gl';
import { Renderer, TextureLoader } from 'expo-three';
import ExpoTHREE from 'expo-three';
import * as THREE from 'three'
import {
  AmbientLight,
  BoxBufferGeometry,
  Fog,
  Mesh,
  MeshStandardMaterial,
  PerspectiveCamera,
  PointLight,
  Scene,
  SpotLight,
} from 'three';
export default class ModelScreen extends React.Component {
    constructor(props) {
        super(props);
        let timeout;
        this.state= {
            loadingCompleted:true,
        }
    }

    componentDidMount(){
        THREE.suppressExpoWarnings(true)
        clearTimeout(this.timeout)
    }
    componentWillUnmount(){
        clearTimeout(this.timeout)
    }

    render() {
        return (
            <View style={styles.container}>
                <TouchableOpacity style={[styles.backButton]} activeOpacity={0.8}
                    onPress= {()=>{
                        this.props.setViewModel(false);
                    }}
                >
                    <Ionicons style={styles.backButtonIcon} name="md-arrow-back"></Ionicons>
                </TouchableOpacity>

                <GLView
                style={styles.viewer}
                onContextCreate={async (gl: ExpoWebGLRenderingContext) => {
                    const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
                    const sceneColor = '#111111';
                    const scale = PixelRatio.get();

                    // Create a WebGLRenderer without a DOM element
                    const renderer = new Renderer({gl,alpha:true});
                    renderer.capabilities.maxVertexUniforms = 52502;
                    renderer.setSize(width/scale, height/scale);
                    renderer.setPixelRatio(scale);
                    renderer.setClearColor(0x000000,0);

                    const camera = new PerspectiveCamera(45, width / height, 1, 1000);
                    camera.position.set(0, 2, 5);
                    camera.lookAt(0,0,0);
            
                    const scene = new Scene();
                    scene.fog = new Fog(sceneColor, 1, 1000);
                    
                    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);
                    var object = null;
                    
                    const model = {
                        'thomas.obj': require('./../assets/models/thomas/thomas.obj'),
                        'thomas.mtl': require('./../assets/models/thomas/thomas.mtl'),
                        'thomas.png': require('./../assets/models/thomas/thomas.png'),
                    };
                    // Load model!
                    await ExpoTHREE.loadAsync(
                        [model['thomas.obj'], model['thomas.mtl']],
                        null,
                        name => model[name],
                    ).then((obj)=>{
                        // // Update size and position
                        ExpoTHREE.utils.scaleLongestSideToSize(obj, 5);
                        ExpoTHREE.utils.alignMesh(obj, { y: 1 });
                        // Smooth mesh
                        ExpoTHREE.utils.computeMeshNormals(obj.children[0]);
                        // Add the mesh to the scene
                        scene.add(obj.children[0]);
                    }).catch((error)=>{
                        console.log(error);
                    });
                    
                    console.log(scene.children.length)
                    
                    function update() {
                        if (scene.children.length == 4)
                            scene.children[3].rotateY(0.03);
                    }
                    
                    // Setup an animation loop
                    const render = () => {
                        this.timeout = requestAnimationFrame(render);
                        update();
                        renderer.render(scene, camera);
                        gl.endFrameEXP();
                    };
                    render();
                }}
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex:1,
        justifyContent:"center",
        alignItems:"center",
        backgroundColor:"#111111",
    },
    backButton:{
        position:'absolute',
        top:30,
        width:50,
        height:50,
        alignItems:"center",
        justifyContent:"center",
        borderRadius:100,
        backgroundColor:"rgb(1,175,250)",
        left:20,
        alignSelf:"flex-start",
        zIndex:10,
    },
    backButtonIcon:{
        fontSize:25,
        fontWeight:'900',
        color:"#111111",
    },
    viewer:{
        width:"80%",
        height:"80%",
    }
});

谁能帮帮我?

编辑

它现在可以在没有材料的情况下工作我已经改变了

await ExpoTHREE.loadAsync([model['thomas.obj'], model['thomas.mtl']],null,name => model[name])

await ExpoTHREE.loadAsync(model['thomas.obj'],null,name => model[name])

但是如果我加载材料并且不知道它有什么问题,它不会渲染。我尝试了不同的对象,但无法渲染材质。物体消失

标签: react-nativethree.jsexpo

解决方案


推荐阅读