翻译glTF文档中的交叉数据这一段以及二进制读写生续的解释

一世执手 提交于 2020-01-09 16:42:06

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

  • Data interleaving 数据交错 存储在单个bufferView中的属性的数据视图可以存储为结构数组。例如,单个bufferView 可以以交错方式包含顶点位置和顶点法线的数据。在这种情况下,访问器的字节偏移定义相应属性的第一个相关数据元素的开头,bufferView 定义一个额外的字节步长属性。这是其访问器的一个元素的开头和下一个元素的开头之间的字节数。下图中显示了如何在bufferView中存储交错位置和法线属性的示例。

    图中可以看到byteStride为24, 这个值存在bufferView这个元素里面.

  • Data contents 数据内容 accessor还包含汇总其数据内容的最小和最大属性。它们是accessor中包含的所有数据元素的组件最小值和最大值。因此,在顶点位置的情况下,最小和最大值属性定义对象的边界框。这对于确定下载优先级或可见性检测非常有用。通常,此信息对于存储和处理在运行时由呈现器取消量化的量化数据也很有用,但此量化的详细信息超出了本教程的范围。

  • Sparse accessors 稀疏访问器 在版本 2.0 中,在 glTF 中引入了稀疏访问器的概念。这是数据的特殊表示形式,允许非常紧凑的存储多个数据块,这些数据块只有几个不同的条目。例如,当存在包含顶点位置的几何数据时,此几何数据可用于多个对象。这可以通过从两个对象引用同一个访问器来实现。如果两个对象的顶点位置基本相同,并且只有几个顶点不同,则不必将整个几何数据存储两次。相反,可以只存储一次数据,并使用稀疏访问器仅存储第二个对象的顶点位置。

下面是一个完整的 glTF 资产(以嵌入式表示形式)显示稀疏访问器的示例:

{
  "scenes" : [ {
    "nodes" : [ 0 ]
  } ],
  
  "nodes" : [ {
    "mesh" : 0
  } ],
  
  "meshes" : [ {
    "primitives" : [ {
      "attributes" : {
        "POSITION" : 1
      },
      "indices" : 0
    } ]
  } ],
  
  "buffers" : [ {
    "uri" : "data:application/gltf-buffer;base64,AAAIAAcAAAABAAgAAQAJAAgAAQACAAkAAgAKAAkAAgADAAoAAwALAAoAAwAEAAsABAAMAAsABAAFAAwABQANAAwABQAGAA0AAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAQAAAAAAAAAAAAABAQAAAAAAAAAAAAACAQAAAAAAAAAAAAACgQAAAAAAAAAAAAADAQAAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAQAAAgD8AAAAAAABAQAAAgD8AAAAAAACAQAAAgD8AAAAAAACgQAAAgD8AAAAAAADAQAAAgD8AAAAACAAKAAwAAAAAAIA/AAAAQAAAAAAAAEBAAABAQAAAAAAAAKBAAACAQAAAAAA=",
    "byteLength" : 284
  } ],
  
  "bufferViews" : [ {
    "buffer" : 0,
    "byteOffset" : 0,
    "byteLength" : 72,
    "target" : 34963
  }, {
    "buffer" : 0,
    "byteOffset" : 72,
    "byteLength" : 168
  }, {
    "buffer" : 0,
    "byteOffset" : 240,
    "byteLength" : 6
  }, {
    "buffer" : 0,
    "byteOffset" : 248,
    "byteLength" : 36
  } ],
  
  "accessors" : [ {
    "bufferView" : 0,
    "byteOffset" : 0,
    "componentType" : 5123,
    "count" : 36,
    "type" : "SCALAR",
    "max" : [ 13 ],
    "min" : [ 0 ]
  }, {
    "bufferView" : 1,
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 14,
    "type" : "VEC3",
    "max" : [ 6.0, 4.0, 0.0 ],
    "min" : [ 0.0, 0.0, 0.0 ],
    "sparse" : {
      "count" : 3,
      "indices" : {
        "bufferView" : 2,
        "byteOffset" : 0,
        "componentType" : 5123
      },
      "values" : {
        "bufferView" : 3,
        "byteOffset" : 0
      }
    }
  } ],
  
  "asset" : {
    "version" : "2.0"
  }
}

显示的结果如下图:

该示例包含两个访问器:一个用于网格的索引,另一个用于顶点位置。引用顶点位置的一个定义一个额外的accessor.sparse 属性,其中包含有关应应用的稀疏数据替换的信息:

"accessors" : [ 
  ...
  {
    "bufferView" : 1,
    "byteOffset" : 0,
    "componentType" : 5126,
    "count" : 14,
    "type" : "VEC3",
    "max" : [ 6.0, 4.0, 0.0 ],
    "min" : [ 0.0, 0.0, 0.0 ],
    "sparse" : {
      "count" : 3,
      "indices" : {
        "bufferView" : 2,
        "byteOffset" : 0,
        "componentType" : 5123
      },
      "values" : {
        "bufferView" : 3,
        "byteOffset" : 0
      }
    }
  } ],

sparse对象本身定义受替换影响的元素计数。sparse.indices属性是指包含要替换的元素的索引的bufferViewsparse.values是指包含实际数据的bufferView

在本例中,原始几何数据存储在索引为1的bufferView中。它描述了一个顶点的矩形数组。sparse.indices引用带有索引2的bufferView,其中包含索引[8,10,12]。sparse.values是指带有索引3的bufferView,它包含新的顶点位置,即[(1,2,0),(3,3,0),(5,4,0)]。应用相应替换的效果如下图所示。


个人觉得 bufferView3 至少要存13个顶点, 因为需要由索引指定替换第十三个顶点 . 但是它的大小是: 36 正好是3个顶点的大小. 所以这个替换操作很奇特. 那么sparse.indices对应的Buffer存储的是什么数据, 肯定是将被替换的索引位置.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!