什么是 glTF?

  • 3D 扫描数据通常以 OBJ、PLY、STL、FBX 等格式存储。
    • 但是,这些不包括场景结构或渲染方法
    • 由于点云数据采用所谓的“表格格式”,因此它可以具有每个点的属性,但很少有格式会考虑具有面的属性
  • 3D 建模工具(如 Maya)可以在 3ds Max 中以 .max 保存场景的结构、灯光设置、相机、动画、3D 对象体,并在 Blender 中保存 .blend
    • 但是,这些需要创建自己的导入器加载器转换
  • glTF 定义了 3D 内容表示的标准规范,包括以下内容
  • glb官方  glbxz.com  下载glb/gltf格式模型

特征

  • 以 JSON 编写,紧凑且易于解析
  • 3D 对象本身以常用工具可以读取的格式保存

基本结构

  • 3D 场景的全部内容都存储在 JSON 中
  • 它被描述为场景结构,并具有定义场景图的节点层次结构。
  • 场景中显示的 3D 对象使用附加到节点的网格
  • 材质、动漫骨架和摄像机也被定义

各种元素概述

  • scene是存储在 glTF 中的场景描述的入口点。 指向定义场景图的节点
  • node是场景图层次结构中的单个节点。 它可以包括转换(例如,旋转或平移),甚至可以引用(子)节点。 此外,还可以引用“附加”到节点的网格或摄像机的实例,或描述网格变形的蒙皮
  • camera定义用于渲染场景的视图配置
  • mesh描述场景中显示的几何对象。 指用于访问实际几何图形数据的访问器对象,以及定义对象在呈现时的外观的材料
  • skin定义顶点蒙皮所需的参数,并允许根据虚拟角色的姿势对网格进行变形。 这些参数的值是从访问器
  • animation描述特定节点的变形(如旋转或平移)如何随时间变化
  • accessor用作任意数据的抽象源。 它用于网格、皮肤和动画,以提供几何数据、蒙皮参数和与时间相关的动画值。 它引用 bufferView,它是包含实际原始二进制数据的缓冲区的一部分
  • material包含定义对象外观的参数。 它通常是指应用于渲染几何体的纹理对象
  • texture由 Sampler 和 Image 定义。 采样器定义纹理图像在对象上的位置
  • buffer并且是二进制化的,并在外部定义 (.bin/.jpg/.png)image
  • buffer表示几何
  • image表示纹理

最少的 glTF 资产

基于上述内容,以下是最小 glTF:
它是从场景衍生而来的层次结构,因此即使是最小的结构也有点复杂。

{
  "scene": 0,
  "scenes" : [
    {
      "nodes" : [ 0 ]
    }
  ],
  
  "nodes" : [
    {
      "mesh" : 0
    }
  ],
  
  "meshes" : [
    {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : 1
        },
        "indices" : 0
      } ]
    }
  ],

  "buffers" : [
    {
      "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
      "byteLength" : 44
    }
  ],
  "bufferViews" : [
    {
      "buffer" : 0,
      "byteOffset" : 0,
      "byteLength" : 6,
      "target" : 34963
    },
    {
      "buffer" : 0,
      "byteOffset" : 8,
      "byteLength" : 36,
      "target" : 34962
    }
  ],
  "accessors" : [
    {
      "bufferView" : 0,
      "byteOffset" : 0,
      "componentType" : 5123,
      "count" : 3,
      "type" : "SCALAR",
      "max" : [ 2 ],
      "min" : [ 0 ]
    },
    {
      "bufferView" : 1,
      "byteOffset" : 0,
      "componentType" : 5126,
      "count" : 3,
      "type" : "VEC3",
      "max" : [ 1.0, 1.0, 0.0 ],
      "min" : [ 0.0, 0.0, 0.0 ]
    }
  ],
  
  "asset" : {
    "version" : "2.0"
  }
}

