Overte C++ Documentation
OctreeElement.h
1 //
2 // OctreeElement.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_OctreeElement_h
13 #define hifi_OctreeElement_h
14 
15 //#define SIMPLE_CHILD_ARRAY
16 #define SIMPLE_EXTERNAL_CHILDREN
17 
18 #include <atomic>
19 
20 #include <QReadWriteLock>
21 
22 #include <OctalCode.h>
23 #include <SharedUtil.h>
24 #include <ViewFrustum.h>
25 
26 #include "AACube.h"
27 #include "OctreeConstants.h"
28 
29 using AtomicUIntStat = std::atomic<uintmax_t>;
30 
31 
32 class EncodeBitstreamParams;
33 class Octree;
34 class OctreeElement;
35 class OctreePacketData;
36 class ReadBitstreamToTreeParams;
37 class Shape;
38 class VoxelSystem;
39 
40 using OctreeElementPointer = std::shared_ptr<OctreeElement>;
41 using OctreeElementWeakPointer = std::weak_ptr<OctreeElement>;
42 using ConstOctreeElementPointer = std::shared_ptr<const OctreeElement>;
43 using OctreePointer = std::shared_ptr<Octree>;
44 
45 class OctreeElement: public std::enable_shared_from_this<OctreeElement> {
46 
47 protected:
48  // can only be constructed by derived implementation
49  OctreeElement();
50 
51  virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0;
52 
53 public:
54  virtual void init(unsigned char * octalCode);
55  virtual ~OctreeElement();
56 
57  // methods you can and should override to implement your tree functionality
58 
60  virtual OctreeElementPointer addChildAtIndex(int childIndex);
61 
63  virtual void calculateAverageFromChildren() { }
64 
66  virtual bool collapseChildren() { return false; }
67 
70  virtual bool hasContent() const { return isLeaf(); }
71 
74  virtual bool hasDetailedContent() const { return isLeaf(); }
75 
79  virtual void splitChildren() { }
80 
82  virtual bool requiresSplit() const { return false; }
83 
85  typedef enum { COMPLETED, PARTIAL, NONE } AppendState;
86 
87  virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const { }
88 
91  virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args)
92  { return 0; }
93 
98  virtual bool isRendered() const { return getShouldRender(); }
99 
100  virtual bool deleteApproved() const { return true; }
101 
102  virtual bool canPickIntersect() const { return isLeaf(); }
107  virtual bool findSpherePenetration(const glm::vec3& center, float radius,
108  glm::vec3& penetration, void** penetratedObject) const;
109 
110  // Base class methods you don't need to implement
111  const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; }
112  OctreeElementPointer getChildAtIndex(int childIndex) const;
113  void deleteChildAtIndex(int childIndex);
114  OctreeElementPointer removeChildAtIndex(int childIndex);
115  bool isParentOf(const OctreeElementPointer& possibleChild) const;
116 
118  bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0);
119 
120 
121  const AACube& getAACube() const { return _cube; }
122  const glm::vec3& getCorner() const { return _cube.getCorner(); }
123  float getScale() const { return _cube.getScale(); }
124  int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; }
125 
126  float getEnclosingRadius() const;
127  bool isInView(const ViewFrustum& viewFrustum) const { return computeViewIntersection(viewFrustum) != ViewFrustum::OUTSIDE; }
128  ViewFrustum::intersection computeViewIntersection(const ViewFrustum& viewFrustum) const;
129  float distanceToCamera(const ViewFrustum& viewFrustum) const;
130  float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
131 
132  // points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)
133  float distanceSquareToPoint(const glm::vec3& point) const; // when you don't need the actual distance, use this.
134  float distanceToPoint(const glm::vec3& point) const;
135 
136  bool isLeaf() const { return _childBitmask == 0; }
137  int getChildCount() const { return numberOfOnes(_childBitmask); }
138  void printDebugDetails(const char* label) const;
139  bool isDirty() const { return _isDirty; }
140  void clearDirtyBit() { _isDirty = false; }
141  void setDirtyBit() { _isDirty = true; }
142  bool hasChangedSince(quint64 time) const { return (_lastChanged > time); }
143  void markWithChangedTime();
144  quint64 getLastChanged() const { return _lastChanged; }
145  void handleSubtreeChanged(OctreePointer myTree);
146 
147  // Used by VoxelSystem for rendering in/out of view and LOD
148  void setShouldRender(bool shouldRender);
149  bool getShouldRender() const { return _shouldRender; }
150 
151 
152  void setSourceUUID(const QUuid& sourceID);
153  QUuid getSourceUUID() const;
154  uint16_t getSourceUUIDKey() const { return _sourceUUIDKey; }
155  bool matchesSourceUUID(const QUuid& sourceUUID) const;
156  static uint16_t getSourceNodeUUIDKey(const QUuid& sourceUUID);
157 
158  static void resetPopulationStatistics();
159  static unsigned long getNodeCount() { return _voxelNodeCount; }
160  static unsigned long getInternalNodeCount() { return _voxelNodeCount - _voxelNodeLeafCount; }
161  static unsigned long getLeafNodeCount() { return _voxelNodeLeafCount; }
162 
163  static quint64 getOctreeMemoryUsage() { return _octreeMemoryUsage; }
164  static quint64 getOctcodeMemoryUsage() { return _octcodeMemoryUsage; }
165  static quint64 getExternalChildrenMemoryUsage() { return _externalChildrenMemoryUsage; }
166  static quint64 getTotalMemoryUsage() { return _octreeMemoryUsage + _octcodeMemoryUsage + _externalChildrenMemoryUsage; }
167 
168  static quint64 getGetChildAtIndexTime() { return _getChildAtIndexTime; }
169  static quint64 getGetChildAtIndexCalls() { return _getChildAtIndexCalls; }
170  static quint64 getSetChildAtIndexTime() { return _setChildAtIndexTime; }
171  static quint64 getSetChildAtIndexCalls() { return _setChildAtIndexCalls; }
172 
173  static quint64 getExternalChildrenCount() { return _externalChildrenCount; }
174  static quint64 getChildrenCount(int childCount) { return _childrenCount[childCount]; }
175 
176  enum ChildIndex {
177  CHILD_BOTTOM_RIGHT_NEAR = 0,
178  CHILD_BOTTOM_RIGHT_FAR = 1,
179  CHILD_TOP_RIGHT_NEAR = 2,
180  CHILD_TOP_RIGHT_FAR = 3,
181  CHILD_BOTTOM_LEFT_NEAR = 4,
182  CHILD_BOTTOM_LEFT_FAR = 5,
183  CHILD_TOP_LEFT_NEAR = 6,
184  CHILD_TOP_LEFT_FAR = 7,
185  CHILD_UNKNOWN = -1
186  };
187 
188  struct HalfSpace {
189  enum {
190  None = 0x00,
191  Bottom = 0x01,
192  Top = 0x02,
193  Right = 0x04,
194  Left = 0x08,
195  Near = 0x10,
196  Far = 0x20,
197  All = 0x3f,
198  };
199  };
200 
201 
202  OctreeElementPointer getOrCreateChildElementAt(float x, float y, float z, float s);
203  OctreeElementPointer getOrCreateChildElementContaining(const AACube& box);
204  OctreeElementPointer getOrCreateChildElementContaining(const AABox& box);
205  int getMyChildContaining(const AACube& cube) const;
206  int getMyChildContaining(const AABox& box) const;
207  int getMyChildContainingPoint(const glm::vec3& point) const;
208 
209  void bumpChangedContent() { _lastChangedContent = usecTimestampNow(); }
210  uint64_t getLastChangedContent() const { return _lastChangedContent; }
211 
212 protected:
213 
214  void deleteAllChildren();
215  void setChildAtIndex(int childIndex, const OctreeElementPointer& child);
216 
217  void calculateAACube();
218 
219  AACube _cube;
220 
222  union octalCode_t {
223  unsigned char buffer[8];
224  unsigned char* pointer;
225  } _octalCode;
226 
227  quint64 _lastChanged;
228  uint64_t _lastChangedContent { 0 };
229 
231 #ifdef SIMPLE_CHILD_ARRAY
232  OctreeElementPointer _simpleChildArray[8];
233 #endif
234 
235 #ifdef SIMPLE_EXTERNAL_CHILDREN
236  // union children_t {
237  OctreeElementPointer _childrenSingle;
238  OctreeElementPointer _externalChildren[NUMBER_OF_CHILDREN];
239  // } _children;
240 #endif
241 
242  uint16_t _sourceUUIDKey;
243 
244  // Support for _sourceUUID, we use these static member variables to track the UUIDs that are
245  // in use by various voxel server nodes. We map the UUID strings into an 16 bit key, this limits us to at
246  // most 65k voxel servers in use at a time within the client. Which is far more than we need.
247  static uint16_t _nextUUIDKey; // start at 1, 0 is reserved for NULL
248  static std::map<QString, uint16_t> _mapSourceUUIDsToKeys;
249  static std::map<uint16_t, QString> _mapKeysToSourceUUIDs;
250 
251  unsigned char _childBitmask; // 1 byte
252 
253  bool _falseColored : 1,
254  _isDirty : 1,
255  _shouldRender : 1,
256  _octcodePointer : 1,
257  _unknownBufferIndex : 1,
258  _childrenExternal : 1;
259 
260  static AtomicUIntStat _voxelNodeCount;
261  static AtomicUIntStat _voxelNodeLeafCount;
262 
263  static AtomicUIntStat _octreeMemoryUsage;
264  static AtomicUIntStat _octcodeMemoryUsage;
265  static AtomicUIntStat _externalChildrenMemoryUsage;
266 
267  static AtomicUIntStat _getChildAtIndexTime;
268  static AtomicUIntStat _getChildAtIndexCalls;
269  static AtomicUIntStat _setChildAtIndexTime;
270  static AtomicUIntStat _setChildAtIndexCalls;
271 
272  static AtomicUIntStat _externalChildrenCount;
273  static AtomicUIntStat _childrenCount[NUMBER_OF_CHILDREN + 1];
274 };
275 
276 #endif // hifi_OctreeElement_h
Handles packing of the data portion of PacketType_OCTREE_DATA messages.
Definition: OctreePacketData.h:93
Client and server, axis aligned box for bounds of this voxel, 48 bytes.
Definition: OctreeElement.h:222