Я работаю над передачей данных облака точек по сети с помощью Flatbuffers в приложение, построенное на Unity.
Скажем, у меня есть следующий файл схемы:
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;
Я успешно сериализовал и передал буфер. Но после получения ByteBuffer
в C# и десериализации его как объекта PCFrame
единственный способ получить доступ к точке в массиве Points
- это вызвать метод Points(n)
. Это крайне неэффективно, особенно когда массив может включать сотни тысяч точек, и мне нужно перебирать все из них.
Есть ли способ более эффективного доступа к массиву?
Изменить: В конце концов я отказался от более удобочитаемой структуры PCPoint и вместо этого создал данные Points в виде массива с плавающей запятой (в виде x1, y1, z1, r1, g1, b1, x2, y2 ...) . Таким образом, гораздо более простая схема теперь выглядит так:
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;
Использование массива примитивного типа позволяет мне извлекать массив байтов напрямую, используя:
ArraySegment<byte> pointsArraySegment = fb_frame.GetPointsBytes();
byte[] pointsByteArray = pointsArraySegment.Value.Array;
Что, в свою очередь, позволяет мне в Buffer.Block: скопируйте весь массив обратно в массив с плавающей запятой сразу:
int offset = pointsArraySegment.Value.Offset;
float[] pointsArray = new float[(pointsByteArray.Length - offset) / sizeof(double)];
Buffer.BlockCopy(pointsByteArray, offset, pointsArray, 0, pointsByteArray.Length - offset);
Доступ к данным точки из массива с плавающей запятой таким способом намного эффективнее. Я до сих пор не уверен, почему FlatBuffers не позволяет делать это с непримитивными массивами.