各种层次结构的解释

  • 场景和节点
    • scene: 0 表示先读取 scenes 数组的第 0 个索引
    • scenes 中有一个包含节点对象索引的数组,这进一步表明我们想要获取节点的第 0 个索引
  "scene": 0,
  "scenes" : [
    {
      "nodes" : [ 0 ]
    }
  ],
  
  "nodes" : [
    {
      "mesh" : 0
    }
  ],
  • 网孔
    • 表示 3D 几何对象
    • 由于网格往往是臃肿的,因此通常只显示 mesh.primitive 对象的数组,但在示例中,mesh.primitives 直接在网格中描述
    • mesh.primitive 具有 attributes 和 indices,它们具有指示顶点的 POSITION 属性
    • indices 描述指示顶点的索引
 "meshes" : [
    {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : 1
        },
        "indices" : 0
      } ]
    }
  ],
  • 缓冲区
    • buffer 表示原始的非结构化数据块
    • uri 属性指向外部文件或 JSON 文件的二进制数据
      • 换句话说,uri 属性是否包含顶点和三角形信息?
    • 指示有一个包含 44 字节的缓冲区
  "buffers" : [
    {
      "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
      "byteLength" : 44
    }
  ],
  • 缓冲区视图
    • bufferViews 描述要缓冲的视图
    • 两者都有 buffer: 0,所以指定了相同的缓冲区,并且指定的字节不同
  "bufferViews" : [
    {
      "buffer" : 0,
      "byteOffset" : 0,
      "byteLength" : 6,
      "target" : 34963
    },
    {
      "buffer" : 0,
      "byteOffset" : 8,
      "byteLength" : 36,
      "target" : 34962
    }
  ],
  • 访问
    • 指定数据类型和布局,并定义应如何解释 bufferView
  "accessors" : [
    {
      "bufferView" : 0,
      "byteOffset" : 0,
      "componentType" : 5123,
      "count" : 3,
      "type" : "SCALAR",
      "max" : [ 2 ],
      "min" : [ 0 ]
    },
    {
      "bufferView" : 1,
      "byteOffset" : 0,
      "componentType" : 5126,
      "count" : 3,
      "type" : "VEC3",
      "max" : [ 1.0, 1.0, 0.0 ],
      "min" : [ 0.0, 0.0, 0.0 ]
    }
  ],
  • 此外,可以使用访问器的索引引用原语
  "meshes" : [
    {
      "primitives" : [ {
        "attributes" : {
          "POSITION" : 1
        },
        "indices" : 0
      } ]
    }
  ],
  • 实际上,定义起来要复杂得多,但就目前而言,它是

结论

因此,如果你想创建自己的 glTF…
– 节点从场景中
引用 – 节点引用网格
– mesh.primitives 引用缓冲区
– 缓冲区定义 3D 对象的
二进制版本 – 如果要在 bufferView 中读取的范围已定义 – 并且
访问器描述了如何读取
它 – 它将是一个文件

在 Python 中试用

  • 似乎当我尝试使用 Python 的 pygltflib 创建几乎相同的东西时,它看起来像这样
from pygltflib import *

gltf = GLTF2()
scene = Scene()
mesh = Mesh()
primitive = Primitive()
node = Node()
buffer = Buffer()
bufferView1 = BufferView()
bufferView2 = BufferView()
accessor1 = Accessor()
accessor2 = Accessor()

buffer.uri = "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA="
buffer.byteLength = 44

bufferView1.buffer = 0
bufferView1.byteOffset = 0
bufferView1.byteLength = 6
bufferView1.target = ELEMENT_ARRAY_BUFFER

bufferView2.buffer = 0
bufferView2.byteOffset = 8
bufferView2.byteLength = 36
bufferView2.target = ARRAY_BUFFER

accessor1.bufferView = 0
accessor1.byteOffset = 0
accessor1.componentType = UNSIGNED_SHORT
accessor1.count = 3
accessor1.type = SCALAR
accessor1.max = [2]
accessor1.min = [0]

accessor2.bufferView = 1
accessor2.byteOffset = 0
accessor2.componentType = FLOAT
accessor2.count = 3
accessor2.type = VEC3
accessor2.max = [1.0, 1.0, 0.0]
accessor2.min = [0.0, 0.0, 0.0]

primitive.attributes.POSITION = 1
node.mesh = 0
scene.nodes = [0]

gltf.scenes.append(scene)
gltf.meshes.append(mesh)
gltf.meshes[0].primitives.append(primitive)
gltf.nodes.append(node)
gltf.buffers.append(buffer)
gltf.bufferViews.append(bufferView1)
gltf.bufferViews.append(bufferView2)
gltf.accessors.append(accessor1)
gltf.accessors.append(accessor2)

gltf.save("triangle.gltf")

如果你从 3D 中经常使用的 np.ndarray 制作它,它将如下所示
(* 类型似乎很重要,所以需要匹配)verticestriangles

import numpy as np
import pygltflib

