preface
Use front-end three In the process of loading 3d models with JS, the model size is often too large, resulting in too long loading time at the front end and reducing the user experience.
What is recorded in this paper is a process of stepping on the DRACOLoader and solving the problem in using gltf pipeline to compress 3d model.
The three library version used is ^ 0.138.2
Solution and introduction
adopt gltf-pipeline The gltf/glb model file can be greatly compressed.
And has the following functions
- Convert glTF to glb (and reverse)
- Save the buffer / texture as an embedded or separate file
- Convert glTF 1.0 model to glTF 2.0 (using KHR_techniques_webgl and KHR_blend (Extended)
- application Draco Mesh compression
install
npm install -g gltf-pipeline
perhaps
yarn global add gltf-pipeline
Common compression commands
gltf-pipeline -i model.glb -o modelDraco.glb -d
use Draco Compress mesh model GLB file, modeldraco GLB is the compressed output file name
gltf-pipeline -i model.glb -o modelDraco.glb -d -s
Compress and write separate buffers, shaders, and textures.
In three JS file after using Draco to compress the grid
Pit and solution process
Code written after Baidu many times
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; });
Here I came across a big pit:
Uncaught SyntaxError: Unexpected token '<'
solve:
In the troubleshooting process, it is found that the network request requests the model data
Later, it was found that the request of bolb:xxx was not sent by the application layer of writing
Then read dracoloader JS source code
In the network request, the bolb:xxx request is made by line 250 URL.createObjectURL Created, the request needs to be created
- draco_decoder.js
- draco_wasm_wrapper.js
- draco_decoder.wasm
And the requested path is set using the setDecoderPath method
Follow up information obtained
- draco_decoder.js - Emscripten compiled decoder, compatible with any modern browser.
- draco_decoder.wasm - web assembly decoder, compatible with newer browsers and devices.
- draco_wasm_wrapper.js - JavaScript wrapper for WASM decoder.
On node_ The draco path corresponding to the three version obtained from the package installed by modules is
node_modules\three\examples\js\libs
Copy the modified folder to the public folder and put it in dracoloader Set the corresponding path when setdecoderpath
The final solution code and its own encapsulation
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; /** * * path:Store model parent path * modelName:Model name * setCenter:Centered * scale:Zoom ratio setting of the model * position:Location of the model * rotation:Local rotation of model */ 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/"); // Set the decoding path under public and pay attention to the last one/ dracoLoader.setDecoderConfig({ type: "js" }); //Use Draco with strong compatibility_ decoder. JS decoder 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; }); }); }
call
loadModuleByDRACOLoader('./moduler/', "grow4-processed.glb", false, 1, 0)
epilogue
Because no corresponding solution was found after encountering this pit, this article was written as a record, and it was also used to avoid the pit for developers encountering the same problem.
also 🎇🎇 Big three seeking inner push 🎇🎇