Three.js基础入门介绍——Three.js学习四【模型导入】

模型导入

通过Three.js的材质和几何体,我们可以很方便的创建基础3D模型,但涉及到复杂模型时,一般是由专业建模工具 生成模型 文件再导入的方式将模型引入到我们的3D场景中进行使用

Three.js加载器

Three.js提供多种加载器以支持市面上多种格式的3D文件导入操作

加载器 支持文件格式
3DMLoader .3dm
DRACOLoader .drc
FontLoader .json
GLTFLoader glTF(gl传输格式)是一种开放格式的规范 (open format specification), 用于更高效地传输、加载3D内容。该类文件以JSON(.gltf)格式或二进制(.glb)格式提供, 外部文件存储贴图(.jpg、.png)和额外的二进制数据(.bin)
KTX2Loader .ktx2
LDrawLoader LDraw资源(一个文本文件,通常扩展名为.ldr、.dat或.txt)可以只描述单个构造件或整个模型。
MMDLoader MMDLoader从MMD资源(例如PMD(.pmd)、PMX(.pmx)、VMD(,vmd)和VPD(.vpd)文件)中创建Three.js物体(对象)
MTLLoader .mlt或.mlt与.obj的配套文件
OBJLoader .obj
PCDLoader .pcd
PDBLoader .pdb
PRWMLoader .prwm
SVGLoader .svg
TGALoader .tga

3D模型文件获取与导入流程

模型获取:
通过建模工具或者模型素材网站获取,学习用的话官网的模型也是可以使用的,在官方示例文件夹中有很多模型文件目录:three.js-master\examples\models
模型导入:
模型导入的要素

  1. 模型文件
  2. 模型加载器

模型导入的流程

  1. 引入加载器并实例化
  2. 使用加载器导入模型文件

模型导入的操作

本文将以典型 GLTF 加载器(GLTFLoader)为例进行模型导入操作,模型使用的是官方示例中的Soldier模型,文件位置:three.js-master\examples\models\gltf\Soldier.glb
为了方便操作我们将文件拷出来放在static\3dmod\gltf文件夹下,static与three.js-master同级

代码基于文章《Three.js基础入门介绍——Three.js学习三【借助控制器操作相机】》的基础上进行修改,文件结构如下
在这里插入图片描述

index.html

//1、引入加载器并实例化
	import { GLTFLoader } from "./three.js-master/examples/jsm/loaders/GLTFLoader.js";
	const gltfLoader = new GLTFLoader();

加载器方法官方文档链接:https://threejs.org/docs/index.html?q=loader#examples/zh/loaders/GLTFLoader

这里用了一个Loader(实现加载器的基类)公有方法.setPath ( path : String ) : this设置资源基本路径,不用的话也可以直接在.load方法第一个url参数中写完整路径。加载器解析基于glTF的ArrayBuffer或JSON字符串,并在完成后触发onLoad回调。onLoad的参数将是一个包含有已加载部分的Object:.scene、 .scenes、 .cameras、 .animations 和 .asset。

.load ( url : String, onLoad : Function, onProgress : Function, onError : Function ) : undefined

  • url — 包含有.gltf/.glb文件路径/URL的字符串。
  • onLoad — 加载成功完成后将会被调用的函数。该函数接收parse所返回的已加载的JSON响应。
  • onProgress — (可选)加载正在进行过程中会被调用的函数。其参数将会是XMLHttpRequest实例,包含有总字节数.total与已加载的字节数.loaded。
  • onError — (可选)若在加载过程发生错误,将被调用的函数。该函数接收error来作为参数。
  • 开始从url加载,并使用解析过的响应内容调用回调函数。
//2、使用加载器导入模型文件,这里注意,需要用在scene创建后
gltfLoader.setPath('./static/3dmod/gltf/')
                .load('Soldier.glb', function (gltf) {
                    console.log("gltf",gltf)
                    gltf.scene.scale.set(1, 1, 1)
                    gltf.scene.traverse(function (child) {
            			if (child instanceof THREE.Mesh) {
            				child.castShadow = true; //阴影
            				child.receiveShadow = true; //接受别人投的阴影
            			}
            		});
                    scene.add(gltf.scene);
                }, function(res){
                    console.log(res.total, res.loaded)
                });

