GLTF格式解析

前置知识:GLB文件格式解析GLTF文件格式解析 (baidu.com)

glb格式解析 | 码农家园 (codenong.com)

3D性能优化 | 说一说glTF文件压缩 - 知乎 (zhihu.com)

glTF格式详解(目录) - 知乎 (zhihu.com)

1 GLTF文件

{
  "accessors": [
    {
      "bufferView": 0,
      "componentType": 5126,
      "count": 3575,
      "type": "VEC2",
      "max": [
        0.9999003,
        -0.0221377648
      ],
      "min": [
        0.0006585993,
        -0.996773958
      ]
    },
    {
      "bufferView": 1,
      "componentType": 5126,
      "count": 3575,
      "type": "VEC3",
      "max": [
        1.0,
        1.0,
        0.9999782
      ],
      "min": [
        -1.0,
        -1.0,
        -0.9980823
      ]
    },
    {
      "bufferView": 2,
      "componentType": 5126,
      "count": 3575,
      "type": "VEC4",
      "max": [
        1.0,
        0.9999976,
        1.0,
        1.0
      ],
      "min": [
        -0.9991289,
        -0.999907851,
        -1.0,
        1.0
      ]
    },
    {
      "bufferView": 3,
      "componentType": 5126,
      "count": 3575,
      "type": "VEC3",
      "max": [
        0.009921154,
        0.00977163,
        0.0100762453
      ],
      "min": [
        -0.009921154,
        -0.00977163,
        -0.0100762453
      ]
    },
    {
      "bufferView": 4,
      "componentType": 5123,
      "count": 18108,
      "type": "SCALAR",
      "max": [
        3574
      ],
      "min": [
        0
      ]
    }
  ],
  "asset": {
    "generator": "glTF Tools for Unity",
    "version": "2.0"
  },
  "bufferViews": [
    {
      "buffer": 0,
      "byteLength": 28600
    },
    {
      "buffer": 0,
      "byteOffset": 28600,
      "byteLength": 42900
    },
    {
      "buffer": 0,
      "byteOffset": 71500,
      "byteLength": 57200
    },
    {
      "buffer": 0,
      "byteOffset": 128700,
      "byteLength": 42900
    },
    {
      "buffer": 0,
      "byteOffset": 171600,
      "byteLength": 36216
    }
  ],
  "buffers": [
    {
      "uri": "BoomBox.bin",
      "byteLength": 207816
    }
  ],
  "images": [
    {
      "uri": "BoomBox_baseColor.png"
    },
    {
      "uri": "BoomBox_occlusionRoughnessMetallic.png"
    },
    {
      "uri": "BoomBox_normal.png"
    },
    {
      "uri": "BoomBox_emissive.png"
    }
  ],
  "meshes": [
    {
      "primitives": [
        {
          "attributes": {
            "TEXCOORD_0": 0,
            "NORMAL": 1,
            "TANGENT": 2,
            "POSITION": 3
          },
          "indices": 4,
          "material": 0
        }
      ],
      "name": "BoomBox"
    }
  ],
  "materials": [
    {
      "pbrMetallicRoughness": {
        "baseColorTexture": {
          "index": 0
        },
        "metallicRoughnessTexture": {
          "index": 1
        }
      },
      "normalTexture": {
        "index": 2
      },
      "occlusionTexture": {
        "index": 1
      },
      "emissiveFactor": [
        1.0,
        1.0,
        1.0
      ],
      "emissiveTexture": {
        "index": 3
      },
      "name": "BoomBox_Mat"
    }
  ],
  "nodes": [
    {
      "mesh": 0,
      "name": "BoomBox"
    }
  ],
  "scene": 0,
  "scenes": [
    {
      "nodes": [
        0
      ]
    }
  ],
  "textures": [
    {
      "source": 0
    },
    {
      "source": 1
    },
    {
      "source": 2
    },
    {
      "source": 3
    }
  ]
}

bufferViews":有好几个,为什么每个都设置 "buffer": 0, 这个“buffer”指的啥???

GLTF格式用于描述3D模型和场景的信息。
在您提供的JSON示例中,
`buffers`,`bufferViews`和`accessors`协同工作以描述3D模型的顶点和其他数据。

### Buffers
- **Buffers** 是存储实际的二进制数据的地方。在这个例子中,
`"uri": "BoomBox.bin"` 指明了buffer的位置,
`"byteLength": 207816` 描述了buffer的长度。

```json
"buffers": [
    {
      "uri": "BoomBox.bin",
      "byteLength": 207816
    }
]
```

### BufferViews
- **BufferViews** 描述了如何从buffer中查看数据。
每个`bufferView`有一个`byteOffset`来描述从buffer的哪个位置开始,
以及`byteLength`来描述view的长度。`"buffer": 0` 指明了该`bufferView`
是从第一个(也是唯一一个)buffer中查看的。

```json
"bufferViews": [
    {
      "buffer": 0,
      "byteLength": 28600
    },
    ...
]
```

