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();
    }
}

 

posted @ 2022-05-26 16:35  名字不好起啊  阅读(335)  评论(0编辑  收藏  举报