Overte C++ Documentation
OctreePacketData.h
1 //
2 // OctreePacketData.h
3 // libraries/octree/src
4 //
5 // Created by Brad Hefta-Gaub on 11/19/2013.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // TO DO:
9 // * add stats tracking for number of unique colors and consecutive identical colors.
10 // (as research for color dictionaries and RLE)
11 //
12 // * further testing of compression to determine optimal configuration for performance and compression
13 //
14 // * improve semantics for "reshuffle" - current approach will work for now and with compression
15 // but wouldn't work with RLE because the colors in the levels would get reordered and RLE would need
16 // to be recalculated
17 //
18 // Distributed under the Apache License, Version 2.0.
19 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
20 //
21 
22 #ifndef hifi_OctreePacketData_h
23 #define hifi_OctreePacketData_h
24 
25 #include <atomic>
26 
27 #include <QByteArray>
28 #include <QString>
29 #include <QUuid>
30 
31 #include <SharedUtil.h>
32 #include <ShapeInfo.h>
33 #include <NLPacket.h>
34 #include <udt/PacketHeaders.h>
35 
36 #include "MaterialMappingMode.h"
37 #include "BillboardMode.h"
38 #include "RenderLayer.h"
39 #include "PrimitiveMode.h"
40 #include "WebInputMode.h"
41 #include "PulseMode.h"
42 #include "GizmoType.h"
43 #include "TextEffect.h"
44 #include "TextAlignment.h"
45 
46 #include "OctreeConstants.h"
47 #include "OctreeElement.h"
48 
49 using AtomicUIntStat = std::atomic<uintmax_t>;
50 
51 typedef unsigned char OCTREE_PACKET_FLAGS;
52 typedef uint16_t OCTREE_PACKET_SEQUENCE;
53 const uint16_t MAX_OCTREE_PACKET_SEQUENCE = 65535;
54 typedef quint64 OCTREE_PACKET_SENT_TIME;
55 typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE;
56 const int MAX_OCTREE_PACKET_SIZE = udt::MAX_PACKET_SIZE;
57 
58 const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS)
59  + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME);
60 
61 const unsigned int MAX_OCTREE_PACKET_DATA_SIZE =
62  udt::MAX_PACKET_SIZE - (NLPacket::MAX_PACKET_HEADER_SIZE + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
63 const unsigned int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE;
64 
65 const unsigned int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40;
66 const unsigned int COMPRESS_PADDING = 15;
67 const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5;
68 
69 const int PACKET_IS_COLOR_BIT = 0;
70 const int PACKET_IS_COMPRESSED_BIT = 1;
71 
73 class LevelDetails {
74  LevelDetails(int startIndex, int bytesOfOctalCodes, int bytesOfBitmasks, int bytesOfColor, int bytesReservedAtStart) :
75  _startIndex(startIndex),
76  _bytesOfOctalCodes(bytesOfOctalCodes),
77  _bytesOfBitmasks(bytesOfBitmasks),
78  _bytesOfColor(bytesOfColor),
79  _bytesReservedAtStart(bytesReservedAtStart) {
80  }
81 
82  friend class OctreePacketData;
83 
84 private:
85  int _startIndex;
86  int _bytesOfOctalCodes;
87  int _bytesOfBitmasks;
88  int _bytesOfColor;
89  int _bytesReservedAtStart;
90 };
91 
94 public:
95  OctreePacketData(bool enableCompression = false, int maxFinalizedSize = MAX_OCTREE_PACKET_DATA_SIZE);
97 
99  void changeSettings(bool enableCompression = false, unsigned int targetSize = MAX_OCTREE_PACKET_DATA_SIZE);
100 
102  void reset();
103 
106  bool startSubTree(const unsigned char* octcode = NULL);
107 
108  // call to indicate that the current subtree is complete and changes should be committed.
109  void endSubTree();
110 
111  // call rollback the current subtree and restore the stream to the state prior to starting the subtree encoding
112  void discardSubTree();
113 
116 
118  void discardLevel(LevelDetails key);
119 
122  bool endLevel(LevelDetails key);
123 
125  bool appendBitMask(unsigned char bitmask);
126 
129  bool updatePriorBitMask(int offset, unsigned char bitmask);
130 
132  bool reserveBitMask();
133 
136  bool reserveBytes(int numberOfBytes);
137 
139  bool releaseReservedBitMask();
140 
142  bool releaseReservedBytes(int numberOfBytes);
143 
146  bool updatePriorBytes(int offset, const unsigned char* replacementBytes, int length);
147 
149  bool appendColor(colorPart red, colorPart green, colorPart blue);
150 
152  bool appendValue(const nodeColor& color);
153 
155  bool appendValue(uint8_t value);
156 
158  bool appendValue(uint16_t value);
159 
161  bool appendValue(uint32_t value);
162 
164  bool appendValue(quint64 value);
165 
167  bool appendValue(float value);
168 
170  bool appendValue(const glm::vec2& value);
171 
173  bool appendValue(const glm::vec3& value);
174 
176  bool appendValue(const glm::u8vec3& value);
177 
179  bool appendValue(const QVector<glm::vec3>& value);
180 
182  bool appendValue(const QVector<glm::quat>& value);
183 
185  bool appendValue(const QVector<float>& value);
186 
188  bool appendValue(const QVector<bool>& value);
189 
191  bool appendValue(const QVector<QUuid>& value);
192 
194  bool appendValue(const glm::quat& value);
195 
197  bool appendValue(bool value);
198 
200  bool appendValue(const QString& string);
201 
203  bool appendValue(const QUuid& uuid);
204 
206  bool appendValue(const QByteArray& bytes);
207 
209  bool appendValue(const AACube& aaCube);
210 
212  bool appendValue(const QRect& rect);
213 
215  bool appendPosition(const glm::vec3& value);
216 
218  bool appendRawData(const unsigned char* data, int length);
219  bool appendRawData(QByteArray data);
220 
223  int getUncompressedByteOffset(int offsetFromEnd = 0) const { return _bytesInUse - offsetFromEnd; }
224 
226  const unsigned char* getFinalizedData();
228  int getFinalizedSize();
229 
231  const unsigned char* getUncompressedData(int byteOffset = 0) { return &_uncompressed[byteOffset]; }
232 
234  int getUncompressedSize() { return _bytesInUse; }
235 
237  void setUncompressedSize(int newSize) { _bytesInUse = newSize; }
238 
240  bool hasContent() const { return (_bytesInUse > 0); }
241 
243  void loadFinalizedContent(const unsigned char* data, int length);
244 
246  bool isCompressed() const { return _enableCompression; }
247 
249  unsigned int getTargetSize() const { return _targetSize; }
250 
252  int getReservedBytes() { return _bytesReserved; }
253 
254  int getBytesAvailable() { return _bytesAvailable; }
255 
257  void debugContent();
258  void debugBytes();
259 
260  static quint64 getCompressContentTime() { return _compressContentTime; }
261  static quint64 getCompressContentCalls() { return _compressContentCalls; }
262  static quint64 getTotalBytesOfOctalCodes() { return _totalBytesOfOctalCodes; }
263  static quint64 getTotalBytesOfBitMasks() { return _totalBytesOfBitMasks; }
264  static quint64 getTotalBytesOfColor() { return _totalBytesOfColor; }
265 
266  static int unpackDataFromBytes(const unsigned char* dataBytes, float& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
267  static int unpackDataFromBytes(const unsigned char* dataBytes, bool& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
268  static int unpackDataFromBytes(const unsigned char* dataBytes, quint64& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
269  static int unpackDataFromBytes(const unsigned char* dataBytes, uint32_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
270  static int unpackDataFromBytes(const unsigned char* dataBytes, uint16_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
271  static int unpackDataFromBytes(const unsigned char* dataBytes, uint8_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
272  static int unpackDataFromBytes(const unsigned char* dataBytes, glm::quat& result) { int bytes = unpackOrientationQuatFromBytes(dataBytes, result); return bytes; }
273  static int unpackDataFromBytes(const unsigned char* dataBytes, ShapeType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
274  static int unpackDataFromBytes(const unsigned char* dataBytes, MaterialMappingMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
275  static int unpackDataFromBytes(const unsigned char* dataBytes, BillboardMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
276  static int unpackDataFromBytes(const unsigned char* dataBytes, RenderLayer& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
277  static int unpackDataFromBytes(const unsigned char* dataBytes, PrimitiveMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
278  static int unpackDataFromBytes(const unsigned char* dataBytes, WebInputMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
279  static int unpackDataFromBytes(const unsigned char* dataBytes, PulseMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
280  static int unpackDataFromBytes(const unsigned char* dataBytes, GizmoType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
281  static int unpackDataFromBytes(const unsigned char* dataBytes, TextEffect& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
282  static int unpackDataFromBytes(const unsigned char* dataBytes, TextAlignment& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
283  static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result);
284  static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result);
285  static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result);
286  static int unpackDataFromBytes(const unsigned char* dataBytes, QString& result);
287  static int unpackDataFromBytes(const unsigned char* dataBytes, QUuid& result);
288  static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<glm::vec3>& result);
289  static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<glm::quat>& result);
290  static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result);
291  static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<bool>& result);
292  static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<QUuid>& result);
293  static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
294  static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result);
295  static int unpackDataFromBytes(const unsigned char* dataBytes, QRect& result);
296 
297 private:
299  bool append(const unsigned char* data, int length);
300 
302  bool append(unsigned char byte);
303 
304  unsigned int _targetSize;
305  bool _enableCompression;
306 
307  QByteArray _uncompressedByteArray;
308  unsigned char* _uncompressed { nullptr };
309  int _bytesInUse;
310  int _bytesAvailable;
311  int _subTreeAt;
312  int _bytesReserved;
313  int _subTreeBytesReserved; // the number of reserved bytes at start of a subtree
314 
315  bool compressContent();
316 
317  QByteArray _compressedByteArray;
318  unsigned char* _compressed { nullptr };
319  int _compressedBytes;
320  int _bytesInUseLastCheck;
321  bool _dirty;
322 
323  // statistics...
324  int _bytesOfOctalCodes;
325  int _bytesOfBitMasks;
326  int _bytesOfColor;
327  int _bytesOfValues;
328  int _bytesOfPositions;
329  int _bytesOfRawData;
330 
331  int _bytesOfOctalCodesCurrentSubTree;
332 
333  static bool _debug;
334 
335  static AtomicUIntStat _compressContentTime;
336  static AtomicUIntStat _compressContentCalls;
337 
338  static AtomicUIntStat _totalBytesOfOctalCodes;
339  static AtomicUIntStat _totalBytesOfBitMasks;
340  static AtomicUIntStat _totalBytesOfColor;
341  static AtomicUIntStat _totalBytesOfValues;
342  static AtomicUIntStat _totalBytesOfPositions;
343  static AtomicUIntStat _totalBytesOfRawData;
344 };
345 
346 #endif // hifi_OctreePacketData_h
An opaque key used when starting, ending, and discarding encoding/packing levels of OctreePacketData.
Definition: OctreePacketData.h:73
Handles packing of the data portion of PacketType_OCTREE_DATA messages.
Definition: OctreePacketData.h:93
void debugContent()
displays contents for debugging
Definition: OctreePacketData.cpp:672
LevelDetails startLevel()
starts a level marker. returns an opaque key which can be used to discard the level
Definition: OctreePacketData.cpp:240
void changeSettings(bool enableCompression=false, unsigned int targetSize=MAX_OCTREE_PACKET_DATA_SIZE)
change compression and target size settings
Definition: OctreePacketData.cpp:38
bool reserveBytes(int numberOfBytes)
Definition: OctreePacketData.cpp:112
int getUncompressedSize()
the size of the packet in uncompressed form
Definition: OctreePacketData.h:234
static quint64 getTotalBytesOfOctalCodes()
total calls to compress content
Definition: OctreePacketData.h:262
void setUncompressedSize(int newSize)
update the size of the packet in uncompressed form
Definition: OctreePacketData.h:237
int getReservedBytes()
the number of bytes in the packet currently reserved
Definition: OctreePacketData.h:252
bool isCompressed() const
returns whether or not zlib compression enabled on finalization
Definition: OctreePacketData.h:246
bool appendValue(const nodeColor &color)
appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
Definition: OctreePacketData.cpp:301
unsigned int getTargetSize() const
returns the target uncompressed size
Definition: OctreePacketData.h:249
bool startSubTree(const unsigned char *octcode=NULL)
Definition: OctreePacketData.cpp:165
void reset()
reset completely, all data is discarded
Definition: OctreePacketData.cpp:54
bool appendColor(colorPart red, colorPart green, colorPart blue)
appends a color to the end of the stream, may fail if new data stream is too long to fit in packet
Definition: OctreePacketData.cpp:305
void discardLevel(LevelDetails key)
discards all content back to a previous marker key
Definition: OctreePacketData.cpp:245
static quint64 getCompressContentCalls()
total time spent compressing content
Definition: OctreePacketData.h:261
const unsigned char * getUncompressedData(int byteOffset=0)
get pointer to the uncompressed stream buffer at the byteOffset
Definition: OctreePacketData.h:231
void loadFinalizedContent(const unsigned char *data, int length)
load finalized content to allow access to decoded content for parsing
Definition: OctreePacketData.cpp:637
int getFinalizedSize()
get size of the finalized data (it may be compressed or rewritten into optimal form)
Definition: OctreePacketData.cpp:204
int getUncompressedByteOffset(int offsetFromEnd=0) const
Definition: OctreePacketData.h:223
static int unpackDataFromBytes(const unsigned char *dataBytes, float &result)
total bytes of color
Definition: OctreePacketData.h:266
bool hasContent() const
has some content been written to the packet
Definition: OctreePacketData.h:240
bool releaseReservedBitMask()
releases previously reserved space in the stream.
Definition: OctreePacketData.cpp:124
bool appendRawData(const unsigned char *data, int length)
appends raw bytes, might fail if byte would cause packet to be too large
Definition: OctreePacketData.cpp:590
bool appendPosition(const glm::vec3 &value)
appends a position to the end of the stream, may fail if new data stream is too long to fit in packet
Definition: OctreePacketData.cpp:579
static quint64 getTotalBytesOfColor()
total bytes of bitmasks
Definition: OctreePacketData.h:264
bool releaseReservedBytes(int numberOfBytes)
releases previously reserved space in the stream.
Definition: OctreePacketData.cpp:128
bool updatePriorBytes(int offset, const unsigned char *replacementBytes, int length)
Definition: OctreePacketData.cpp:151
bool endLevel(LevelDetails key)
Definition: OctreePacketData.cpp:279
bool updatePriorBitMask(int offset, unsigned char bitmask)
Definition: OctreePacketData.cpp:141
bool reserveBitMask()
reserves space in the stream for a future bitmask, may fail if new data stream is too long to fit in ...
Definition: OctreePacketData.cpp:108
bool appendBitMask(unsigned char bitmask)
appends a bitmask to the end of the stream, may fail if new data stream is too long to fit in packet
Definition: OctreePacketData.cpp:292
const unsigned char * getFinalizedData()
get access to the finalized data (it may be compressed or rewritten into optimal form)
Definition: OctreePacketData.cpp:190
static quint64 getTotalBytesOfBitMasks()
total bytes for octal codes
Definition: OctreePacketData.h:263