first cut at reducing memory footprint of AABox

This commit is contained in:
ZappoMan 2013-10-15 11:29:04 -07:00
parent 9f05faa088
commit c9b0edf345
9 changed files with 107 additions and 101 deletions

View file

@ -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;
}
};

View file

@ -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();

View file

@ -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
}

View file

@ -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);
}
}

View file

@ -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;
};

View file

@ -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 <PerfStat.h>
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) {

View file

@ -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

View file

@ -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 {

View file

@ -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;