next round of voxelnode size improvements

This commit is contained in:
ZappoMan 2013-10-15 14:43:51 -07:00
parent 9800dc0fde
commit 6fff53a2dc
10 changed files with 149 additions and 57 deletions

View file

@ -1392,13 +1392,13 @@ void Application::increaseVoxelSize() {
const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500;
struct SendVoxelsOperationArgs {
unsigned char* newBaseOctCode;
const unsigned char* newBaseOctCode;
};
bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData;
if (node->isColored()) {
unsigned char* nodeOctalCode = node->getOctalCode();
const unsigned char* nodeOctalCode = node->getOctalCode();
unsigned char* codeColorBuffer = NULL;
int codeLength = 0;

View file

@ -16,7 +16,7 @@
#include "SharedUtil.h"
#include "OctalCode.h"
int numberOfThreeBitSectionsInCode(unsigned char * octalCode) {
int numberOfThreeBitSectionsInCode(const unsigned char * octalCode) {
assert(octalCode);
if (*octalCode == 255) {
return *octalCode + numberOfThreeBitSectionsInCode(octalCode + 1);
@ -25,7 +25,7 @@ int numberOfThreeBitSectionsInCode(unsigned char * octalCode) {
}
}
void printOctalCode(unsigned char * octalCode) {
void printOctalCode(const unsigned char * octalCode) {
if (!octalCode) {
qDebug("NULL\n");
} else {
@ -36,7 +36,7 @@ void printOctalCode(unsigned char * octalCode) {
}
}
char sectionValue(unsigned char * startByte, char startIndexInByte) {
char sectionValue(const unsigned char * startByte, char startIndexInByte) {
char rightShift = 8 - startIndexInByte - 3;
if (rightShift < 0) {
@ -54,14 +54,14 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes) {
}
}
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode) {
int branchIndexWithDescendant(const unsigned char * ancestorOctalCode, const unsigned char * descendantOctalCode) {
int parentSections = numberOfThreeBitSectionsInCode(ancestorOctalCode);
int branchStartBit = parentSections * 3;
return sectionValue(descendantOctalCode + 1 + (branchStartBit / 8), branchStartBit % 8);
}
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber) {
unsigned char * childOctalCode(const unsigned char * parentOctalCode, char childNumber) {
// find the length (in number of three bit code sequences)
// in the parent
@ -115,7 +115,7 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber
return newCode;
}
void voxelDetailsForCode(unsigned char * octalCode, VoxelPositionSize& voxelPositionSize) {
void voxelDetailsForCode(const unsigned char * octalCode, VoxelPositionSize& voxelPositionSize) {
float output[3];
memset(&output[0], 0, 3 * sizeof(float));
float currentScale = 1.0;
@ -138,7 +138,7 @@ void voxelDetailsForCode(unsigned char * octalCode, VoxelPositionSize& voxelPosi
voxelPositionSize.s = currentScale;
}
void copyFirstVertexForCode(unsigned char * octalCode, float* output) {
void copyFirstVertexForCode(const unsigned char * octalCode, float* output) {
memset(output, 0, 3 * sizeof(float));
float currentScale = 0.5;
@ -154,13 +154,13 @@ void copyFirstVertexForCode(unsigned char * octalCode, float* output) {
}
}
float * firstVertexForCode(unsigned char * octalCode) {
float * firstVertexForCode(const unsigned char * octalCode) {
float * firstVertex = new float[3];
copyFirstVertexForCode(octalCode, firstVertex);
return firstVertex;
}
OctalCodeComparison compareOctalCodes(unsigned char* codeA, unsigned char* codeB) {
OctalCodeComparison compareOctalCodes(const unsigned char* codeA, const unsigned char* codeB) {
if (!codeA || !codeB) {
return ILLEGAL_CODE;
}
@ -196,10 +196,10 @@ OctalCodeComparison compareOctalCodes(unsigned char* codeA, unsigned char* codeB
}
char getOctalCodeSectionValue(unsigned char* octalCode, int section) {
char getOctalCodeSectionValue(const unsigned char* octalCode, int section) {
int startAtByte = 1 + (BITS_IN_OCTAL * section / BITS_IN_BYTE);
char startIndexInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE;
unsigned char* startByte = octalCode + startAtByte;
const unsigned char* startByte = octalCode + startAtByte;
return sectionValue(startByte, startIndexInByte);
}
@ -243,7 +243,7 @@ void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectio
}
}
unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels) {
unsigned char* chopOctalCode(const unsigned char* originalOctalCode, int chopLevels) {
int codeLength = numberOfThreeBitSectionsInCode(originalOctalCode);
unsigned char* newCode = NULL;
if (codeLength > chopLevels) {
@ -259,7 +259,9 @@ unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels) {
return newCode;
}
unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, bool includeColorSpace) {
unsigned char* rebaseOctalCode(const unsigned char* originalOctalCode, const unsigned char* newParentOctalCode,
bool includeColorSpace) {
int oldCodeLength = numberOfThreeBitSectionsInCode(originalOctalCode);
int newParentCodeLength = numberOfThreeBitSectionsInCode(newParentOctalCode);
int newCodeLength = newParentCodeLength + oldCodeLength;
@ -280,7 +282,7 @@ unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char*
return newCode;
}
bool isAncestorOf(unsigned char* possibleAncestor, unsigned char* possibleDescendent, int descendentsChild) {
bool isAncestorOf(const unsigned char* possibleAncestor, const unsigned char* possibleDescendent, int descendentsChild) {
if (!possibleAncestor || !possibleDescendent) {
return false;
}
@ -350,7 +352,7 @@ unsigned char* hexStringToOctalCode(const QString& input) {
return bytes;
}
QString octalCodeToHexString(unsigned char* octalCode) {
QString octalCodeToHexString(const unsigned char* octalCode) {
const int HEX_NUMBER_BASE = 16;
const int HEX_BYTE_SIZE = 2;
QString output;

View file

@ -20,27 +20,28 @@ const int RED_INDEX = 0;
const int GREEN_INDEX = 1;
const int BLUE_INDEX = 2;
void printOctalCode(unsigned char * octalCode);
void printOctalCode(const unsigned char * octalCode);
int bytesRequiredForCodeLength(unsigned char threeBitCodes);
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber);
int numberOfThreeBitSectionsInCode(unsigned char * octalCode);
unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels);
unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode,
int branchIndexWithDescendant(const unsigned char * ancestorOctalCode, const unsigned char * descendantOctalCode);
unsigned char * childOctalCode(const unsigned char * parentOctalCode, char childNumber);
int numberOfThreeBitSectionsInCode(const unsigned char * octalCode);
unsigned char* chopOctalCode(const unsigned char* originalOctalCode, int chopLevels);
unsigned char* rebaseOctalCode(const unsigned char* originalOctalCode, const unsigned char* newParentOctalCode,
bool includeColorSpace = false);
const int CHECK_NODE_ONLY = -1;
bool isAncestorOf(unsigned char* possibleAncestor, unsigned char* possibleDescendent, int descendentsChild = CHECK_NODE_ONLY);
bool isAncestorOf(const unsigned char* possibleAncestor, const unsigned char* possibleDescendent,
int descendentsChild = CHECK_NODE_ONLY);
// Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return
// but other than that these do the same thing.
float * firstVertexForCode(unsigned char * octalCode);
void copyFirstVertexForCode(unsigned char * octalCode, float* output);
float * firstVertexForCode(const unsigned char * octalCode);
void copyFirstVertexForCode(const unsigned char * octalCode, float* output);
struct VoxelPositionSize {
float x, y, z, s;
};
void voxelDetailsForCode(unsigned char* octalCode, VoxelPositionSize& voxelPositionSize);
void voxelDetailsForCode(const unsigned char* octalCode, VoxelPositionSize& voxelPositionSize);
typedef enum {
ILLEGAL_CODE = -2,
@ -49,9 +50,9 @@ typedef enum {
GREATER_THAN = 1
} OctalCodeComparison;
OctalCodeComparison compareOctalCodes(unsigned char* code1, unsigned char* code2);
OctalCodeComparison compareOctalCodes(const unsigned char* code1, const unsigned char* code2);
QString octalCodeToHexString(unsigned char* octalCode);
QString octalCodeToHexString(const unsigned char* octalCode);
unsigned char* hexStringToOctalCode(const QString& input);
#endif /* defined(__hifi__OctalCode__) */

View file

@ -29,8 +29,8 @@ bool VoxelPersistThread::process() {
_initialLoad = true;
qDebug("loading voxels from file: %s...\n", _filename);
qDebug("sizeof(oldVoxelNode)=%ld sizeof(VoxelNode)=%ld sizeof(AABox)=%ld sizeof(oldAABox)=%ld\n",
sizeof(oldVoxelNode), sizeof(VoxelNode), sizeof(AABox), sizeof(oldAABox));
qDebug("sizeof(oldVoxelNode)=%ld sizeof(VoxelNode)=%ld sizeof(smallerVoxelNodeTest1)=%ld sizeof(AABox)=%ld sizeof(oldAABox)=%ld\n",
sizeof(oldVoxelNode), sizeof(VoxelNode), sizeof(smallerVoxelNodeTest1), sizeof(AABox), sizeof(oldAABox));
bool persistantFileRead = _tree->readFromSVOFile(_filename);
if (persistantFileRead) {

View file

@ -132,7 +132,7 @@ void JurisdictionMap::init(unsigned char* rootOctalCode, const std::vector<unsig
_endNodes = endNodes;
}
JurisdictionMap::Area JurisdictionMap::isMyJurisdiction(unsigned char* nodeOctalCode, int childIndex) const {
JurisdictionMap::Area JurisdictionMap::isMyJurisdiction(const unsigned char* nodeOctalCode, int childIndex) const {
// to be in our jurisdiction, we must be under the root...
// if the node is an ancestor of my root, then we return ABOVE

View file

@ -41,7 +41,7 @@ public:
JurisdictionMap(const char* rootHextString, const char* endNodesHextString);
~JurisdictionMap();
Area isMyJurisdiction(unsigned char* nodeOctalCode, int childIndex) const;
Area isMyJurisdiction(const unsigned char* nodeOctalCode, int childIndex) const;
bool writeToFile(const char* filename);
bool readFromFile(const char* filename);

View file

@ -42,7 +42,16 @@ VoxelNode::VoxelNode(unsigned char * octalCode) {
}
void VoxelNode::init(unsigned char * octalCode) {
_octalCode = octalCode;
int octalCodeLength = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(octalCode));
if (octalCodeLength > sizeof(_octalCode)) {
_octalCode._octalCodePointer = octalCode;
_octcodePointer = true;
_octcodeMemoryUsage += octalCodeLength;
} else {
_octcodePointer = false;
memcpy(_octalCode._octalCodeBuffer, octalCode, octalCodeLength);
delete[] octalCode;
}
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
_falseColored = false; // assume true color
@ -57,8 +66,9 @@ void VoxelNode::init(unsigned char * octalCode) {
}
_childCount = 0;
_glBufferIndex = GLBUFFER_INDEX_UNKNOWN;
_voxelSystem = NULL;
_unknownBufferIndex = true;
setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
setVoxelSystem(NULL);
_isDirty = true;
_shouldRender = false;
_sourceID = UNKNOWN_NODE_ID;
@ -66,21 +76,22 @@ void VoxelNode::init(unsigned char * octalCode) {
markWithChangedTime();
_voxelMemoryUsage += sizeof(VoxelNode);
_octcodeMemoryUsage += bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(getOctalCode()));
}
VoxelNode::~VoxelNode() {
notifyDeleteHooks();
_voxelMemoryUsage -= sizeof(VoxelNode);
_octcodeMemoryUsage -= bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(getOctalCode()));
_voxelNodeCount--;
if (isLeaf()) {
_voxelNodeLeafCount--;
}
delete[] _octalCode;
if (_octcodePointer) {
_octcodeMemoryUsage -= bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(getOctalCode()));
delete[] _octalCode._octalCodePointer;
}
// delete all of this node's children
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
@ -110,6 +121,31 @@ void VoxelNode::handleSubtreeChanged(VoxelTree* myTree) {
markWithChangedTime();
}
uint8_t VoxelNode::_nextIndex = 0;
std::map<VoxelSystem*, uint8_t> VoxelNode::_mapVoxelSystemPointersToIndex;
std::map<uint8_t, VoxelSystem*> VoxelNode::_mapIndexToVoxelSystemPointers;
VoxelSystem* VoxelNode::getVoxelSystem() const {
if (_mapIndexToVoxelSystemPointers.end() != _mapIndexToVoxelSystemPointers.find(_voxelSystemIndex)) {
return _mapIndexToVoxelSystemPointers[_voxelSystemIndex];
}
return NULL;
}
void VoxelNode::setVoxelSystem(VoxelSystem* voxelSystem) {
uint8_t index;
if (_mapVoxelSystemPointersToIndex.end() != _mapVoxelSystemPointersToIndex.find(voxelSystem)) {
index = _mapVoxelSystemPointersToIndex[voxelSystem];
} else {
index = _nextIndex;
_nextIndex++;
_mapVoxelSystemPointersToIndex[voxelSystem] = index;
_mapIndexToVoxelSystemPointers[index] = voxelSystem;
}
_voxelSystemIndex = index;
}
void VoxelNode::setShouldRender(bool shouldRender) {
// if shouldRender is changing, then consider ourselves dirty
if (shouldRender != _shouldRender) {
@ -170,7 +206,7 @@ VoxelNode* VoxelNode::addChildAtIndex(int childIndex) {
}
_children[childIndex] = new VoxelNode(childOctalCode(getOctalCode(), childIndex));
_children[childIndex]->setVoxelSystem(_voxelSystem); // our child is always part of our voxel system NULL ok
_children[childIndex]->setVoxelSystem(getVoxelSystem()); // our child is always part of our voxel system NULL ok
_isDirty = true;
_childCount++;
markWithChangedTime();

View file

@ -41,7 +41,7 @@ public:
VoxelNode(unsigned char * octalCode); // regular constructor
~VoxelNode();
unsigned char* getOctalCode() const { return _octalCode; }
const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode._octalCodePointer : &_octalCode._octalCodeBuffer[0]; }
VoxelNode* getChildAtIndex(int childIndex) const { return _children[childIndex]; }
void deleteChildAtIndex(int childIndex);
VoxelNode* removeChildAtIndex(int childIndex);
@ -83,11 +83,10 @@ public:
void handleSubtreeChanged(VoxelTree* myTree);
glBufferIndex getBufferIndex() const { return _glBufferIndex; }
bool isKnownBufferIndex() const { return (_glBufferIndex != GLBUFFER_INDEX_UNKNOWN); }
void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; }
VoxelSystem* getVoxelSystem() const { return _voxelSystem; }
void setVoxelSystem(VoxelSystem* voxelSystem) { _voxelSystem = voxelSystem; }
bool isKnownBufferIndex() const { return !_unknownBufferIndex; }
void setBufferIndex(glBufferIndex index) { _glBufferIndex = index; _unknownBufferIndex =(index == GLBUFFER_INDEX_UNKNOWN);}
VoxelSystem* getVoxelSystem() const;
void setVoxelSystem(VoxelSystem* voxelSystem);
// Used by VoxelSystem for rendering in/out of view and LOD
void setShouldRender(bool shouldRender);
@ -125,25 +124,37 @@ private:
void notifyUpdateHooks();
VoxelNode* _children[8]; /// Client and server, pointers to child nodes, 64 bytes
AABox _box; /// Client and server, axis aligned box for bounds of this voxel, 48 bytes
unsigned char* _octalCode; /// Client and server, pointer to octal code for this node, 8 bytes
/// Client and server, buffer containing the octal code or a pointer to octal code for this node, 8 bytes
union octalCode_t {
unsigned char _octalCodeBuffer[8];
unsigned char* _octalCodePointer;
} _octalCode;
uint64_t _lastChanged; /// Client and server, timestamp this node was last changed, 8 bytes
glBufferIndex _glBufferIndex; /// Client only, vbo index for this voxel if being rendered, 8 bytes
VoxelSystem* _voxelSystem; /// Client only, pointer to VoxelSystem rendering this voxel, 8 bytes
uint32_t _glBufferIndex : 24, /// Client only, vbo index for this voxel if being rendered, 3 bytes
_voxelSystemIndex : 8; /// Client only, index to the VoxelSystem rendering this voxel, 1 bytes
static uint8_t _nextIndex;
static std::map<VoxelSystem*, uint8_t> _mapVoxelSystemPointersToIndex;
static std::map<uint8_t, VoxelSystem*> _mapIndexToVoxelSystemPointers;
float _density; /// Client and server, If leaf: density = 1, if internal node: 0-1 density of voxels inside, 4 bytes
int _childCount; /// Client and server, current child nodes set to non-null in _children, 4 bytes
nodeColor _trueColor; /// Client and server, true color of this voxel, 4 bytes
nodeColor _currentColor; /// Client only, false color of this voxel, 4 bytes
bool _falseColored; /// Client only, is this voxel false colored, 1 bytes
bool _isDirty; /// Client only, has this voxel changed since being rendered, 1 byte
bool _shouldRender; /// Client only, should this voxel render at this time, 1 byte
uint16_t _sourceID; /// Client only, stores node id of voxel server that sent his voxel, 2 bytes
bool _falseColored : 1, /// Client only, is this voxel false colored, 1 bit
_isDirty : 1, /// Client only, has this voxel changed since being rendered, 1 bit
_shouldRender : 1, /// Client only, should this voxel render at this time, 1 bit
_octcodePointer : 1, /// Client and Server only, is this voxel's octal code a pointer or buffer, 1 bit
_unknownBufferIndex : 1; /// Client only, is this voxel's VBO buffer the unknown buffer index, 1 bit
static std::vector<VoxelNodeDeleteHook*> _deleteHooks;
static std::vector<VoxelNodeUpdateHook*> _updateHooks;
@ -181,4 +192,46 @@ public:
bool _shouldRender; /// Client only, should this voxel render at this time, 1 byte
uint16_t _sourceID; /// Client only, stores node id of voxel server that sent his voxel, 2 bytes
};
class smallerVoxelNodeTest1 {
public:
AABox _box; // 48 bytes - 4x glm::vec3, 3 floats x 4 bytes = 48 bytes
// 16 bytes... 1x glm::vec3 + 1 float
union octalCode_t {
unsigned char _octalCodeBuffer[8];
unsigned char* _octalCodePointer;
} _octalCode; /// Client and server, buffer containing the octal code if it's smaller than 8 bytes or a
/// pointer to octal code for this node, 8 bytes
uint32_t _glBufferIndex : 24, /// Client only, vbo index for this voxel if being rendered, 3 bytes
_voxelSystemIndex : 8; /// Client only, index to the VoxelSystem rendering this voxel, 1 bytes
uint64_t _lastChanged; // 8 bytes, could be less?
void* _children; // 8 bytes (for 0 or 1 children), or 8 bytes * count + 1
nodeColor _trueColor; // 4 bytes, could be 3 bytes + 1 bit
nodeColor _currentColor; // 4 bytes ** CLIENT ONLY **
float _density; // 4 bytes - If leaf: density = 1, if internal node: 0-1 density of voxels inside... 4 bytes? do we need this?
// could make this 1 or 2 byte linear ratio...
uint16_t _sourceID; // 2 bytes - only used to colorize and kill sources? ** CLIENT ONLY **
unsigned char _childBitmask; // 1 byte
// Bitmask.... // 1 byte... made up of 5 bits so far... room for 3 more bools...
unsigned char _falseColored : 1, // 1 bit
_shouldRender : 1, // 1 bit
_isDirty : 1, // 1 bit
_octcodePointer : 1, // 1 bit
_unknownBufferIndex : 1; // 1 bit
};
#endif /* defined(__hifi__VoxelNode__) */

View file

@ -134,7 +134,7 @@ void VoxelTree::recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseV
VoxelNode* VoxelTree::nodeForOctalCode(VoxelNode* ancestorNode,
unsigned char* needleCode, VoxelNode** parentOfFoundNode) const {
const unsigned char* needleCode, VoxelNode** parentOfFoundNode) const {
// find the appropriate branch index based on this ancestorNode
if (*needleCode > 0) {
int branchForNeedle = branchIndexWithDescendant(ancestorNode->getOctalCode(), needleCode);
@ -1978,7 +1978,7 @@ bool VoxelTree::nudgeCheck(VoxelNode* node, void* extraData) {
NodeChunkArgs* args = (NodeChunkArgs*)extraData;
// get octal code of this node
unsigned char* octalCode = node->getOctalCode();
const unsigned char* octalCode = node->getOctalCode();
// get voxel position/size
VoxelPositionSize unNudgedDetails;
@ -2017,7 +2017,7 @@ void VoxelTree::nudgeLeaf(VoxelNode* node, void* extraData) {
NodeChunkArgs* args = (NodeChunkArgs*)extraData;
// get octal code of this node
unsigned char* octalCode = node->getOctalCode();
const unsigned char* octalCode = node->getOctalCode();
// get voxel position/size
VoxelPositionSize unNudgedDetails;

View file

@ -214,7 +214,7 @@ private:
static bool countVoxelsOperation(VoxelNode* node, void* extraData);
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, const unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes, ReadBitstreamToTreeParams& args);
@ -225,7 +225,7 @@ private:
/// Octal Codes of any subtrees currently being encoded. While any of these codes is being encoded, ancestors and
/// descendants of them can not be deleted.
std::set<unsigned char*> _codesBeingEncoded;
std::set<const unsigned char*> _codesBeingEncoded;
/// mutex lock to protect the encoding set
pthread_mutex_t _encodeSetLock;