首页 > 其他分享 >three模型加载loader模块封装

three模型加载loader模块封装

时间:2024-03-18 11:34:39浏览次数:31  
标签:resolve 封装 import three loader path new

在three项目中需要加载很多的模型 而且在很多地方需要使用loader加载模型回调的gltf 上一个项目中遇到了 初学three的我 留下笔记

简单版
`
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

const loader = new GLTFLoader();
let model = new THREE.Group();

export const loaderModel = function (path) {
return new Promise(resolve => {
loader.load(path, function (gltf) {
// 遍历模型中的每个object
gltf.scene.traverse((object) => {
if (object.isMesh) {
//可以在这里做一些基础操作
}
});

        if(model.children.length){
            model.children.forEach(item=>{
                model.remove(item)
            })
        }
        model.add(gltf.scene);
        resolve(gltf)
    });


})

}

export { model };

`

后面根据别人的案例 做了一个完整的版本 支持使用indexDB 对模型缓存功能的

完整版
`
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
import utils from "utils";
import * as THREE from "three";
import DBUtils from "@/common/_/threejs/DBUtils";

var serverAddress = window.location.host; // 获取服务器地址

//params 为引入的模型地址或者地址集合 handleProgress 为 回调函数 用于计算加载进度
export default function loader(params, handleProgress) {
// 批量加载资源
// lodash 中的 isArray 方法
if (utils.isArray(params)) {
let funcarr = [];
let progressEvent = {
loaded: {},
total: {}
}
// lodash 中的 throttle 节流 方法
let update = utils.throttle(() => {
let loaded = 0, total = 0;
// lodash 中的 each 方法
utils.each(progressEvent.loaded, (v) => {
loaded += v;
});
utils.each(progressEvent.total, (v) => {
total += v;
});
// console.log(loaded, total);
handleProgress({
loaded,
total
})
}, 100);
let func = (i) => {
// console.log('func', progressEvent);
return (o) => {
progressEvent.loaded[i] = o.loaded;
progressEvent.total[i] = o.total;
update();
}
};
params.forEach((p, i) => {
funcarr.push(loader(p, func(i)))
});
return Promise.all(funcarr);
}
return new Promise(resolve => {
let path = params.path;
let ext = utils.getFileType(path);
let loader;
switch (ext) {
case 'glb':
case 'gltf':
if (params.decoderPath) {
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(params.decoderPath);
loader = new GLTFLoader();
loader.setDRACOLoader(dracoLoader);
}
else {
loader = new GLTFLoader();
}
break;
case 'obj':
if (params.mtl) {
return new Promise(resolve => {
var mtlLoader = new MTLLoader();
// 初始化obj
var objLoader = new OBJLoader();
// 加载mtl文件
mtlLoader.load(params.mtl, (mtl) => {
// 初始化
mtl.preload();
// 加载贴图
objLoader.setMaterials(mtl);
objLoader.load(path, (obj) => {
resolve({ mtl, obj })
}, handleProgress);
})
});
}
else {
loader = new OBJLoader();
}
break;
case 'mtl':
loader = new MTLLoader();
break;
case "fbx":
loader = new FBXLoader();
break;
}
if (loader) {
if (path == 'models/swfq/zt1/shengwei.gltf') {
const indexDB = new DBUtils("gltf", "shengwei");
// 此处拼 服务器地址
indexDB.get('http://'+serverAddress + '/' + path)
.then((blob) => {
path = URL.createObjectURL(new Blob([blob]));
loader.load(path, (res) => {
resolve(res);
}, handleProgress)

                });
        } else {
            loader.load(path, (res) => {
                resolve(res);
            }, handleProgress)
        }

    }
});

}

`

DBUtils 缓存的代码