### Accessors
- **Accessors** 则进一步描述了如何从`bufferView`中解读数据。
它会定义component的类型,例如,是否是一个VEC3或者SCALAR,
以及数据的类型,例如,是否是FLOAT。它还会包含一些有关数据的其他信息,例如min和max值。

```json
"accessors": [
    {
      "bufferView": 0,
      "componentType": 5126,
      "count": 3575,
      "type": "VEC2",
      ...
    },
    ...
]
```

### 为什么每个 BufferView 的 `"buffer": 0` ?
在您的JSON示例中,所有的`bufferViews`都有`"buffer": 0`,
这是因为所有的`bufferViews`都是从同一个buffer中提取的,
也就是上述`buffers`数组中的第一个(并且是唯一的)buffer。

如果您的GLTF文件中有多个buffer,那么您将会看到不同的`bufferViews`
关联到不同的buffer。例如,如果有一个`bufferView`从第二个buffer中
提取数据,那么它将会有`"buffer": 1`。

"accessors": [ { "bufferView": 0, "componentType": 5126, "count": 3575, "type": "VEC2", ... }, ... ]

这accessors中的每一个bufferView可以重复吗,比如accessors三个孩子,bufferView分别为0,1,1???

  比如这种文件

{"asset":{"generator":"COLLADA2GLTF","version":"2.0"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"children":[1],"matrix":[1.0,0.0,0.0,0.0,0.0,0.0,-1.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0]},{"mesh":0}],"meshes":[{

"primitives":[{"attributes":{"NORMAL":1,"POSITION":2},"indices":0,"mode":4,"material":0}],"name":"Mesh"}],

"accessors":[

{"bufferView":0,"byteOffset":0,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":24,"max":[1.0,1.0,1.0],"min":[-1.0,-1.0,-1.0],"type":"VEC3"},{"bufferView":1,"byteOffset":288,"componentType":5126,"count":24,"max":[0.5,0.5,0.5],"min":[-0.5,-0.5,-0.5],"type":"VEC3"}]

,"materials":[{"pbrMetallicRoughness":{"baseColorFactor":[0.800000011920929,0.0,0.0,1.0],"metallicFactor":0.0},"name":"Red"}],

"bufferViews":[
{"buffer":0,"byteOffset":576,"byteLength":72,"target":34963},
{"buffer":0,"byteOffset":0,"byteLength":576,"byteStride":12,"target":34962}],
"buffers":[{"byteLength":648}]}
是的,`accessors`中的`bufferView`可以重复。每个`accessor`定义了
如何解读存储在`bufferView`中的数据。不同的`accessor`可以使用相同
的`bufferView`,但可能会有不同的`byteOffset`、`componentType`、
`count`或`type`,以便以不同的方式解读相同的数据,或解读该`bufferView`
中的不同部分数据。

举个例子,假设我们有两个`accessor`,它们都指向`bufferView` 1,但
一个是解读VEC3类型数据,另一个是解读SCALAR类型数据。那么,这两个
`accessor`将会从相同的`bufferView`中提取不同类型和格式的数据。

```json
"accessors": [
    {
      "bufferView": 1,
      "componentType": 5126,
      "count": 1000,
      "type": "VEC3"
    },
    {
      "bufferView": 1,
      "componentType": 5123,
      "count": 2000,
      "type": "SCALAR"
    }
]
```

在这个例子中,即便两个`accessor`都引用了`bufferView` 1,但由于
它们有不同的`type`和`componentType`,它们将会以不同的方式解读
`bufferView`中的数据。

2 GLB文件并进行了Draco压缩

glTF   T	  ?  JSON{
  "asset": {
    "version": "2.0",
    "generator": "draco_decoder"
  },
  "scenes": [
    {
      "nodes": [
        0
      ]
    }
  ],
  "scene": 0,
  "nodes": [
    {
      "children": [
        1
      ],
      "matrix": [
        1,
        0,
        0,
        0,
        0,
        0,
        -1,
        0,
        0,
        1,
        0,
        0,
        0,
        0,
        0,
        1
      ]
    },
    {
      "mesh": 0
    }
  ],
  "meshes": [
    {
      "primitives": [
        {
          "attributes": {
            "NORMAL": 2,
            "POSITION": 1
          },
          "indices": 0,
          "mode": 4,
          "material": 0,
          "extensions": {
            "KHR_draco_mesh_compression": {
              "bufferView": 0,
              "attributes": {
                "NORMAL": 0,
                "POSITION": 1
              }
            }
          }
        }
      ]
    }
  ],
  "materials": [
    {
      "pbrMetallicRoughness": {
        "baseColorFactor": [
          0.800000011920929,
          0,
          0,
          1
        ],
        "metallicFactor": 0,
        "roughnessFactor": 1
      },
      "emissiveFactor": [
        0,
        0,
        0
      ],
      "alphaMode": "OPAQUE"
    }
  ],
  "accessors": [
    {
      "componentType": 5121,
      "count": 36,
      "normalized": false,
      "max": [
        23
      ],
      "min": [
        0
      ],
      "type": "SCALAR"
    },
    {
      "componentType": 5126,
      "count": 24,
      "normalized": false,
      "max": [
        0.5,
        0.5,
        0.5
      ],
      "min": [
        -0.5,
        -0.5,
        -0.5
      ],
      "type": "VEC3"
    },
    {
      "componentType": 5126,
      "count": 24,
      "normalized": false,
      "max": [
        1,
        1,
        1
      ],
      "min": [
        -1,
        -1,
        -1
      ],
      "type": "VEC3"
    }
  ],
  "bufferViews": [
    {
      "buffer": 0,
      "byteOffset": 0,
      "byteLength": 152
    }
  ],
  "buffers": [
    {
      "byteLength": 152
    }
  ],
  "extensionsRequired": [
    "KHR_draco_mesh_compression"
  ],
  "extensionsUsed": [
    "KHR_draco_mesh_compression"
  ]
}
 ?   BIN DRACO    	

	

	   	  ??鱑?喊﹤        ???鏌?I)?皷 ?         ?   ?   ?  €?  
