为什么 React Native Expo Three.js 模型纹理不包裹并渲染为黑色?

问题描述 投票:0回答:1

我正在尝试使用 Expo 和 Three.js 在我的 React Native 应用程序中渲染 3D 模型。模型已加载,但它是全黑的,并且纹理未正确包裹。我已尝试调整材质和照明,但仍然遇到问题。这是我的代码:

import React, { useState, useRef } from "react";
import { View } from "react-native";
import { GLView } from "expo-gl";
import { Renderer } from "expo-three";
import * as THREE from "three";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import { Asset } from "expo-asset";

const ThreeJSModelViewer: React.FC = () => {
  const [modelLoaded, setModelLoaded] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const objectRef = useRef<THREE.Object3D | null>(null);

  const handleContextCreate = async (gl: any) => {
    const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;

    const renderer = new Renderer({ gl });
    renderer.setSize(width, height);
    renderer.setClearColor("#ffffff", 0);

    const scene = new THREE.Scene();

    const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
    camera.position.z = 7;

    const ambientLight = new THREE.AmbientLight(0xffffff, 0.8);
    scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(1, 1, 1).normalize();
    scene.add(directionalLight);

    try {
      const objAsset = Asset.fromModule(require("../../assets/temp-obj/ibraheem.obj"));
      const mtlAsset = Asset.fromModule(require("../../assets/temp-obj/ibraheem.mtl"));
      const textureAsset = Asset.fromModule(require("../../assets/temp-obj/ibraheem.png"));

      await Promise.all([objAsset.downloadAsync(), mtlAsset.downloadAsync(), textureAsset.downloadAsync()]);

      const mtlLoader = new MTLLoader();
      const materials = await mtlLoader.loadAsync(mtlAsset.uri);
      materials.preload();

      const objLoader = new OBJLoader();
      objLoader.setMaterials(materials);

      const object = await objLoader.loadAsync(objAsset.uri);

      const textureLoader = new THREE.TextureLoader();
      const texture: THREE.Texture = await new Promise((resolve, reject) => {
        textureLoader.load(
          textureAsset.uri,
          (loadedTexture) => resolve(loadedTexture),
          undefined,
          (error) => reject(error)
        );
      });

      object.traverse((child) => {
        if (child instanceof THREE.Mesh) {
          child.material = new THREE.MeshPhongMaterial({
            map: texture,
            specular: new THREE.Color(0x111111),
            shininess: 200,
          });
        }
      });

      // Resize and position the object
      const resizeObject = (obj: THREE.Object3D) => {
        const box = new THREE.Box3().setFromObject(obj);
        const size = box.getSize(new THREE.Vector3());
        const maxDim = Math.max(size.x, size.y, size.z);
        const scale = 5 / maxDim;
        obj.scale.multiplyScalar(scale);

        box.setFromObject(obj);
        box.getCenter(obj.position);
        obj.position.multiplyScalar(-1);
      };

      resizeObject(object);
      scene.add(object);
      setModelLoaded(true);

      objectRef.current = object;

      const animate = () => {
        requestAnimationFrame(animate);
        if (objectRef.current) {
          objectRef.current.rotation.y += 0.01;
        }
        renderer.render(scene, camera);
        gl.endFrameEXP();
      };
      animate();
    } catch (error) {
      console.error("Error loading 3D model:", error);
      setError("Failed to load 3D model.");
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <GLView style={{ flex: 1 }} onContextCreate={handleContextCreate} />
      {/* ... (other UI components) */}
    </View>
  );
};

export default ThreeJSModelViewer;

.png 文件(纹理)

texture

这是我的 .mtl 文件的内容:

newmtl FaceTexture
map_Kd ibraheem.png

纹理文件 (ibraheem.png) 存在并且位于正确的位置。

我不确定我做错了什么。任何帮助将不胜感激!

我尝试过的事情

增加环境光和定向光的强度 使用不同的材质类型(MeshBasicMaterial、MeshStandardMaterial) 检查纹理是否正确加载 验证 .obj 和 .mtl 文件格式是否正确

尽管进行了这些尝试,模型仍保持黑色并且未应用纹理。我错过了什么?

react-native three.js expo 3d-modelling
1个回答
0
投票

使用ExpoTHREE.TextureLoader()。这解决了我的问题:

import ExpoTHREE, { THREE,Renderer, TextureLoader } from 'expo-three';
import { Asset, useAssets } from 'expo-asset';

const asset = Asset.fromModule(require('../../assets/images/es.png'));
const texture = new ExpoTHREE.TextureLoader().load(asset)
console.log("texture:", texture);
const textureMaterial = new THREE.MeshBasicMaterial({ map: texture });
© www.soinside.com 2019 - 2024. All rights reserved.