问题
我正在从描述 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 个垃圾字节来填充剩余空间
到目前为止,我所处的位置:
假设二进制点变量保存来自 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);
情况可能并非如此,因为我计划在下一步中将类型化数组直接转录到 Three.js 缓冲区几何中,并且保留一个 [大型] 超普通 JS 数组会增加开销。
下一步:将点放入 Three.js 缓冲区几何图形
我将使用 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);
我知道到目前为止这一切都非常松散,但我只是在黑暗中四处游荡,把这一切写下来有助于我思考清楚。
你有一个双倍的gUint8View..第二个应该是bUint8View。
我想你想要数据视图 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 位边界开始,这将使 TR
复杂化。代码的 THREE 面看起来大致正确。
您走在正确的轨道上:)我刚刚做了一个类似的应用程序来解析海斯特-耶鲁的星表,并制作一个星星点云。
好东西!