0

问题

我从描述 3D 空间中一组彩色点的 API 接收二进制数据。目的是解析这些点并在 Three.js 的缓冲几何中使用它们。

在处理二进制格式的数据时,我有点不知所措,所以我需要你的帮助。


关于来自 API 的二进制数据:

二进制数据以以下格式的标头开头:

HTTP/1.1 200 OK
Content-Length: 13632 // varies depending on the query

标题后面是一个空行,然后是这种格式的这些点:

每 32 个字节:

  • X:双(8字节)
  • Y:双(8字节)
  • Z:双(8字节)
  • R:无符号字符(1 字节)
  • G:无符号字符(1 字节)
  • B:无符号字符(1 字节)
  • 5个垃圾字节来填充剩余空间

到目前为止我在哪里:

假设binaryPoints变量保存来自 API 的原始二进制数据。据我所知,我必须首先将数据添加到一个字节大小为 32(每个点的大小)的 arrayBuffer 中。接下来,我将该缓冲区添加到 DataView 对象以对其进行操作。

  // create a 32-byte arrayBuffer (each point takes up 32 bytes)
  const buffer = await binaryPoints.arrayBuffer(32);

  // create a dataview of the buffer to read the points
  const data = new DataView(buffer);

所以我还没有很多。我想我需要通过实现偏移来计算标题占用的空间,我想从标题中获取点数。

  // temporary hard-set values
  const numPoints = 1000;
  const offsetFromHeader = 100; // bits

从我看到的一些示例和其他 SO 问题中,我相信我应该一次循环通过缓冲区 32 个字节,同时读出 xyzrgb 值。它可能看起来像:

  // offset is in bits, increases by 256 each iteration (32*8)
  for (var i=0, offset=offsetFromHeader; i<numPoints; i++, offset += 256) {
    // Go through each xyz value, using Float64Array (double) to store that value
    const xFloat64View = data.getFloat64Array(offset);
    const yFloat64View = data.getFloat64Array(offset + 64);
    const zFloat64View = data.getFloat64Array(offset + 128);

    // Go through each rgb value, using Uint8Array (1 byte unsigned int) to store that value
    const rUint8View = data.getUint8Array(offset + 192);
    const gUint8View = data.getUint8Array(offset + 200);
    const bUint8View = data.getUint8Array(offset + 208);

    // just ignore the final bits
  }

...但说实话,一旦我到了这一点,我就无法弄清楚如何处理这些信息。在我发现的一些示例中,循环通过只有一种信息类型的二进制数据运行(在我的情况下,就好像我只有 X 值)。

我是否应该创建一个新的纯 javascript 点数组并添加如下值:

// psuedo code
var points = [];

// in the loop
points[i].x = data.getFloat64Array(offset);

情况可能并非如此,因为我计划在下一步中将 Typed Arrays 直接转录到 Three.js bufferGeometries 中,并且保留一个 [large] 额外的普通 JS 数组会增加开销。


下一步:将点放入 Three.js bufferGeometry

我将使用 Three.js 的 bufferGeometry 中的点来渲染点云。我知道这会通知我想要的上一部分的输出。

它可能看起来像:

const bufferGeometry = new THREE.BufferGeometry();


let vertices = new Float32Array(); // xyz
let colors = new Float32Array(); // rgb

bufferGeometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
bufferGeometry.addAttribute('color', new THREE.BufferAttribute(colors, 3));

const points = new THREE.Points(bufferGeometry, material);
scene.add(points);

我知道到目前为止这一切都很松散,但我只是在黑暗中四处乱窜,把这一切写下来帮助我思考清楚。

4

1 回答 1

0

你有一个加倍的 gUint8View.. 第二个应该是 bUint8View..

我认为您想要 DataView api...然后您可以这样做...

var x= view.getFloat64(0); 
var y= view.getFloat64(8); 
var z= view.getFloat64(16);
var r = view.getUInt8(24); 
var g = view.getUInt8(25); 
var v = view.getUInt8(26); 

另外..您确定“100位”标头还是字节?看起来很奇怪,您的数据源会从一个奇怪的非 8 位边界开始,这会使解析 TRemendously 变得复杂。

您的代码的三个方面看起来大致正确。

你在正确的轨道上 :) 我刚刚做了一个类似的应用程序来解析 HYG 星目录并制作星点云....

好东西!

于 2018-05-18T02:26:04.380 回答