举例说明三者的关系
{
"asset": {
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [0]
}
],
"nodes": [
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"POSITION": 0 // 通过索引为 0 的accessor获取具体的顶点数据
},
"indices": 1 // 通过索引为 1 的accessor获取具体的索引数据
}
]
}
],
"accessors": [
{
// 第一个 accessor 指向顶点的位置
// 它的 byteOffset 是 0,表示它从所属的 bufferView 的起始位置开始
// 它的 count 是 3,表示它包含 3 个元素(每个元素是一个 vec3)
// 它的 componentType 是 5126 (FLOAT),表示每个分量是一个 32 位浮点数
// 它的 type 是 VEC3,表示每个元素是一个包含三个分量的向量
// 它没有 min 或 max 属性,因为这个属性不需要它们
// 这个 accessor 的数据存储在索引为 0 的 bufferView 中
"bufferView" : 0,
"byteOffset" : 0,
"componentType" : 5126,
"count" : 3,
"type" : "VEC3"
},
{
// 第二个 accessor 指向三角形的索引
// 它的 byteOffset 是 0,表示它从所属的 bufferView 的起始位置开始
// 它的 count 是 3,表示它包含 3 个元素(每个元素是一个标量)
// 它的 componentType 是 5125 (UNSIGNED_INT),表示每个分量是一个无符号 32 位整数
// 它的 type 是 SCALAR,表示每个元素只有一个分量
// 它没有 min 或 max 属性,因为这个属性不需要它们
// 这个 accessor 的数据存储在索引为 1 的 bufferView 中
"bufferView" : 1,
"byteOffset" : 0,
"componentType" : 5125,
"count" : 3,
"type" : "SCALAR"
}
],
"bufferViews": [
{
// 第一个 bufferView 指向顶点位置数据
// 它的 buffer 是 0,表示它所属的 buffer 的索引是 0
// 它的 byteOffset 是 0,表示它从所属的 buffer 的起始位置开始
// 它的 byteLength 是 36,表示它包含了 36 字节的数据(3 * (3 * sizeof(float)))
// 它没有 byteStride 属性,因为这个 bufferView 只被一个 accessor 引用
"buffer" : 0,
"byteOffset" : 0,
"byteLength" : 36
},
{
// 第二个 bufferView 指向三角形索引数据
// 它的 buffer 是 0,表示它所属的 buffer 的索引是 0
// 它的 byteOffset 是 36,表示它从所属的 buffer 的第 36 字节开始(紧接着第一个 bufferView 的数据)
// 它的 byteLength 是 12,表示它包含了 12 字节的数据(3 * sizeof(uint32))
// 它没有 byteStride 属性,因为这个 bufferView 只被一个 accessor 引用
"buffer" : 0,
"byteOffset" : 36,
"byteLength" : 12
}
],
"buffers": [
{
// 这个文件只有一个 buffer,包含了所有的顶点位置和三角形索引数据
// 它的 uri 是 data:application/octet-stream;base64,... 表示它是一个 base64 编码的内嵌数据
// 它的 byteLength 是 48,表示它包含了 48 字节的数据(36 + 12)
"uri" : "data:application/octet-stream;base64,...",
"byteLength" : 48
}
]
}
bufferView中的byteStride属性
byteStride 属性是用来表示在一个 bufferView 中,相邻两个元素之间的字节间隔。这个属性在 bufferView 被多个 accessor 引用时,或者 bufferView 中的数据是交错存储的时候,比如位置和法线属性,是有用的1。
举个例子,如果一个 bufferView 包含了三个顶点的位置和法线数据,每个顶点的位置和法线都是一个 vec3(12 字节),那么这个 bufferView 的 byteLength 是 72(3 * (12 + 12))。如果我们想要分别引用位置和法线数据,我们可以创建两个 accessor,一个指向位置数据,一个指向法线数据。这两个 accessor 都属于同一个 bufferView,但是它们的 byteOffset 不同。位置数据的 byteOffset 是 0,法线数据的 byteOffset 是 12。同时,这个 bufferView 的 byteStride 是 24(12 + 12),表示每两个相邻顶点之间有 24 字节的间隔。