three.js 3 载入模型
import * as THREE from 'three'; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; /** * 3d 根据文档学习 3 - 载入模型 * https://threejs.org/docs/index.html#manual/zh/introduction/Loading-3D-models * 模型网站:https://sketchfab.com/3d-models?features=downloadable&sort_by=-likeCount * 谷歌邮箱登录,微软邮箱创建的账号(网易邮箱注册失败,估计大陆号不支持) */ export class ThreeDoc3Load { constructor(canvasId) { this.work(canvasId); } /** * 如果有可能的话,我们推荐使用glTF(gl传输格式)。.GLB和.GLTF是这种格式的这两种不同版本, 都可以被很好地支持。 * 由于glTF这种格式是专注于在程序运行时呈现三维物体的,所以它的传输效率非常高,且加载速度非常快。 功能方面则包括了网格、 * 材质、纹理、皮肤、骨骼、变形目标、动画、灯光和摄像机。 * 公共领域的glTF文件可以在网上找到,例如 Sketchfab * @param canvasId */ work(canvasId) { // 创建 3d 场景 const scene = new THREE.Scene(); /** * GLTF加载器(GLTFLoader) * glTF(gl传输格式)是一种开放格式的规范 (open format specification), 用于更高效地传输、加载3D内容。该类文件以JSON * (.glft)格式或二进制(.glb)格式提供, 外部文件存储贴图(.jpg、.png)和额外的二进制数据(.bin)。一个glTF组件可传输一个 * 或多个场景, 包括网格、材质、贴图、蒙皮、骨架、变形目标、动画、灯光以及摄像机。 * @type {GLTFLoader} */ const loader = new GLTFLoader(); // 文件夹名称,摄像机xyz, let dir , cameraXYZ, cameraPx, cameraPy, cameraPz, lightR; // 口袋妖怪治疗中心 dir = 'pokemon_rse_-_pokemon_center'; cameraXYZ = [ 0.6, 1, 1.8 ]; lightR = 1.2; // 露琪亚 dir = 'lugia-statue'; cameraXYZ = [ -2, 1.3, 5 ]; lightR = 1.2; // 卡通小汽车 dir = 'pony_cartoon'; cameraXYZ = [ 2.3, 2.4, 3.6 ]; lightR = 20; // 引用地址 let url = `assets/models/${ dir }/scene.gltf`; /** * .load ( url : String, onLoad : Function, onProgress : Function, onError : Function ) : * url — 包含有.gltf/.glb文件路径/URL的字符串。 * onLoad — 加载成功完成后将会被调用的函数。该函数接收parse所返回的已加载的JSON响应。 * onProgress — (可选)加载正在进行过程中会被调用的函数。其参数将会是XMLHttpRequest实例,包含有总字节数.total与已加载的字节数.loaded。 * onError — (可选)若在加载过程发生错误,将被调用的函数。该函数接收error来作为参数。 */ loader.load(url, function (gltf) { scene.add(gltf.scene); }, undefined, function (error) { console.error(error); }); /** * .setDRACOLoader ( dracoLoader : DRACOLoader ) : this * dracoLoader — THREE.DRACOLoader的实例,用于解码使用KHR_draco_mesh_compression扩展压缩过的文件。 * .parse ( data : ArrayBuffer, path : String, onLoad : Function, onError : Function ) : undefined * data — 需要解析的glTF文件,值为一个ArrayBuffer或JSON字符串。 * path — 用于找到后续glTF资源(如纹理和.bin数据文件)的基础路径。 * onLoad — 解析成功完成后将会被调用的函数。 * onError — (可选)若在解析过程发生错误,将被调用的函数。该函数接收error来作为参数。 * 解析基于glTF的ArrayBuffer或JSON字符串,并在完成后触发onLoad回调。onLoad的参数将是一个包含有已加载部分的Object:.scene、 .scenes、 .cameras、 .animations 和 .asset。 */ /** * 创建渲染器 * WebGLRenderer渲染器之外,Three.js同时提供了其他几种渲染器。当用户所使用的浏览器过于老旧,或者由于其他原因不支持WebGL时,可以使用这几种渲染器进行降级。 * @type {number} */ const renderer = new THREE.WebGLRenderer(); /** * 渲染器尺寸:设置渲染器的宽高使渲染出的场景充满应用程序 * 对于性能比较敏感的应用程序来说,你可以使用setSize传入一个较小的值,例如window.innerWidth/2和window.innerHeight/2 * 如果想以较低的分辨率来渲染,可以在调用setSize时,将updateStyle(第三个参数)设为false */ renderer.setSize(window.innerWidth, window.innerHeight); // 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。 document.body.appendChild(renderer.domElement); let light = ''; // 添加灯光 - 环境光 - 无阴影 light = new THREE.AmbientLight(0xffffff, lightR); // 平行光 // light = new THREE.DirectionalLight(0xffffff, 2); light.position.set(0,0,0); scene.add(light); /** * 照相机常用的有两种 * 正投影相机:THREE.OrthographicCamera(left,right,top,bottom,near,far); * 透视照相机:THREE.PerspectiveCamera( fov, aspect, near, far ) ; * fov - 视野角度。视野角度就是无论在什么时候,你所能在显示器上看到的场景的范围,它的单位是角度(与弧度区分开) * aspect ratio - 长宽比。也就是你用一个物体的宽除以它的高的值。当你在一个宽屏电视上播放老电影时,可以看到图像仿佛是被压扁的 * near,far - 近截面和远截面。 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中 */ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 设置相机位置 [ cameraPx, cameraPy, cameraPz ] = cameraXYZ; camera.position.x = cameraPx; camera.position.y = cameraPy; camera.position.z = cameraPz; camera.lookAt(0,0,0); // 添加控制器 let orb = new OrbitControls(camera, document.body); orb.addEventListener('change', function () { console.log(camera.position); }); renderer.render(scene, camera); function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate(); } }