前言
大部分的webgl框架,比方threejs和babylon等,都能够加载obj和gltf模型。 咱们的引擎,基于three封装,同样有加载模型的loader,因而加载obj和gltf模型也是很简略就能够实现的。
不过加载文件都是在线的文件,也就是通过url的模式进行加载。 团队开发的三维可视化平台框架,须要可能上传obj和gltf等格局的模型,在上传前,须要先对模型预览,这就波及到如何加载本地模型的问题了。
加载本地模型
本文以gltf为例,进行阐明。 加载本地模型的思路是这样的:
既然引擎能够通过url的机制,加载模型。 那么如果有一种机制,能够把本地文件及其关联的资源(比方贴图)等转换成url的模式,就能够进行应用loader进行拜访了。
Blob & File
首先咱们学习下Blob和File对象,以下内容来自MDN:
Blob
对象示意一个不可变、原始数据的类文件对象。它的数据能够按文本或二进制的格局进行读取,也能够转换成 ReadableStream
来用于数据操作。
Blob 示意的不肯定是JavaScript原生格局的数据。File
接口基于Blob
,继承了 blob 的性能并将其扩大使其反对用户零碎上的文件。
File
对象是非凡类型的 Blob
,且能够用在任意的 Blob 类型的 context 中。比如说, FileReader
, URL.createObjectURL()
, createImageBitmap()
(en-US)"), 及 XMLHttpRequest.send()
) 都能解决 Blob
和 File
。
createObjectURL
URL对象上的办法 createObjectURL能够把一个Blob对象或者File对象,转化成一个url对象,语法如下:
objectURL = URL.createObjectURL(object);
其中object示意的是Blob或者File对象。返回的是一个url地址对象。
加载本地模型
有了上述基础知识,大抵的思路就进去了:
- 首先 加载本地文件,读取file对象(可能是多个File对象,因为一个模型可能包含多个资源文件)。
- 找出次要文件(gltf glb等格局的)文件,主文件通过 createObjectURL办法转换成url对象
- 找出其余文件,通过createObjectURL办法转换成url对象
- 加载主文件的url,并在加载过程中,通过地址改写的形式,把相干的资源替换成文件的url对象。
以上思路的大抵代码如下:
let files = document.getElementById("file-input").files; if (!files.length) return; console.log(files); let rootFile; const fileMap = new Map(); Array.from(files).forEach((file) => fileMap.set(file.name, file)); Array.from(fileMap).forEach(([path, file]) => { if (file.name.match(/\.(gltf|glb)$/)) { rootFile = file; rootPath = path.replace(file.name, ""); } }); const fileUrl = URL.createObjectURL(rootFile); const gltf = await load(fileUrl, rootPath, fileMap);function load(url, rootPath, assetMap) { const index = url.lastIndexOf("/"); const baseURL = index === -1 ? "./" : url.substr(0, index + 1); const manager = new dt.LoadingManager(); // Load. return new Promise((resolve, reject) => { manager.setURLModifier((url, path) => { const normalizedURL = rootPath + decodeURI(url) .replace(baseURL, "") .replace(/^(\.?\/)/, ""); if (assetMap.has(normalizedURL)) { const blob = assetMap.get(normalizedURL); const blobURL = URL.createObjectURL(blob); blobURLs.push(blobURL); return blobURL; } return (path || "") + url; }); const loader = new dt.GLTFLoader(manager).setCrossOrigin("anonymous"); loader.setDRACOLoader(new dt.DRACOLoader()); loader.setMeshoptDecoder(MeshoptDecoder); const blobURLs = []; let time = new Date().getTime(); loader.load(url,(gltf) => { const scene = gltf.scene || gltf.scenes[0]; const clips = gltf.animations || []; if (!scene) { throw new Error("This model contains no scene"); } console.log("delta", new Date().getTime() - time); blobURLs.forEach(URL.revokeObjectURL); resolve(gltf); }, undefined, reject ); }); }
总结
通过上述形式,能够写简略工具,帮忙开发和建模人员随时查看模型的状况。
除gltf模型外,其余格局的模型,比方fbx或者obj,也能够相似操作。
如果对可视化感兴趣,能够和我交换,微信541002349。 关注公号“ITMan彪叔” 能够及时收到更多有价值的文章。