如何将OBJ文件转成GLB文件
背景
项目上需要展示3D矿图效果,当时前端框架选用了three.js进行渲染引擎,成功的满足了需求进行效果展示,但在后期一直有性能问题的困扰,前端同学做了一些优化,包括分布加载、采用nginx请求头缓存配置、浏览器缓存等机制。
在实践中,我们发现glb格式要比obj格式的文件小一些,此外,obj在加载的过程也容易丢失样式、纹理等文件,由于obj模型文件通常为一组格式mlt(纹理、样式)、png(贴图),因此在做前端浏览器缓存时,也存在问题,后来和前端同学商量后,我们决定将obj转成glb进行尝试。
两种文件格式简介
obj文件
obj文件专注于存储3D模型的几何数据(顶点、纹理坐标、法线等),通过纯文本描述模型结构,是一组可读的文本语句,eg:v表示顶点定义模型;ojb会依赖外部文件,材质信息需客外MTL文件存储,不支持动画功能,支持贴图文件,png/jpeg
glb文件
GLB 是GLTF标准的二进制版本,全称为“GL传输格式二进制文件”,将3D模型、纹理、材质、动画甚至场景光源打包为单一二进制文件。是一体化封装文件,所有资源饭知JSON元数据、纹理等都可以整合一体,其设计目标就是快速加载与高效解析,适配WEB和移动端
对比维度 | OBJ | GLB |
---|---|---|
文件大小 | 文本格式冗余,所以文件相对大 | 二进制压缩,相对小 |
功能支持 | 无动画/场景支持 | 支持动画、光照、相机视角 |
文件可读性 | 文本格式易上手 | 二进制文件难理解难编辑 |
兼容性 | 广泛支持(3D打印/建模软件) | 主流引擎/WebGL原生支持 |
材质管理 | 需额外的MLT、PNG | 内嵌纹理与材制裁 |
经上对比,综述,GLB支持WEB集成,体积更小,减少带宽消耗,如果追求轻量、动画支持可首选GLB格式
转换方式
选用Node插件进行转换,首先可以用npm install obj2gltf安装插件,然后通过命令进行转换
# 安装node插件
npm install obj2gltf
# 格式转换命令
obj2gltf -i 源文件.obj -o 目标文件.glb
示例如下所示:
# 示例如下
obj2gltf -i D:\data\mainMap\主要系统巷道\主要大巷.3dmobj\主要大巷_offset.obj -o D:\data\mainMap\主要系统巷道\主要大巷.3dmobj\主要大巷.glb
这个搞定了,剩的工作就简单了,如何动达转换呢,我们可以通过Java程序监听指定目录的新增、修改操作,然后对其变化的文件执行脚本调用,进行转换,思路有了,来码代码,先容我再啰嗦两句,把步骤描述如下所示:
1 、obj2gltf是通过npm install obj2gltf安装的插件,用于模型格式转换操作
2、包下的node_module是将npm install 时产生的所有npm依赖都copy进去了。否则缺少依赖;
3、application.yml 中需要配置脚本文件的绝对路径,需引用obj2gltf下的bin下的obj2gltf.js
4、java 引入Pom依赖
5、JAVA调用IO包中的Process类执行命令脚本
代码结果如下所示:
obj2gltf -i D:\data\mainMap\主要系统巷道\主要大巷.3dmobj\主要大巷_offset.obj -o D:\data\mainMap\主要系统巷道\主要大巷.3dmobj\主要大巷.glb
写了一个转换工具类,参数如下所示:
pom.xml依赖
<dependency><groupId>de.javagl</groupId><artifactId>jgltf-model</artifactId><version>2.0.0</version></dependency><!-- https://mvnrepository.com/artifact/de.javagl/obj --><dependency><groupId>de.javagl</groupId><artifactId>obj</artifactId><version>0.3.0</version></dependency>
写一个Util工具类
package com.zhanglu.test.handle.util;import com.zhanglu.test..handle.obj2gltf.ConvertObjToGltf;
import com.zhanglu.test..handle.obj2gltf.obj.BufferStrategy;
import com.zhanglu.test..handle.obj2gltf.obj.GltfWriteType;
import com.zhanglu.test..handle.obj2gltf.obj.IndicesComponentType;
import lombok.extern.slf4j.Slf4j;import java.io.BufferedReader;
import java.io.InputStreamReader;
@Slf4j
@SuppressWarnings("all")
public class NodeJsExcutorUtil {public static void convertObjToGlb(String objPath,String glbPath,String scriptPath) {BufferedReader reader = null;try {// 构建命令(根据安装方式调整)String[] command = {"node", //本地windows启动不加这个命令,不然会报错scriptPath, // 局部安装使用 npx"-i", objPath.trim(),"-o", glbPath.trim()};ProcessBuilder builder = new ProcessBuilder(command);System.out.println(builder.command());builder.redirectErrorStream(true); // 将错误输出和标准输出合并,便于读取Process process = builder.start();reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"utf-8"));String line;while ((line = reader.readLine()) != null) {log.info(line);}process.waitFor(); // 等待进程结束log.info("【glb文件】转换成功");} catch (Exception err) {err.printStackTrace();log.error("【glb文件】转换失败:{}",err.getMessage());}finally {try {if (reader != null) {reader.close();}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {//本地如果是windows环境用以下脚本String scriptPath = "D:\\web\\node_modules\\.bin\\obj2gltf.cmd"; //如果是Linux脚本用以下脚本 // String scriptPath = "scriptPath: /data/webapp/calamity/handle/obj2gltf/bin/obj2gltf.js";String objPath="D:\\data\\mainMap\\主要系统巷道\\主要大巷.3dmobj\\主要大巷.obj";String glbPath="D:\\data\\mainMap\\主要系统巷道\\主要大巷.3dmobj";String glbFilePath="D:\\data\\mainMap\\主要系统巷道\\主要大巷.3dmobj\\主要大巷_1.glb";NodeJsExcutorUtil.convertObjToGlb(objPath,glbFilePath,scriptPath);}
}
以上代码需要注意
Linux环境脚本引用说明
Linux环境脚本路径node安装obj2gltf包下的:obj2gltf/bin/obj2gltf.js;
命令:node /脚本实际路径/obj2gltf.js -i objFile.obj -o glbFile.glb
windows环境脚本引用说明
Windows 环境脚本路径node安装obj3gltf包下:node_modules\\.bin\\obj2gltf.cmd
命令: /脚本实际路径/obj2gltf.cmd -i objFile.obj -o glbFile.glb