当我们添加好后会发现是黑黑的,只能看到在转动的绿色立方体,但是我们使用鼠标转动一下视角还是能发现有模型的存在
Three.js基础入门介绍——Three.js学习四【模型导入】_第1张图片
追其原因是我们场景中缺少了光照,添加光照

//添加一个白色点光源
	const light = new THREE.PointLight(0xffffff, 1, 100, 1);
	light.position.set(0, 10, 10 );
	scene.add(light);

模型可以看见了是一个伸展双臂的Soldier,但是背景还是黑色的,而且,这个Soldier是背向的。Three.js基础入门介绍——Three.js学习四【模型导入】_第2张图片
调整一下转向以及背景颜色,调整角度如果不知道怎么转,可以引入坐标系来辅助找旋转角度

// 增加坐标系红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
// 显示三维坐标系,辅助找旋转角度
const axes = new THREE.AxesHelper(20);
// 添加坐标系到场景中
scene.add(axes);

//2、使用加载器导入模型文件,这里注意,需要用在scene创建后,加载完后修改转向
gltfLoader.setPath('./static/3dmod/gltf/')
                .load('Soldier.glb', function (gltf) {
                    console.log("gltf",gltf)
                    gltf.scene.rotation.y = Math.PI; //沿着Y轴转180
                    gltf.scene.scale.set(1, 1, 1)
                    gltf.scene.traverse(function (child) {
            			if (child instanceof THREE.Mesh) {
            				child.castShadow = true; //阴影
            				child.receiveShadow = true; //接受别人投的阴影
            			}
            		});
                    scene.add(gltf.scene);
                }, function(res){
                    console.log(res.total, res.loaded)
                });

//在renderer渲染器创建后设置场景颜色
renderer.setClearColor(new THREE.Color(0xbbbbbb));

效果:

完整代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script type="importmap">
			{
				"imports": {
					"three": "./three.js-master/build/three.module.js"
				}
			}
		</script>
		<script type="module">
			import * as THREE from "three";
			import { OrbitControls } from "./three.js-master/examples/jsm/controls/OrbitControls.js";
			import { GLTFLoader } from "./three.js-master/examples/jsm/loaders/GLTFLoader.js";

			const gltfLoader = new GLTFLoader();
			const scene = new THREE.Scene();
			const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
			// 增加坐标系红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
			// 显示三维坐标系
            const axes = new THREE.AxesHelper(20);
            // 添加坐标系到场景中
            scene.add(axes);
			gltfLoader.setPath('./static/3dmod/gltf/')
                .load('Soldier.glb', function (gltf) {
                    console.log("gltf",gltf)
					gltf.scene.rotation.y = Math.PI;
                    gltf.scene.scale.set(1, 1, 1)
                    gltf.scene.traverse(function (child) {
            			if (child instanceof THREE.Mesh) {
            				child.castShadow = true; //阴影
            				child.receiveShadow = true; //接受别人投的阴影
            			}
            		});
                    scene.add(gltf.scene);
                }, function(res){
                    console.log(res.total, res.loaded)
                });
			//添加一个白色点光源
            const light = new THREE.PointLight(0xffffff, 1, 100, 1);
            light.position.set(0, 10, 10);
            scene.add(light);
			const renderer = new THREE.WebGLRenderer();
			renderer.setClearColor(new THREE.Color(0xbbbbbb));
			renderer.setSize( window.innerWidth, window.innerHeight );
			document.body.appendChild( renderer.domElement );

			const controls = new OrbitControls(camera,renderer.domElement);//创建控件对

			const geometry = new THREE.BoxGeometry();
			const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
			const cube = new THREE.Mesh( geometry, material );
			scene.add( cube );

			camera.position.z = 5;

			function animate() {
				requestAnimationFrame( animate );

				cube.rotation.x += 0.01;
				cube.rotation.y += 0.01;

				renderer.render( scene, camera );
			};

			animate();
		</script>
	</body>
</html>

你可能感兴趣的:(Three.js,前端)