問題
3D 空間内の色付きポイントのグループを記述する API からバイナリ データを受信しています。その意図は、ポイントを解析し、それらを Three.js の buffergeometry で使用することです。
バイナリ形式のデータを操作することになると、ここで少し頭を悩ませているので、あなたの助けが必要です.
API からのバイナリ データについて:
バイナリ データは、次の形式のヘッダーで始まります。
HTTP/1.1 200 OK
Content-Length: 13632 // varies depending on the query
ヘッダーの後に空白行が続き、次にこれらのポイントが次の形式で示されます。
32 バイトごと:
- X: double (8 バイト)
- Y: double (8 バイト)
- Z: ダブル (8 バイト)
- R: unsigned char (1バイト)
- G: unsigned char (1バイト)
- B: unsigned char (1バイト)
- 残りのスペースを埋めるための 5 ガベージ バイト
私がこれまでにいる場所:
binaryPoints変数が API からの生のバイナリ データを保持しているとします。私がこれまでに理解しているように、最初にデータを arrayBuffer にバイトサイズ 32 (各ポイントのサイズ) で追加する必要があります。次に、そのバッファーを操作するために 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
}
……が、正直なところ、ここまで来てしまった情報をどうしたらいいのか分からなかった。私が見つけたいくつかの例では、ループは 1 種類の情報のみを持つバイナリ データを処理します (私の場合は、X 値しかないかのようになります)。
ポイントの新しいプレーンJavaScript配列を作成し、次のような値を追加する必要があります:
// psuedo code
var points = [];
// in the loop
points[i].x = data.getFloat64Array(offset);
次のステップで Typed Arrays を Three.js bufferGeometries に直接転記する予定であり、[大きな] 余分な単純な 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);
これまでのところ、これはすべて非常にルーズなものであることはわかっていますが、暗闇の中で動き回っているだけなので、これをすべて書き留めておくと、考えるのに役立ちます.