首页IT科技gulp压缩(压缩gltf/glb模型踩坑与解决 three.js DRACOLoader)

gulp压缩(压缩gltf/glb模型踩坑与解决 three.js DRACOLoader)

时间2025-05-04 00:24:35分类IT科技浏览4784
导读:前言 使用前端three.js加载3d模型过程中,往往会出现模型大小过大导致前端加载时间过长,降低用户体验。...

前言

使用前端three.js加载3d模型过程中            ,往往会出现模型大小过大导致前端加载时间过长                    ,降低用户体验            。

本文所记录的是笔者在使用gltf-pipeline压缩3d模型中踩坑DRACOLoader与解决的一个过程                    。

所采用的three库版本为 ^0.138.2

解决方案与介绍

通过gltf-pipeline可以大幅度压缩gltf/glb模型文件      。

并且有如下的作用

将 glTF 转换为 glb(和反向) 将缓冲区/纹理保存为嵌入或单独的文件 将 glTF 1.0 模型转换为 glTF 2.0(使用KHR_techniques_webgl和KHR_blend扩展) 应用Draco网格压缩

安装

npm install -g gltf-pipeline

或者

yarn global add gltf-pipeline

常用压缩命令

gltf-pipeline -i model.glb -o modelDraco.glb -d

使用 Draco 压缩网格 model.glb 文件      ,modelDraco.glb为压缩后输出文件名

gltf-pipeline -i model.glb -o modelDraco.glb -d -s

压缩并编写单独的缓冲区            、着色器和纹理         。

在three.js中使用Draco压缩网格后的文件

坑与解决过程

在多次百度之后写出的代码

let dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath("path"); dracoLoader.preload(); const loader = new GLTFLoader().setPath("path"); loader.setDRACOLoader(dracoLoader); loader.load("modelName", (gltf) => { scene.addObject(gltf.scene); gltf = null; });

在这里我遇到了一个大坑:

Uncaught SyntaxError: Unexpected token <

解决:

在问题过程排查中         ,发现网络请求是请求了模型数据的

后续发现bolb:xxx的请求不是写的应用层所发出的

之后通过阅读DRACOLoader.js的源码得

网络请求中bolb:xxx请求是由第250行URL.createObjectURL所创建的,创建该请求需要

draco_decoder.js draco_wasm_wrapper.js draco_decoder.wasm

并且请求的路径是使用setDecoderPath方法所设定

后续查阅资料得到

draco_decoder.js— Emscripten 编译的解码器                    ,与任何现代浏览器兼容                    。 draco_decoder.wasm— WebAssembly 解码器         ,与较新的浏览器和设备兼容         。 draco_wasm_wrapper.js— WASM 解码器的 JavaScript 包装器      。

在node_modules安装的包中获取three版本对应的draco路径为

node_modules\three\examples\js\libs

将改文件夹复制到public文件夹下并在DRACOLoader.setDecoderPath时候设置该对应路径即可

最后的解决代码与自己的封装

import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; /** * * path:存放模型父路径 * modelName:模型名 * setCenter:是否居中 * scale:模型的缩放比设定 * position:模型的位置 * rotation:模型的局部旋转 */ function loadModuleByDRACOLoader( path, modelName, setCenter, scale, position, rotation ) { let scaleVec3, positionVec3; if (typeof scale == "number") { scaleVec3 = new THREE.Vector3(scale, scale, scale); } else { scaleVec3 = new THREE.Vector3(scale.x, scale.y, scale.z); } if (typeof position == "number") { positionVec3 = new THREE.Vector3(position, position, position); } else { positionVec3 = new THREE.Vector3(position.x, position.y, position.z); } let dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath("./moduler/draco/"); // 设置public下的解码路径      ,注意最后面的/ dracoLoader.setDecoderConfig({ type: "js" }); //使用兼容性强的draco_decoder.js解码器 dracoLoader.preload(); const loader = new GLTFLoader().setPath(path); loader.setDRACOLoader(dracoLoader); return new Promise((res, rj) => { loader.load(modelName, (gltf) => { if (setCenter) { gltf.scene.traverse(function(child) { if (setCenter && child.isMesh) { child.geometry.center(); } }); } gltf.scene.scale.copy(scaleVec3); gltf.scene.position.copy(positionVec3); if (rotation) { gltf.scene.rotation.copy(rotation); } scene.add(gltf.scene); res(gltf.scene); gltf = null; }); }); }

调用

loadModuleByDRACOLoader(./moduler/, "grow4-processed.glb", false, 1, 0)

结语

因为遇到这个坑之后没有找到对应的解决方法                    ,所以写了该文章作为记录也给遇到相同问题的开发者避坑                    。

还有🎇🎇大三求内推🎇🎇

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
防弹性能最好的防弹衣(高防弹性VPS租用有哪些优势) 制作web网页头部导航栏 折叠(制作web网页头部导航栏)