在一些实战项目中,three只有几种有限的几何体,除非对细节不怎么要求,否则只能加载blender等工具导出的外部模型。在导入外部的模型时,经常会遇到各种各样的问题。
加载模型报错
我们使用GLTFLoader加载模型时,经常会遇到这样的错误: 7.png这是因为,模型是压缩过的,类似gzip,因此我们使用之前,需要先解压。
DRACOLoader是three提供的模型解压工具,可以帮我们对模型进行解压操作。
addGlb();
async function addGlb() {
const loader = new THREE.GLTFLoader();
const dracoloader = getDracoLoader();
loader.setDRACOLoader(dracoloader);//注入loader
//加载地板
const floor = await loadGlb('./model/floor2.glb', loader);
scene.add(floor);
//加载外墙
const wall = await loadGlb('./model/wall.glb', loader);
scene.add(wall);
}
function getDracoLoader() {
//对模型解压
const dracoloader = new THREE.DRACOLoader();
dracoloader.setDecoderPath("./draco/");//把examples\jsm\libs\draco这个文件夹复制过来
dracoloader.setDecoderConfig({ type: "js" })
dracoloader.preload();
return dracoloader;
}
function loadGlb(filepath, loader) {
return new Promise((resolve, reject) => {
loader.setCrossOrigin('Anonymous');//跨域问题
loader.load(filepath, (glb) => {
resolve(glb.scene);
}, undefined, (error) => {
console.error(error);
reject(error);
});
});
}
这里需要注意设置解压路径问题。我们需要把下载的E:\three.js-master\examples\jsm\libs\draco这个文件夹,复制到我们的项目中来,这个文件夹有一些写好的js工具类。
5.png
模型是黑的
加载出来的模型,即使打光了也是黑的。这是为啥呢?
这是因为blender在转换时出现了材质丢失,我们可以在代码中进行补救。
gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
child.material.emissive = child.material.color;
child.material.emissiveMap = child.material.map ;
}
});
全部代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="http://www.yanhuangxueyuan.com/threejs/build/three.min.js"></script>
<script src="http://www.yanhuangxueyuan.com/threejs/examples/js/controls/OrbitControls.js"></script>
<script src="http://www.yanhuangxueyuan.com/threejs/examples/js/loaders/GLTFLoader.js"></script>
<script src="http://www.yanhuangxueyuan.com/threejs/examples/js/loaders/DRACOLoader.js"></script>
</head>
<body>
<div id="webgl"></div>
</body>
</html>
<script>
//场景
var scene = new THREE.Scene();
//相机设置为世界坐标原点
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 300);
scene.add(camera);//添加相机
//添加坐标轴
var axes = new THREE.AxesHelper(500);//500表示xyz轴的长度,红:x,绿:y,蓝:z
scene.add(axes);
scene.add(new THREE.AmbientLight(0x444444));//打光
addGlb();
async function addGlb() {
const loader = new THREE.GLTFLoader();
const dracoloader = getDracoLoader();
loader.setDRACOLoader(dracoloader);//注入loader
//加载地板
const floor = await loadGlb('./model/floor2.glb', loader);
scene.add(floor);
//加载外墙
const wall = await loadGlb('./model/wall.glb', loader);
scene.add(wall);
//加载飞机
const airplane = await loadGlb('./model/Fighter.glb', loader);
airplane.position.y = 200;
scene.add(airplane);
}
function getDracoLoader() {
//对模型解压
const dracoloader = new THREE.DRACOLoader();
dracoloader.setDecoderPath("./draco/");//把examples\jsm\libs\draco这个文件夹复制过来
dracoloader.setDecoderConfig({ type: "js" })
dracoloader.preload();
return dracoloader;
}
function loadGlb(filepath, loader) {
return new Promise((resolve, reject) => {
loader.setCrossOrigin('Anonymous');//跨域问题
loader.load(filepath, (glb) => {
console.log('glb>>>', glb);
//处理材质丢失的情况
glb.scene.traverse(child => {
if (child.isMesh) {
child.material.emissive = child.material.color;
child.material.emissiveMap = child.material.map;
}
});
resolve(glb.scene);
}, undefined, (error) => {
console.error(error);
reject(error);
});
});
}
var renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});//画布
renderer.setSize(window.innerWidth, window.innerHeight);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
var controls = new THREE.OrbitControls(camera, renderer.domElement);
//将渲染好的canvas追加到dom
var cont = document.getElementById('webgl');
cont.appendChild(renderer.domElement);
animate();
function animate() {
renderer.render(scene, camera);//开始渲染
requestAnimationFrame(animate);
}
</script>
参考文章:https://blog.csdn.net/weixin_43131842/article/details/118025968
https://zhuanlan.zhihu.com/p/350136476
网友评论