From c9b0edf34507e930ed0cc6330cf98a0ef9863940 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 15 Oct 2013 11:29:04 -0700 Subject: [PATCH] first cut at reducing memory footprint of AABox --- libraries/shared/src/PerfStat.cpp | 7 +- libraries/shared/src/PerfStat.h | 6 +- .../src/VoxelSendThread.cpp | 9 +- libraries/voxels/src/AABox.cpp | 126 ++++++++---------- libraries/voxels/src/AABox.h | 13 +- libraries/voxels/src/ViewFrustum.cpp | 20 ++- libraries/voxels/src/ViewFrustum.h | 5 + libraries/voxels/src/VoxelNode.cpp | 20 ++- libraries/voxels/src/VoxelNode.h | 2 +- 9 files changed, 107 insertions(+), 101 deletions(-) diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 31f4b1a30b..961e24744f 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -108,7 +108,8 @@ bool PerformanceWarning::_suppressShortTimings = false; // Destructor handles recording all of our stats PerformanceWarning::~PerformanceWarning() { uint64_t end = usecTimestampNow(); - double elapsedmsec = (end - _start) / 1000.0; + uint64_t elapsedusec = (end - _start); + double elapsedmsec = elapsedusec / 1000.0; if ((_alwaysDisplay || _renderWarningsOn) && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - _start) / 1000000.0; @@ -127,6 +128,10 @@ PerformanceWarning::~PerformanceWarning() { } else if (_alwaysDisplay) { qDebug("%s took %lf milliseconds\n", _message, elapsedmsec); } + // if the caller gave us a pointer to store the running total, track it now. + if (_runningTotal) { + *_runningTotal += elapsedusec; + } }; diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 2c5924e5ce..3343c9fd62 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -89,13 +89,15 @@ private: const char* _message; bool _renderWarningsOn; bool _alwaysDisplay; + uint64_t* _runningTotal; static bool _suppressShortTimings; public: - PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false) : + PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false, uint64_t* runningTotal = NULL) : _start(usecTimestampNow()), _message(message), _renderWarningsOn(renderWarnings), - _alwaysDisplay(alwaysDisplay) { } + _alwaysDisplay(alwaysDisplay), + _runningTotal(runningTotal) { } ~PerformanceWarning(); diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index ac2c56d2d3..f12577bd2f 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -52,7 +52,14 @@ bool VoxelSendThread::process() { std::cout << "Last send took too much time, not sleeping!\n"; } } - + + // some debugging... + printf("ViewFrustum::getProjectedPolygonTime=%llu ViewFrustum::getProjectedPolygonCalls=%llu\n", + ViewFrustum::getProjectedPolygonTime, ViewFrustum::getProjectedPolygonCalls); + + printf("ViewFrustum::getFurthestPointFromCameraTime=%llu ViewFrustum::getFurthestPointFromCameraCalls=%llu\n", + ViewFrustum::getFurthestPointFromCameraTime, ViewFrustum::getFurthestPointFromCameraCalls); + return isStillRunning(); // keep running till they terminate us } diff --git a/libraries/voxels/src/AABox.cpp b/libraries/voxels/src/AABox.cpp index 6a9dd68082..24f6384aee 100644 --- a/libraries/voxels/src/AABox.cpp +++ b/libraries/voxels/src/AABox.cpp @@ -13,83 +13,63 @@ #include "AABox.h" #include "GeometryUtil.h" -AABox::AABox(const glm::vec3& corner, float size) : _corner(corner), _size(size, size, size), _topFarLeft(_corner + _size) -{ +AABox::AABox(const glm::vec3& corner, float size) : + _corner(corner), _scale(size) { }; -AABox::AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x, y, z), _topFarLeft(_corner + _size) -{ +AABox::AABox() : _corner(0,0,0), _scale(0) { }; -AABox::AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size), _topFarLeft(_corner + _size) -{ +glm::vec3 AABox::calcTopFarLeft() const { + glm::vec3 topFarLeft(_corner); + topFarLeft += glm::vec3(_scale, _scale, _scale); + return topFarLeft; }; -AABox::AABox() : _corner(0,0,0), _size(0,0,0), _topFarLeft(0,0,0) -{ -}; - - void AABox::scale(float scale) { _corner = _corner * scale; - _size = _size * scale; _center = _center * scale; - _topFarLeft = _topFarLeft * scale; + _scale = _scale * scale; } glm::vec3 AABox::getVertex(BoxVertex vertex) const { switch (vertex) { case BOTTOM_LEFT_NEAR: - return _corner + glm::vec3(_size.x, 0, 0); + return _corner + glm::vec3(_scale, 0, 0); case BOTTOM_RIGHT_NEAR: return _corner; case TOP_RIGHT_NEAR: - return _corner + glm::vec3(0, _size.y, 0); + return _corner + glm::vec3(0, _scale, 0); case TOP_LEFT_NEAR: - return _corner + glm::vec3(_size.x, _size.y, 0); + return _corner + glm::vec3(_scale, _scale, 0); case BOTTOM_LEFT_FAR: - return _corner + glm::vec3(_size.x, 0, _size.z); + return _corner + glm::vec3(_scale, 0, _scale); case BOTTOM_RIGHT_FAR: - return _corner + glm::vec3(0, 0, _size.z); + return _corner + glm::vec3(0, 0, _scale); case TOP_RIGHT_FAR: - return _corner + glm::vec3(0, _size.y, _size.z); + return _corner + glm::vec3(0, _scale, _scale); case TOP_LEFT_FAR: - return _corner + _size; + return _corner + glm::vec3(_scale, _scale, _scale); } } -void AABox::setBox(const glm::vec3& corner, const glm::vec3& size) { +void AABox::setBox(const glm::vec3& corner, float scale) { _corner = corner; - _size = size; - - // In the event that the caller gave us negative sizes, fix things up to be reasonable - if (_size.x < 0.0) { - _size.x = -size.x; - _corner.x -= _size.x; - } - if (_size.y < 0.0) { - _size.y = -size.y; - _corner.y -= _size.y; - } - if (_size.z < 0.0) { - _size.z = -size.z; - _corner.z -= _size.z; - } - _center = _corner + (_size * 0.5f); - _topFarLeft = _corner + _size; + _scale = scale; + _center = _corner + (glm::vec3(_scale, _scale, _scale) * 0.5f); } glm::vec3 AABox::getVertexP(const glm::vec3& normal) const { glm::vec3 result = _corner; if (normal.x > 0) { - result.x += _size.x; + result.x += _scale; } if (normal.y > 0) { - result.y += _size.y; + result.y += _scale; } if (normal.z > 0) { - result.z += _size.z; + result.z += _scale; } return result; } @@ -98,15 +78,15 @@ glm::vec3 AABox::getVertexN(const glm::vec3& normal) const { glm::vec3 result = _corner; if (normal.x < 0) { - result.x += _size.x; + result.x += _scale; } if (normal.y < 0) { - result.y += _size.y; + result.y += _scale; } if (normal.z < 0) { - result.z += _size.z; + result.z += _scale; } return result; @@ -118,9 +98,9 @@ static bool isWithin(float value, float corner, float size) { } bool AABox::contains(const glm::vec3& point) const { - return isWithin(point.x, _corner.x, _size.x) && - isWithin(point.y, _corner.y, _size.y) && - isWithin(point.z, _corner.z, _size.z); + return isWithin(point.x, _corner.x, _scale) && + isWithin(point.y, _corner.y, _scale) && + isWithin(point.z, _corner.z, _scale); } bool AABox::contains(const AABox& otherBox) const { @@ -140,9 +120,9 @@ static bool isWithinExpanded(float value, float corner, float size, float expans } bool AABox::expandedContains(const glm::vec3& point, float expansion) const { - return isWithinExpanded(point.x, _corner.x, _size.x, expansion) && - isWithinExpanded(point.y, _corner.y, _size.y, expansion) && - isWithinExpanded(point.z, _corner.z, _size.z, expansion); + return isWithinExpanded(point.x, _corner.x, _scale, expansion) && + isWithinExpanded(point.y, _corner.y, _scale, expansion) && + isWithinExpanded(point.z, _corner.z, _scale, expansion); } // finds the intersection between a ray and the facing plane on one axis @@ -164,7 +144,7 @@ bool AABox::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& e } // check each axis glm::vec3 expandedCorner = _corner - glm::vec3(expansion, expansion, expansion); - glm::vec3 expandedSize = _size + glm::vec3(expansion, expansion, expansion) * 2.0f; + glm::vec3 expandedSize = glm::vec3(_scale, _scale, _scale) + glm::vec3(expansion, expansion, expansion) * 2.0f; glm::vec3 direction = end - start; float axisDistance; return (findIntersection(start.x, direction.x, expandedCorner.x, expandedSize.x, axisDistance) && @@ -189,23 +169,23 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct } // check each axis float axisDistance; - if ((findIntersection(origin.x, direction.x, _corner.x, _size.x, axisDistance) && axisDistance >= 0 && - isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) && - isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z))) { + if ((findIntersection(origin.x, direction.x, _corner.x, _scale, axisDistance) && axisDistance >= 0 && + isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && + isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { distance = axisDistance; face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE; return true; } - if ((findIntersection(origin.y, direction.y, _corner.y, _size.y, axisDistance) && axisDistance >= 0 && - isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x) && - isWithin(origin.z + axisDistance*direction.z, _corner.z, _size.z))) { + if ((findIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 && + isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale) && + isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { distance = axisDistance; face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE; return true; } - if ((findIntersection(origin.z, direction.z, _corner.z, _size.z, axisDistance) && axisDistance >= 0 && - isWithin(origin.y + axisDistance*direction.y, _corner.y, _size.y) && - isWithin(origin.x + axisDistance*direction.x, _corner.x, _size.x))) { + if ((findIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 && + isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && + isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) { distance = axisDistance; face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE; return true; @@ -268,27 +248,27 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec3& point, BoxFace face) con switch (face) { case MIN_X_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), - glm::vec3(_corner.x, _corner.y + _size.y, _corner.z + _size.z)); + glm::vec3(_corner.x, _corner.y + _scale, _corner.z + _scale)); case MAX_X_FACE: - return glm::clamp(point, glm::vec3(_corner.x + _size.x, _corner.y, _corner.z), - glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z + _size.z)); + return glm::clamp(point, glm::vec3(_corner.x + _scale, _corner.y, _corner.z), + glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); case MIN_Y_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), - glm::vec3(_corner.x + _size.x, _corner.y, _corner.z + _size.z)); + glm::vec3(_corner.x + _scale, _corner.y, _corner.z + _scale)); case MAX_Y_FACE: - return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _size.y, _corner.z), - glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z + _size.z)); + return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _scale, _corner.z), + glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); case MIN_Z_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), - glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z)); + glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z)); case MAX_Z_FACE: - return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _size.z), - glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z + _size.z)); + return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _scale), + glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); } } @@ -338,7 +318,7 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& glm::vec4 thirdAxisMaxPlane = getPlane((BoxFace)(thirdAxis * 2 + 1)); glm::vec4 offset = glm::vec4(0.0f, 0.0f, 0.0f, - glm::dot(glm::vec3(secondAxisMaxPlane + thirdAxisMaxPlane), _size) * 0.5f); + glm::dot(glm::vec3(secondAxisMaxPlane + thirdAxisMaxPlane), glm::vec3(_scale, _scale, _scale)) * 0.5f); glm::vec4 diagonals[] = { secondAxisMinPlane + thirdAxisMaxPlane + offset, secondAxisMaxPlane + thirdAxisMaxPlane + offset }; @@ -362,11 +342,11 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& glm::vec4 AABox::getPlane(BoxFace face) const { switch (face) { case MIN_X_FACE: return glm::vec4(-1.0f, 0.0f, 0.0f, _corner.x); - case MAX_X_FACE: return glm::vec4(1.0f, 0.0f, 0.0f, -_corner.x - _size.x); + case MAX_X_FACE: return glm::vec4(1.0f, 0.0f, 0.0f, -_corner.x - _scale); case MIN_Y_FACE: return glm::vec4(0.0f, -1.0f, 0.0f, _corner.y); - case MAX_Y_FACE: return glm::vec4(0.0f, 1.0f, 0.0f, -_corner.y - _size.y); + case MAX_Y_FACE: return glm::vec4(0.0f, 1.0f, 0.0f, -_corner.y - _scale); case MIN_Z_FACE: return glm::vec4(0.0f, 0.0f, -1.0f, _corner.z); - case MAX_Z_FACE: return glm::vec4(0.0f, 0.0f, 1.0f, -_corner.z - _size.z); + case MAX_Z_FACE: return glm::vec4(0.0f, 0.0f, 1.0f, -_corner.z - _scale); } } diff --git a/libraries/voxels/src/AABox.h b/libraries/voxels/src/AABox.h index 7bb203aaf4..b08f94df5c 100644 --- a/libraries/voxels/src/AABox.h +++ b/libraries/voxels/src/AABox.h @@ -42,13 +42,10 @@ class AABox public: AABox(const glm::vec3& corner, float size); - AABox(const glm::vec3& corner, float x, float y, float z); - AABox(const glm::vec3& corner, const glm::vec3& size); AABox(); ~AABox() {}; - void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); }; - void setBox(const glm::vec3& corner, const glm::vec3& size); + void setBox(const glm::vec3& corner, float scale); // for use in frustum computations glm::vec3 getVertexP(const glm::vec3& normal) const; @@ -57,9 +54,10 @@ public: void scale(float scale); const glm::vec3& getCorner() const { return _corner; }; - const glm::vec3& getSize() const { return _size; }; const glm::vec3& getCenter() const { return _center; }; - const glm::vec3& getTopFarLeft() const { return _topFarLeft; }; + + glm::vec3 calcTopFarLeft() const; + float getScale() const { return _scale; } glm::vec3 getVertex(BoxVertex vertex) const; @@ -81,8 +79,7 @@ private: glm::vec3 _corner; glm::vec3 _center; - glm::vec3 _size; - glm::vec3 _topFarLeft; + float _scale; }; diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index e0cfa7cd97..3733442e9c 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -541,9 +541,17 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left }; +uint64_t ViewFrustum::getProjectedPolygonTime = 0; +uint64_t ViewFrustum::getProjectedPolygonCalls = 0; +#include + VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { + getProjectedPolygonCalls++; + PerformanceWarning(false, "ViewFrustum::getProjectedPolygon", false, &getProjectedPolygonTime); + const glm::vec3& bottomNearRight = box.getCorner(); - const glm::vec3& topFarLeft = box.getTopFarLeft(); + glm::vec3 topFarLeft = box.calcTopFarLeft(); + int lookUp = ((_position.x < bottomNearRight.x) ) // 1 = right | compute 6-bit + ((_position.x > topFarLeft.x ) << 1) // 2 = left | code to + ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera @@ -605,13 +613,19 @@ VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { } +uint64_t ViewFrustum::getFurthestPointFromCameraTime = 0; +uint64_t ViewFrustum::getFurthestPointFromCameraCalls = 0; + // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. glm::vec3 ViewFrustum::getFurthestPointFromCamera(const AABox& box) const { - const glm::vec3& center = box.getCenter(); + getFurthestPointFromCameraCalls++; + PerformanceWarning(false, "ViewFrustum::getFurthestPointFromCamera", false, &getFurthestPointFromCameraTime); + + const glm::vec3& center = box.getCenter(); const glm::vec3& bottomNearRight = box.getCorner(); - const glm::vec3& topFarLeft = box.getTopFarLeft(); + glm::vec3 topFarLeft = box.calcTopFarLeft(); glm::vec3 furthestPoint; if (_position.x < center.x) { diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index 803e52908e..d3341ede23 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -96,6 +96,11 @@ public: VoxelProjectedPolygon getProjectedPolygon(const AABox& box) const; glm::vec3 getFurthestPointFromCamera(const AABox& box) const; + static uint64_t getProjectedPolygonTime; + static uint64_t getProjectedPolygonCalls; + static uint64_t getFurthestPointFromCameraTime; + static uint64_t getFurthestPointFromCameraCalls; + private: // Used for keyhole calculations diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index ad83b5a9cf..6c45bde441 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -61,14 +61,14 @@ void VoxelNode::init(unsigned char * octalCode) { markWithChangedTime(); _voxelMemoryUsage += sizeof(VoxelNode); - _octcodeMemoryUsage += bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_octalCode)); + _octcodeMemoryUsage += bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(getOctalCode())); } VoxelNode::~VoxelNode() { notifyDeleteHooks(); _voxelMemoryUsage -= sizeof(VoxelNode); - _octcodeMemoryUsage -= bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_octalCode)); + _octcodeMemoryUsage -= bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(getOctalCode())); delete[] _octalCode; @@ -128,18 +128,14 @@ void VoxelNode::setShouldRender(bool shouldRender) { } void VoxelNode::calculateAABox() { - glm::vec3 corner; - glm::vec3 size; // copy corner into box - copyFirstVertexForCode(_octalCode,(float*)&corner); + copyFirstVertexForCode(getOctalCode(),(float*)&corner); // this tells you the "size" of the voxel - float voxelScale = 1 / powf(2, *_octalCode); - size = glm::vec3(voxelScale,voxelScale,voxelScale); - - _box.setBox(corner,size); + float voxelScale = 1 / powf(2, numberOfThreeBitSectionsInCode(getOctalCode())); + _box.setBox(corner,voxelScale); } void VoxelNode::deleteChildAtIndex(int childIndex) { @@ -166,7 +162,7 @@ VoxelNode* VoxelNode::removeChildAtIndex(int childIndex) { VoxelNode* VoxelNode::addChildAtIndex(int childIndex) { if (!_children[childIndex]) { - _children[childIndex] = new VoxelNode(childOctalCode(_octalCode, childIndex)); + _children[childIndex] = new VoxelNode(childOctalCode(getOctalCode(), childIndex)); _children[childIndex]->setVoxelSystem(_voxelSystem); // our child is always part of our voxel system NULL ok _isDirty = true; _childCount++; @@ -339,13 +335,13 @@ void VoxelNode::printDebugDetails(const char* label) const { } qDebug("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isColored=%s (%d,%d,%d,%d) isDirty=%s shouldRender=%s\n children=", label, - _box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getSize().x, + _box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getScale(), debug::valueOf(isLeaf()), debug::valueOf(isColored()), getColor()[0], getColor()[1], getColor()[2], getColor()[3], debug::valueOf(isDirty()), debug::valueOf(getShouldRender())); outputBits(childBits, false); qDebug("\n octalCode="); - printOctalCode(_octalCode); + printOctalCode(getOctalCode()); } float VoxelNode::getEnclosingRadius() const { diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 41196c81b5..2cd3c90389 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -55,7 +55,7 @@ public: const AABox& getAABox() const { return _box; } const glm::vec3& getCenter() const { return _box.getCenter(); } const glm::vec3& getCorner() const { return _box.getCorner(); } - float getScale() const { return _box.getSize().x; } // voxelScale = (1 / powf(2, *node->getOctalCode())); } + float getScale() const { return _box.getScale(); } // voxelScale = (1 / powf(2, *node->getOctalCode())); } int getLevel() const { return *_octalCode + 1; } // one based or zero based? this doesn't correctly handle 2 byte case float getEnclosingRadius() const;