Update PointCloud type to support client-side rendering #754
+47
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change introduces a
PointCloudHeader
to thePointCloud
message, making the existingbytes
payload self-describing. This change is additive, non-breaking, and significantly improves our ability to describe and render point clouds.Reasoning
The current
PointCloud
message efficiently transports data as a binary blob (bytes point_cloud = 1;
). However, it lacks any descriptive metadata, forcing an implicit, out-of-band contract between the client and server to interpret the byte stream's structure (e.g., field order, data types, presence of color or intensity).This approach has three main drawbacks:
Transform.metadata
.Proposed Changes
To address this, I introduced the
PointCloudHeader
message. This header adheres to industry standards to explicitly define the structure of the data contained within thepoint_cloud
byte array.I updated the
PointCloud
message with a new field,PointCloudHeader header = 2;
, to contain the metadata.This change is non-breaking. Existing clients will continue to parse the
bytes
at field1
as they always have and will ignore the newheader
field at tag2
. New clients can check for the presence of theheader
to adopt a more robust parsing logic, enabling them to handle varied and evolving point cloud structures.Rendering Benefits
This enhancement directly benefits rendering performance by allowing the server to provide a GPU-optimized, interleaved memory layout. In this Array-of-Structures format, all attributes for a single point (e.g., position, color, intensity) are packed contiguously in the binary blob. A rendering client using a library like Three.js can leverage this for maximum efficiency. The entire
bytes
payload from the message is loaded into a singleTypedArray
and used to create aTHREE.InterleavedBuffer
.The new
PointCloudHeader
provides the crucialstride
value—the total number of elements for one point—needed for this step. From this single buffer, visualizers can create multipleTHREE.InterleavedBufferAttribute's to define 'position', 'color', and other properties by specifying their individual
itemSizeand
offset` within the stride, all of which are now explicitly defined in the header. This "zero-copy" process is speedy because it avoids any client-side iteration or data restructuring. The data flows directly from the network into a memory layout that is highly cache-friendly for the GPU, ensuring that when a vertex is processed, all of its associated attributes are fetched in a single memory read, maximizing rendering throughput for large-scale point clouds.Beyond the initial transfer of a complete point cloud, this self-describing format is exceptionally well-suited for streaming targeted updates to a client. For instance, if only a small region of the point cloud changes (e.g., an object moves or a sensor updates a specific area), the server can send a new
PointCloud
message containing only the data for the modified points by including thestart
field in the header. Upon receiving this partial update, the client can perform a highly efficient, targeted modification of the data on the GPU.Instead of rebuilding the entire geometry, the client can use the new binary data to overwrite a specific portion of its existing
THREE.BufferAttribute
orTHREE.InterleavedBuffer
. The client can inform the renderer to only re-upload the small, changed segment of the buffer to the GPU, and avoid the significant performance cost of transferring and processing the entire multi-million point dataset for a minor change.Quick Example
I have already put together a working POC using the world state store service fake as an example. You can see the code here:
Screen.Recording.2025-10-06.at.9.28.46.AM.mov