I'm working on transmitting point cloud data over the network using Flatbuffers to an application built in Unity.
Say I have the following schema file:
namespace PCFrame;
struct Vec3 {
x: float;
y: float;
z: float;
}
struct RGB {
R: ubyte;
G: ubyte;
B: ubyte;
}
struct PCPoint {
Position: Vec3;
Color: RGB;
}
table PCFrame {
FrameNo: uint;
Points: [PCPoint];
}
file_identifier "FBPC";
root_type PCFrame;
I've successfully serialized and transmitted the buffer. But after receiving the ByteBuffer
in C# and deserializing it as a PCFrame
object, the only way for me to access a point in the Points
array is to call the method Points(n)
. This is extremely inefficient, especially when the array can include hundreds of thousands of points and I need to iterate over all of them.
Is there any way to access the array more efficiently?
Edit: I ended up giving up on the more legible PCPoint struct and instead created the Points data as a float array (arranged as x1, y1, z1, r1, g1, b1, x2, y2...). So the much simpler schema now looks like this:
namespace PCFrame;
table PCFrame
{
FrameNo: uint;
Points: [float]; // x1, y1, z1, r1, g1, b1, x2, y2, z2, r2, g2, b2, x3, ...
}
file_identifier "FBPC";
root_type PCFrame;
Using an array of a primitive type allows me to extract the byte array directly using:
ArraySegment<byte> pointsArraySegment = fb_frame.GetPointsBytes();
byte[] pointsByteArray = pointsArraySegment.Value.Array;
Which in turn allows me to Buffer.BlockCopy the entire array back into a float array at once:
int offset = pointsArraySegment.Value.Offset;
float[] pointsArray = new float[(pointsByteArray.Length - offset) / sizeof(double)];
Buffer.BlockCopy(pointsByteArray, offset, pointsArray, 0, pointsByteArray.Length - offset);
Accessing the point data from the float array in this manner is much more efficient. I'm still not sure why FlatBuffers doesn't allow you to do this on non-primitive arrays, though.