The Challenge
Received data from an API contains binary information about colored points in 3D space. The goal is to decode these points and utilize them in a buffergeometry within Three.js.
Working with binary formatted data is proving to be beyond my current expertise, so I am seeking assistance to tackle this task.
Description of the binary data obtained from the API:
The binary data commences with a header structured as follows:
HTTP/1.1 200 OK
Content-Length: 13632 // varies based on query
Following the header is a blank line, succeeded by the representation of points in this layout:
Every 32 bytes:
- X: double (8 byte)
- Y: double (8 byte)
- Z: double (8 byte)
- R: unsigned char (1 byte)
- G: unsigned char (1 byte)
- B: unsigned char (1 byte)
- 5 placeholders to fill remaining space
My Progress So Far:
Assuming that the binaryPoints variable holds the raw binary data fetched from the API. Initial steps involve adding the data to an arrayBuffer sized at 32 bytes per point, followed by creating a DataView object for manipulation.
// create a 32-byte arrayBuffer (each point occupies 32 bytes)
const buffer = await binaryPoints.arrayBuffer(32);
// establish a dataview of the buffer for reading the points
const data = new DataView(buffer);
Currently, I am considering incorporating an offset to account for the header size and aiming to extract the number of points from the header.
// assigning temporary values
const numPoints = 1000;
const offsetFromHeader = 100; // bits
Based on examples and references, it seems like iterating through the buffer 32 bytes at a time will facilitate extraction of xyzrgb values:
// increment offset by 256 each iteration (32*8)
for (var i=0, offset=offsetFromHeader; i<numPoints; i++, offset += 256) {
// Extract xyz values using Float64Array (double)
const xFloat64View = data.getFloat64Array(offset);
const yFloat64View = data.getFloat64Array(offset + 64);
const zFloat64View = data.getFloat64Array(offset + 128);
// Fetch rgb values using Uint8Array (1 byte unsigned int)
const rUint8View = data.getUint8Array(offset + 192);
const gUint8View = data.getUint8Array(offset + 200);
const bUint8View = data.getUint8Array(offset + 208);
// Ignore excess bits
}
Despite reaching this point, I'm uncertain about how to proceed further with this information. It seems existing samples focus on single-type data rather than the multi-dimensional nature seen here.
Should I construct a plain javascript array of points and input values accordingly?
// pseudocode
var points = [];
// inside loop
points[i].x = data.getFloat64Array(offset);
This approach might not be suitable as eventual integration into Three.js bufferGeometries aims to eliminate additional overhead associated with maintaining separate JS arrays.
Next Objective: Integrating Points into Three.js bufferGeometry
The rendered pointcloud in Three.js bufferGeometry relies on the outcome desired from the previous phases.
A potential implementation could resemble:
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);
Although progress remains tentative, detailing each step aids in refining my thought process amid this challenging endeavor.