这段 JSON 是 glTF(GL Transmission Format)格式的,一个用于
 3D 场景和模型的传输格式。这个例子中使用了 Draco 压缩,这是一
种几何图形压缩方法,可以大幅减小 3D 模型的文件大小。

以下是该 JSON 文件的组织结构:

1. **asset**
   - 描述了 glTF 资源的信息,比如版本和生成器。

2. **scenes**
   - 定义了 3D 场景的列表,其中包含了场景所包含的节点(nodes)。

3. **scene**
   - 表示当前要展示的场景。

4. **nodes**
   - 定义了场景中的节点列表,其中每个节点可能包含子节点、网格、变换矩阵等。

5. **meshes**
   - 定义了网格的列表。每个网格都包含了一组 primitive,每个 primitive 
都有自己的 attributes,如位置、法线等。

6. **materials**
   - 定义了场景中使用的材料的属性。

7. **accessors**
   - 定义了如何从 bufferView 中访问数据,包含了类型、数量等信息。

8. **bufferViews**
   - 定义了如何在 buffer 中访问原始二进制数据。

9. **buffers**
   - 存储了原始二进制数据的长度信息。

10. **extensionsRequired 和 extensionsUsed**
    - 定义了此 glTF 模型所需和所用的扩展,本例中使用了 Draco 压缩的扩展。

### Draco 压缩

在这个例子中,`"KHR_draco_mesh_compression"` 扩展被使用,表示模型数据经
过了 Draco 压缩。压缩后的数据存储在 `buffer` 中。Draco 压缩的具体信息是
在每个 `primitive` 的 `extensions` 字段中定义的:

```json
"extensions": {
  "KHR_draco_mesh_compression": {
    "bufferView": 0,
    "attributes": {
      "NORMAL": 0,
      "POSITION": 1
    }
  }
}
```

这里的 `bufferView` 指向包含压缩数据的 `bufferView`,而 `attributes` 定义
了属性类型和对应的索引,这些索引对应于 Draco 压缩数据中的属性。

总而言之,这个 JSON 文件定义了一个 glTF 场景,其中包含了节点、网格、材料、访
问器、缓冲视图和缓冲器,以及 Draco 压缩的扩展,以减小 3D 模型的文件大小。 若
要渲染这个 3D 模型,需要按照定义在访问器和缓冲视图中的信息,从缓冲中获取原始
数据,然后解压 Draco 压缩的数据,最后应用材料并将其放入场景中。

indices是怎么来的,我看其他glb文件有的是1,有的是2???

在 glTF 结构中,`primitives`字段定义了如何将顶点属性组合成几何图元。
每个`primitive`都包含一个`attributes`对象,`attributes`对象定义了
一组`accessor`,这些`accessor`引用了包含实际几何数据的缓冲区视图
(`bufferView`)。`indices`字段则是一个指向`accessor`的索引,这个
`accessor`包含了组成这些几何图元的索引。

- `"indices": 0`表示用来组成几何图元的索引存储在`accessors`数组的第一个元素中。
- `"indices": 1`表示索引存储在`accessors`数组的第二个元素中。
- `"indices": 2`表示索引存储在`accessors`数组的第三个元素中。

以此类推。这个`indices`引用的`accessor`定义了如何从`attributes`指定的
顶点属性中索引值,来组成三角形或其他几何图元。

例如,如果您有以下几何结构:
```
"accessors": [
    { ... }, // 0: indices
    { ... }, // 1: POSITION
    { ... }  // 2: NORMAL
],
"primitives": [
    {
      "attributes": {
        "POSITION": 1,
        "NORMAL": 2
      },
      "indices": 0,
    }
]
```

在这个例子中,`indices`是`0`,意味着`accessors`数组的第一个元素包含了
组成几何图元的索引。而`POSITION`和`NORMAL`属性分别由`accessors`数组的
第二个和第三个元素提供。

所以,如果您在不同的glTF或glb文件中看到不同的`indices`值,这仅仅是因为
这些索引存储在`accessors`数组中不同的位置。这并不会影响最终模型的几何
结构,因为`indices`和`attributes`的组合提供了完整的几何定义。

你可能感兴趣的:(图像算法与c++,c++,算法)