Overte C++ Documentation
Octree.h
1 //
2 // Octree.h
3 // libraries/octree/src
4 //
5 // Created by Stephen Birarda on 3/13/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_Octree_h
13 #define hifi_Octree_h
14 
15 #include <memory>
16 #include <set>
17 #include <stdint.h>
18 
19 #include <QHash>
20 #include <QObject>
21 #include <QtCore/QJsonObject>
22 
23 #include <shared/ReadWriteLockable.h>
24 #include <SimpleMovingAverage.h>
25 #include <ViewFrustum.h>
26 
27 #include "OctreeElement.h"
28 #include "OctreeElementBag.h"
29 #include "OctreePacketData.h"
30 #include "OctreeSceneStats.h"
31 #include "OctreeUtils.h"
32 
33 class ReadBitstreamToTreeParams;
34 class Octree;
35 class OctreeElement;
36 class OctreePacketData;
37 class Shape;
38 using OctreePointer = std::shared_ptr<Octree>;
39 
40 extern QVector<QString> PERSIST_EXTENSIONS;
41 
44 public:
45  virtual bool preRecursion(const OctreeElementPointer& element) = 0;
46  virtual bool postRecursion(const OctreeElementPointer& element) = 0;
47  virtual OctreeElementPointer possiblyCreateChildAt(const OctreeElementPointer& element, int childIndex) { return NULL; }
48 };
49 
50 // Callback function, for recuseTreeWithOperation
51 using RecurseOctreeOperation = std::function<bool(const OctreeElementPointer&, void*)>;
52 // Function for sorting octree children during recursion. If return value == FLT_MAX, child is discarded
53 using RecurseOctreeSortingOperation = std::function<float(const OctreeElementPointer&, void*)>;
54 using SortedChild = std::pair<float, OctreeElementPointer>;
55 typedef QHash<uint, AACube> CubeList;
56 
57 const bool NO_EXISTS_BITS = false;
58 const bool WANT_EXISTS_BITS = true;
59 
60 const int NO_BOUNDARY_ADJUST = 0;
61 const int LOW_RES_MOVING_ADJUST = 1;
62 
63 class EncodeBitstreamParams {
64 public:
65  bool includeExistsBits;
66  NodeData* nodeData;
67 
68  // output hints from the encode process
69  typedef enum {
70  UNKNOWN,
71  DIDNT_FIT,
72  FINISHED
73  } reason;
74  reason stopReason;
75 
76  EncodeBitstreamParams(bool includeExistsBits = WANT_EXISTS_BITS,
77  NodeData* nodeData = nullptr) :
78  includeExistsBits(includeExistsBits),
79  nodeData(nodeData),
80  stopReason(UNKNOWN)
81  {
82  }
83 
84  void displayStopReason() {
85  printf("StopReason: ");
86  switch (stopReason) {
87  case UNKNOWN: qDebug("UNKNOWN"); break;
88  case DIDNT_FIT: qDebug("DIDNT_FIT"); break;
89  case FINISHED: qDebug("FINISHED"); break;
90  }
91  }
92 
93  QString getStopReason() {
94  switch (stopReason) {
95  case UNKNOWN: return QString("UNKNOWN"); break;
96  case DIDNT_FIT: return QString("DIDNT_FIT"); break;
97  case FINISHED: return QString("FINISHED"); break;
98  }
99  }
100 
101  std::function<void(const QUuid& dataID, quint64 itemLastEdited)> trackSend { [](const QUuid&, quint64){} };
102 };
103 
104 class ReadBitstreamToTreeParams {
105 public:
106  bool includeExistsBits;
107  OctreeElementPointer destinationElement;
108  QUuid sourceUUID;
109  SharedNodePointer sourceNode;
110  int elementsPerPacket = 0;
111  int entitiesPerPacket = 0;
112 
113  ReadBitstreamToTreeParams(
114  bool includeExistsBits = WANT_EXISTS_BITS,
115  OctreeElementPointer destinationElement = NULL,
116  QUuid sourceUUID = QUuid(),
117  SharedNodePointer sourceNode = SharedNodePointer()) :
118  includeExistsBits(includeExistsBits),
119  destinationElement(destinationElement),
120  sourceUUID(sourceUUID),
121  sourceNode(sourceNode)
122  {}
123 };
124 
125 class Octree : public QObject, public std::enable_shared_from_this<Octree>, public ReadWriteLockable {
126  Q_OBJECT
127 public:
128  Octree(bool shouldReaverage = false);
129  virtual ~Octree();
130 
132  virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0;
133 
134  // These methods will allow the OctreeServer to send your tree inbound edit packets of your
135  // own definition. Implement these to allow your octree based server to support editing
136  virtual PacketType expectedDataPacketType() const { return PacketType::Unknown; }
137  virtual PacketVersion expectedVersion() const { return versionForPacketType(expectedDataPacketType()); }
138  virtual bool handlesEditPacketType(PacketType packetType) const { return false; }
139  virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
140  const SharedNodePointer& sourceNode) { return 0; }
141 
142  virtual bool rootElementHasData() const { return false; }
143  virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const { }
144 
145  // Why preUpdate() and update()?
146  // Because EntityTree needs them.
147  virtual void preUpdate() { }
148  virtual void update(bool simulate = true) { }
149 
150  OctreeElementPointer getRoot() { return _rootElement; }
151 
152  virtual void eraseDomainAndNonOwnedEntities() { _isDirty = true; };
153  virtual void eraseAllOctreeElements(bool createNewRoot = true);
154 
155  virtual void readBitstreamToTree(const unsigned char* bitstream, uint64_t bufferSizeBytes, ReadBitstreamToTreeParams& args);
156  void reaverageOctreeElements(OctreeElementPointer startElement = OctreeElementPointer());
157 
160  OctreeElementPointer getOctreeElementAt(float x, float y, float z, float s) const;
161 
164  OctreeElementPointer getOctreeEnclosingElementAt(float x, float y, float z, float s) const;
165 
166  OctreeElementPointer getOrCreateChildElementAt(float x, float y, float z, float s);
167  OctreeElementPointer getOrCreateChildElementContaining(const AACube& box);
168 
169  void recurseTreeWithOperation(const RecurseOctreeOperation& operation, void* extraData = NULL);
170  void recurseTreeWithOperationSorted(const RecurseOctreeOperation& operation, const RecurseOctreeSortingOperation& sortingOperation, void* extraData = NULL);
171 
172  void recurseTreeWithOperator(RecurseOctreeOperator* operatorObject);
173 
174  bool isDirty() const { return _isDirty; }
175  void clearDirtyBit() { _isDirty = false; }
176  void setDirtyBit() { _isDirty = true; }
177 
178  // output hints from the encode process
179  typedef enum {
180  Lock,
181  TryLock
182  } lockType;
183 
184 
185  bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL,
186  Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
187 
188  bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration,
189  Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
190 
193  bool findContentInCube(const AACube& cube, CubeList& cubes);
194 
198  OctreeElementPointer getElementEnclosingPoint(const glm::vec3& point,
199  Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
200 
201  // Note: this assumes the fileFormat is the HIO individual voxels code files
202  void loadOctreeFile(const char* fileName);
203 
204  // Octree exporters
205  bool toJSONDocument(QJsonDocument* doc, const OctreeElementPointer& element = nullptr);
206  bool toJSONString(QString& jsonString, const OctreeElementPointer& element = nullptr);
207  bool toJSON(QByteArray* data, const OctreeElementPointer& element = nullptr, bool doGzip = false);
208  bool writeToFile(const char* filename, const OctreeElementPointer& element = nullptr, QString persistAsFileType = "json.gz");
209  bool writeToJSONFile(const char* filename, const OctreeElementPointer& element = nullptr, bool doGzip = false);
210  virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues,
211  bool skipThoseWithBadParents) = 0;
212  virtual bool writeToJSON(QString& jsonString, const OctreeElementPointer& element) = 0;
213 
214  // Octree importers
215  bool readFromFile(const char* filename);
216  bool readFromURL(const QString& url, const bool isObservable = true, const qint64 callerId = -1, const bool isImport = false); // will support file urls as well...
217  bool readFromByteArray(const QString& url, const QByteArray& byteArray);
218  bool readFromStream(uint64_t streamLength, QDataStream& inputStream, const bool isImport = false, const QUrl& urlString = QUrl());
219  bool readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const bool isImport = false, const QUrl& urlString = QUrl());
220  bool readJSONFromGzippedFile(QString qFileName);
221  virtual bool readFromMap(QVariantMap& entityDescription, const bool isImport = false) = 0;
222 
223  uint64_t getOctreeElementsCount();
224 
225  bool getShouldReaverage() const { return _shouldReaverage; }
226 
227  void recurseElementWithOperation(const OctreeElementPointer& element, const RecurseOctreeOperation& operation,
228  void* extraData, int recursionCount = 0);
229  bool recurseElementWithOperationSorted(const OctreeElementPointer& element, const RecurseOctreeOperation& operation,
230  const RecurseOctreeSortingOperation& sortingOperation, void* extraData, int recursionCount = 0);
231 
232  bool recurseElementWithOperator(const OctreeElementPointer& element, RecurseOctreeOperator* operatorObject, int recursionCount = 0);
233 
234  bool getIsViewing() const { return _isViewing; }
235  void setIsViewing(bool isViewing) { _isViewing = isViewing; }
236 
237  bool getIsServer() const { return _isServer; }
238  void setIsServer(bool isServer) { _isServer = isServer; }
239 
240  bool getIsClient() const { return !_isServer; }
241  void setIsClient(bool isClient) { _isServer = !isClient; }
242 
243  virtual void dumpTree() { }
244  virtual void pruneTree() { }
245 
246  void setOctreeVersionInfo(QUuid id, int64_t dataVersion) {
247  _persistID = id;
248  _persistDataVersion = dataVersion;
249  }
250 
251  virtual void resetEditStats() { }
252  virtual quint64 getAverageDecodeTime() const { return 0; }
253  virtual quint64 getAverageLookupTime() const { return 0; }
254  virtual quint64 getAverageUpdateTime() const { return 0; }
255  virtual quint64 getAverageCreateTime() const { return 0; }
256  virtual quint64 getAverageLoggingTime() const { return 0; }
257  virtual quint64 getAverageFilterTime() const { return 0; }
258 
259  void incrementPersistDataVersion() { _persistDataVersion++; }
260 
261 
262 protected:
263  void deleteOctalCodeFromTreeRecursion(const OctreeElementPointer& element, void* extraData);
264 
265  static bool countOctreeElementsOperation(const OctreeElementPointer& element, void* extraData);
266 
267  OctreeElementPointer nodeForOctalCode(const OctreeElementPointer& ancestorElement, const unsigned char* needleCode, OctreeElementPointer* parentOfFoundElement) const;
268  OctreeElementPointer createMissingElement(const OctreeElementPointer& lastParentElement, const unsigned char* codeToReach, int recursionCount = 0);
269  int readElementData(const OctreeElementPointer& destinationElement, const unsigned char* nodeData,
270  int bufferSizeBytes, ReadBitstreamToTreeParams& args);
271 
272  OctreeElementPointer _rootElement = nullptr;
273 
274  QUuid _persistID { QUuid::createUuid() };
275  int _persistDataVersion { 0 };
276 
277  bool _isDirty;
278  bool _shouldReaverage;
279 
280  bool _isViewing;
281  bool _isServer;
282 };
283 
284 #endif // hifi_Octree_h
Handles packing of the data portion of PacketType_OCTREE_DATA messages.
Definition: OctreePacketData.h:93
derive from this class to use the Octree::recurseTreeWithOperator() method
Definition: Octree.h:43