GLTF简介

一、什么是gltf

  • GLTF代表 Graphics Language Transmission Format(图形语言传输格式)。这种跨平台格式已成为Web上的3D对象标准。
  • 几乎每个框架都支持GLTF,3D模型可以优选GLTF格式。
  • GLTF是对近二十年来各种3D格式的总结,使用最优的数据结构,来保证最大的兼容性以及可伸缩性。GLTF使用json格式进行描述(本质是一个json文件)。GlTF可以包括场景、摄像机、动画等,也可以包括网格、材质、纹理,甚至包括了渲染技术、着色器以及着色器程序。由于json格式的特点,它支持预留一般以及特定供应商的扩展。

1. gltf的两种存储方式

  • 嵌入式(所有的数据都在xxx.gltf的文件中);
  • 分离式(gltf+bin+image);

2. glb与gltf的关系

GLB文件是.GLTF文件的二进制版本。

glTF是一种高效、可扩展、可互操作的格式,用于传输和加载3D场景和模型。glTF格式的目标包括最大限度地减少文件大小、快速加载、完整的3D场景表示、运行时独立性以及伴随进一步开发的可扩展性。glTF的提出是源自于3D工业和媒体发展的过程中,对3D格式统一化的急迫需求。

GLB是glTF模型的二进制文件格式表示,它存储了glTF的组件,如JSON、BIN文件和图片。GLB避免了使用glTF格式文件变大的问题,通过压缩,GLB能更快地加载,提供完整的三维场景,且能在未来的开发中扩展。



二、gltf的组织架构

在这里插入图片描述

  • scene: 场景,一个gltf文件中可能存储多个场景,每个场景都包含一个或者多个node;
  "scene":0,
  "scenes":[
    {
      "name":"Scene",
      "nodes":[
        2
      ]
    }
  ],
  • node:场景图层次结构中的一个节点,每个节点都node可以包含一个名为 的数组children,该数组包含其子节点的索引(也就是说,第三个node节点可以包含前两个node节点的信息);
"nodes":[
    {
      "mesh":0,
      "name":"Object_2"
    },
    {
      "children":[
        0
      ],
      "name":"apple_test_scale2.obj.cleaner.materialmerger.gles"
    },
    {
      "children":[
        1
      ],
      "name":"Sketchfab_model",
      "rotation":[
        -0.70710688829422,
        0,
        0,
        0.7071066498756409
      ]
    }
  ],
  • camera:渲染场景的视图配置;
  • mesh:表示场景中的几何对象,它包含:accessor是用于访问实际几何数据的对象,material几何对象渲染时的外观对象;
  • skin:顶点参数信息,来源:accessor;
  • animation:节点变化(如:旋转、平移);
  • accessor:抽象数据源,数据访问器(mesh、skin、animation的数据来源);
  • material:定义几何对象外观参数;
  • texture:包含sampler和image,其使用source和sampler指向图片和采样器;
  • images:通过 uri定位到图片资源
  • sampler:定义图片的采样和滤波方式

gltf格式详解:
译文:https://zhuanlan.zhihu.com/p/65267849
原文:https://github.com/fangcun010/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_003_MinimalGltfFile.md

补充小知识:

  1. bufferViews中的target对应的数值表示数据在buffer中的组织形式:
    渲染器可以使用此属性来分类缓冲区视图所引用的数据的类型或性质。target可以是一个常量指示数据是用于顶点属性(34962,表示ARRAY_BUFFER),或者该数据被用于顶点索引(34963,表示ELEMENT_ARRAY_BUFFER);

  2. 材质与贴图的区别:
    材质包括贴图,材质是一个数据集,主要功能就是给渲染器提供数据和光照算法。贴图就是其中数据的一部分。材质是基础,细节靠纹理和贴图来呈现。
    材质用来指定物体的表面或数个面的特性,它决定这些平面在着色时的特性,如颜色,光亮程度,自发光度及不透明度等;制定到材质上的图形则称为贴图。



三、glb转gltf

安装gltf-pipeline工具

参考来源:https://npmmirror.com/package/gltf-pipeline

全局安装方式:

npm install -g gltf-pipeline

gltf转换成glb

gltf-pipeline -i model.gltf -o model.glb
gltf-pipeline -i model.gltf -b

glb转换成gltf

gltf-pipeline -i model.glb -o model.gltf
gltf-pipeline -i model.glb -j

单独输出模型的贴图文件

gltf-pipeline -i model.gltf -t


四、glb中贴图的替换

    public String replaceGltfTexture(String gltfURL, String textureURL) {
        File tempFile = null;
        File tempGltf = null;
        try {
            //1.解析数据,获取glb模型对象
            GltfModelReader modelReader = new GltfModelReader();
            DefaultGltfModel gltfModel = (DefaultGltfModel) modelReader.read(new URI(gltfURL));

            //2.材质对象
            //根据修改的材质的索引信息获取贴图的对象,meshIndex(修改的材质在模型中meshes数组的索引值)meshPrimitiveIndex (材质中primitives修改的primitive的第几个索引值)
            MaterialModelV2 materialModel =
                    (MaterialModelV2) gltfModel.getMeshModel(0).getMeshPrimitiveModels().get(0).getMaterialModel();

            //3.贴图对象
            DefaultTextureModel baseColorTexture = (DefaultTextureModel) materialModel.getBaseColorTexture();

            //4.换贴图  xxx.png贴图文件
            replaceMaterialImage(gltfModel, textureURL, baseColorTexture);

            //5.将更换贴图的模型输出
            GltfModelWriter gltfModelWriter = new GltfModelWriter();
            tempFile = File.createTempFile("模型文件贴图替换", System.nanoTime() + ".glb");
            gltfModelWriter.writeBinary(gltfModel, tempFile);

            //6.glb转成gltf文件
            tempGltf = new File("/tmp/" + tempFile.getName().substring(0, tempFile.getName().lastIndexOf(".")) + ".gltf");
            if (!tempFile.exists()) {
                tempGltf.createNewFile();
            }

            log.info("命令执行前:{}", tempFile);
            String[] cmd = {"gltf-pipeline", "-i", tempFile.getAbsolutePath(), "-o", tempGltf.getAbsolutePath()};
            Process process =
                    Runtime.getRuntime().exec(cmd);

            BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String readLine = br.readLine();
            StringBuilder builder = new StringBuilder();
            while (readLine != null) {
                readLine = br.readLine();
                builder.append(readLine);
            }
            log.error( "#readLine error: " + builder);

            process.waitFor();

            log.info("命令执行后:{}", tempGltf);

			//oss上传
            return ossOperateFacade.upload("xxx/", tempGltf.getAbsolutePath(), "时间");
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (tempFile != null) {
                tempFile.delete();
            }
            if (tempGltf != null) {
                tempGltf.delete();
            }
        }
        return null;
    }

    private void replaceMaterialImage(DefaultGltfModel gltfModel, String imageUrl, DefaultTextureModel baseColorTexture) {
        String imageFormat = imageUrl.substring(imageUrl.lastIndexOf(".") + 1);
        String imageName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
        if ("jpg".equalsIgnoreCase(imageFormat)) {
            imageFormat = "jpeg";
        }

        byte[] bytes = imageBytes(imageUrl);
        ByteBuffer imageData = ByteBuffer.wrap(bytes);
        imageDetailWith(gltfModel, baseColorTexture, imageFormat, imageData, imageName);
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值