points = np.array(
    [
        [-0.5, -0.5, 0.5],
        [0.5, -0.5, 0.5],
        [-0.5, 0.5, 0.5],
        [0.5, 0.5, 0.5],
        [0.5, -0.5, -0.5],
        [-0.5, -0.5, -0.5],
        [0.5, 0.5, -0.5],
        [-0.5, 0.5, -0.5],
    ],
    dtype="float32",
)
triangles = np.array(
    [
        [0, 1, 2],
        [3, 2, 1],
        [1, 0, 4],
        [5, 4, 0],
        [3, 1, 6],
        [4, 6, 1],
        [2, 3, 7],
        [6, 7, 3],
        [0, 2, 5],
        [7, 5, 2],
        [5, 7, 4],
        [6, 4, 7],
    ],
    dtype="uint8",
)

triangles_binary_blob = triangles.flatten().tobytes()
points_binary_blob = points.tobytes()
gltf = pygltflib.GLTF2(
    scene=0,
    scenes=[pygltflib.Scene(nodes=[0])],
    nodes=[pygltflib.Node(mesh=0)],
    meshes=[
        pygltflib.Mesh(
            primitives=[
                pygltflib.Primitive(
                    attributes=pygltflib.Attributes(POSITION=1), indices=0
                )
            ]
        )
    ],
    accessors=[
        pygltflib.Accessor(
            bufferView=0,
            componentType=pygltflib.UNSIGNED_BYTE,
            count=triangles.size,
            type=pygltflib.SCALAR,
            max=[int(triangles.max())],
            min=[int(triangles.min())],
        ),
        pygltflib.Accessor(
            bufferView=1,
            componentType=pygltflib.FLOAT,
            count=len(points),
            type=pygltflib.VEC3,
            max=points.max(axis=0).tolist(),
            min=points.min(axis=0).tolist(),
        ),
    ],
    bufferViews=[
        pygltflib.BufferView(
            buffer=0,
            byteLength=len(triangles_binary_blob),
            target=pygltflib.ELEMENT_ARRAY_BUFFER,
        ),
        pygltflib.BufferView(
            buffer=0,
            byteOffset=len(triangles_binary_blob),
            byteLength=len(points_binary_blob),
            target=pygltflib.ARRAY_BUFFER,
        ),
    ],
    buffers=[
        pygltflib.Buffer(
            byteLength=len(triangles_binary_blob) + len(points_binary_blob)
        )
    ],
)
gltf.set_binary_blob(triangles_binary_blob + points_binary_blob)

现在应该能够输出所需的 glTF。
有关如何使用它的更多信息,请参阅官方 README。

 

扩展和附加功能

"nodes" : [
    {
        "extensions" : {
            "KHR_lights_punctual" : {
                "light" : 0
            }
        }
    }            
]
  • 除此之外,还有一个名为 extras 的自由格式扩展,可以将其添加到任何属性中,例如网格、缓冲区或节点
  "nodes": [
    {
      "extras": {
        "id": "0a4a5478b66849b3890a3d5b1de98e18",
        "name": "\u307f\u3069\u308a\u306e\u7a93\u53e3"
      },
      "mesh": 0
    }
  ],
  • 在 Blender 中,你可以通过将其添加到 Node 的 extras 来引用它。

结论

如开头所述,大多数 3D 数据格式不能被视为 3D GIS 数据,因为它们不具备这样的功能,只具有保持面的功能。属性

但是,使用 glTF,您可以使用扩展函数自由保留属性,因此可以执行 3D GIS 分析。

从此,就是 glTF 的时代!

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,请不要用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性

GLB下载网(glbxz.com)gltf文件下载-glb格式下载-模型制作 » 现在您已经完全了解了 glTF,请尝试在 Python 中创建 glTF/glb

常见问题FAQ

免费下载或者VIP会员专享资源能否直接商用?
本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
提示下载要提取码
百度网盘提取码都是gltf。
分享过期和重复下载怎么办
分享过期请使用备份下载,重复下载是不另扣费的,请放心下载。
模型和平台不兼容怎么办
可以用网站在线编辑功能,修改模型属性,大小,方向,坐标,中心,透明等问题,然后重新导出既可https://glbxz.com/38636.html
  • 9466会员数(个)
  • 16906资源数(个)
  • 24本周更新(个)
  • 39284 今日更新(个)
  • 1298稳定运行(天)

提供最优质的资源集合

加入VIP
开通VIP 享更多特权,建议使用 QQ 登录
×