export default class DBUtils { constructor(dbName, storeName, dbVersion = 1) { this.dbName = dbName; this.storeName = storeName; this.dbVersion = dbVersion; this.db = null; } async get(url) { this.db = await this.initDataBase(this.dbName, this.storeName, this.dbVersion); const request = this.db .transaction([this.storeName], 'readwrite') .objectStore(this.storeName) .get(url); return new Promise((resolve, reject) => { request.onsuccess = evt => { const modelFile = evt.target.result; console.log(modelFile); // 如果缓存中有,直接从缓存中获取 if (modelFile) { console.log("使用缓存"); resolve(modelFile.blob); } else { console.log("请求资源"); // 如果缓存中没有,则请求资源 this.addData(url).then(blob => { resolve(blob); }).catch(() => { reject(); }); } }; request.onerror = evt => { console.log('error', evt); reject(); }; }); }

utils 中全是引用 lodash 的方法 完整版是借鉴的大佬的代码

使用 完整版
`
loader(option.load, (progressEvent) => {
this.percentage = +(progressEvent.loaded * 99 / progressEvent.total).toFixed(2);
}).then(res => {
this.loading = false;
this.init();

            if (!this.on.load) {
                console.error("option.on.load方法不存在");
            }
            else {
                this.on.load(this, res);
            }
        });

`

完整版有部分代码是复制的 欢迎大家一起讨论进步

标签:resolve,封装,import,three,loader,path,new
From: https://www.cnblogs.com/babybearcq/p/18079975

相关文章

  • 什么是TO封装
    TO的英文全名是:TransistorOutline(晶体管外形),是一种晶体管封装,旨在使引线能够被成型加工并用于表面贴装。为了更好的理解,那小编先给大家介绍下晶体管(Transistor)1947年12月16日,威廉·邵克雷(WilliamShockley)、约翰·巴顿(JohnBardeen)和沃特·布拉顿(WalterBrattain)成功地......
  • FFmpeg-aac、h264封装flv及时间转换
    文章目录时间概念流程api核心代码时间概念dts:解码时间戳,表示压缩帧的解码时间pts:显示时间戳,表示将压缩帧解码后得到的原始帧的显示时间时间基:time_base,通常以ms为单位时间戳:timestamp,多少个时间基真实时间:time_base*timestamp如一个视频帧......
  • Python面向对象编程:合集篇(类、对象、封装、继承和多态)
    Python语言设计之初,就是为了面向对象。所以Python的面向对象更加易于理解。如果你以前学过Java、C++你大概就懂得什么是面向对象,但如果你是第一门编程语言就选择Python,那么也不要害怕。这篇文章,我们将会尽量详细的讲解,把Python面向对象编程的知识讲清楚。接下来我们先来简单的......
  • 2.1封装
    封装是C++面向对象三大特征之一1、封装的意义封装实现了类的接口和实现的分离。封装后的类隐藏了它的实现细节,也就是说,类的用户只能是使用接口而无法访问实现部分。意义:1、将属性和行为作为一个整体,表现生活中的事物。在设计类的时候,属性和行为写在一起,表现事物。语法:class......
  • vue 3+TS 封装自定义右键全局菜单(虚拟节点)
    有时我们需要点击(右键或左键)某个元素时弹出菜单,实现复制、粘贴、删除等功能。本文将介绍如何封装一个自定义的右键全局菜单(无三方依赖)。封装的菜单可自定义菜单项,图标,禁用,分割线,隐藏等。并且可以在全局任意地方使用。源码在文章末尾。效果使用<template><div>......
  • PyInstaller does not include a pre-compiled bootloader for your platform.
    用PyInstaller打包python程序时,收到下面错误:User140343INFO:BuildingPKGbecausePKG-00.tocisnonexistent140344INFO:BuildingPKG(CArchive)mainwindow.pkg215759INFO:BuildingPKG(CArchive)mainwindow.pkgcompletedsuccessfully.215891INFO:Bootloa......
  • PyInstaller does not include a pre-compiled bootloader for your platform.
    用PyInstaller打包python程序时,收到下面错误:User140343INFO:BuildingPKGbecausePKG-00.tocisnonexistent140344INFO:BuildingPKG(CArchive)mainwindow.pkg215759INFO:BuildingPKG(CArchive)mainwindow.pkgcompletedsuccessfully.215891INFO:Bootloa......
  • Vue — 请求模块、api模块封装
    1.请求模块importaxiosfrom'axios'constrequest=axios.create({  baseURL:'',//请求的域名地址  timeout:5000,})request.interceptors.request.use((config)=>{  //开启loading禁止背景点击  returnconfig},(err)=>{  returnPro......
  • US1M/US1G-ASEMI高效快恢复二极管SMA封装
    编辑:llUS1M/US1G-ASEMI高效快恢复二极管SMA封装型号:US1M/US1G品牌:ASEMI封装:SMA最大平均正向电流(IF):1A最大循环峰值反向电压(VRRM):1000V最大正向电压(VF):1.1V工作温度:-55°C~150°C反向恢复时间:100ns重量:0.064克芯片个数:1芯片尺寸:50mil正向浪涌电流(IFMS):30AUS1M/US1G特性:......
  • Vue3——axios 安装和封装
    axios安装和封装安装npminstallaxios最后通过axios测试接口!!!axios二次封装在开发项目的时候避免不了与后端进行交互,因此我们需要使用axios插件实现发送网络请求。在开发项目的时候我们经常会把axios进行二次封装。目的:1:使用请求拦截器,可以在请求拦截器中处理......