我正在尝试使用 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;
这是我的 .mtl 文件的内容:
newmtl FaceTexture
map_Kd ibraheem.png
纹理文件 (ibraheem.png) 存在并且位于正确的位置。
我不确定我做错了什么。任何帮助将不胜感激!
增加环境光和定向光的强度 使用不同的材质类型(MeshBasicMaterial、MeshStandardMaterial) 检查纹理是否正确加载 验证 .obj 和 .mtl 文件格式是否正确
尽管进行了这些尝试,模型仍保持黑色并且未应用纹理。我错过了什么?
使用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 });