fix crashing on deleting voxels in server and client

This commit is contained in:
ZappoMan 2013-05-22 13:23:01 -07:00
parent dfe7008a35
commit 06f2528d6a
5 changed files with 51 additions and 29 deletions

View file

@ -83,7 +83,7 @@ const glm::vec3 bugParts[VOXELS_PER_BUG] = {
glm::vec3(0,0,0),
glm::vec3(0,0,1),
glm::vec3(0,0,2),
// eyes
glm::vec3(1,0,3),
glm::vec3(-1,0,3),
@ -432,9 +432,9 @@ void* animateVoxels(void* args) {
// some animations
//sendVoxelBlinkMessage();
//sendBlinkingStringOfLights();
//sendBillboard();
renderMovingBug();
sendBlinkingStringOfLights();
sendBillboard();
//renderMovingBug();
double end = usecTimestampNow();
double elapsedSeconds = (end - ::start) / 1000000.0;

View file

@ -337,16 +337,15 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
} else {
voxelsUpdated += updateNodeInArraysAsPartialVBO(node);
}
node->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
// If the node has been asked to be deleted, but we've gotten to here, after updateNodeInArraysXXX()
// then it means our VBOs are "clean" and our vertices have been removed or not added. So we can now
// safely remove the node from the tree and actually delete it.
// otherwise honor our calculated shouldRender
if (node->isStagedForDeletion()) {
_tree->deleteVoxelCodeFromTree(node->getOctalCode());
}
node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered
return voxelsUpdated;
}

View file

@ -29,14 +29,15 @@ int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
return voxelSizeScale / powf(2, renderLevel);
}
VoxelTree::VoxelTree() :
VoxelTree::VoxelTree(bool shouldReaverage) :
voxelsCreated(0),
voxelsColored(0),
voxelsBytesRead(0),
voxelsCreatedStats(100),
voxelsColoredStats(100),
voxelsBytesReadStats(100),
_isDirty(true) {
_isDirty(true),
_shouldReaverage(shouldReaverage) {
rootNode = new VoxelNode();
}
@ -254,12 +255,13 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s, bool stage) {
unsigned char* octalCode = pointToVoxel(x,y,z,s,0,0,0);
deleteVoxelCodeFromTree(octalCode, stage);
delete octalCode; // cleanup memory
reaverageVoxelColors(rootNode);
}
// Note: uses the codeColorBuffer format, but the color's are ignored, because
// this only finds and deletes the node from the tree.
void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage) {
void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage, bool collapseEmptyTrees) {
VoxelNode* parentNode = NULL;
VoxelNode* nodeToDelete = nodeForOctalCode(rootNode, codeBuffer, &parentNode);
// If the node exists...
@ -276,14 +278,13 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage) {
}
// If we're not a colored leaf, and we have no children, then delete ourselves
// This will collapse the empty tree above us.
if (parentNode->getChildCount() == 0 && !parentNode->isColored()) {
// This will collapse the empty tree above us.
if (collapseEmptyTrees && parentNode->getChildCount() == 0 && !parentNode->isColored()) {
// Can't delete the root this way.
if (parentNode != rootNode) {
deleteVoxelCodeFromTree(parentNode->getOctalCode(),stage);
deleteVoxelCodeFromTree(parentNode->getOctalCode(), stage, collapseEmptyTrees);
}
}
reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode
_isDirty = true;
}
} else if (nodeToDelete->isLeaf()) {
@ -357,11 +358,12 @@ void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int buffe
unsigned char octets = (unsigned char)*pVoxelData;
int voxelDataSize = bytesRequiredForCodeLength(octets)+3; // 3 for color!
deleteVoxelCodeFromTree(pVoxelData);
deleteVoxelCodeFromTree(pVoxelData, ACTUALLY_DELETE, COLLAPSE_EMPTY_TREE);
pVoxelData+=voxelDataSize;
atByte+=voxelDataSize;
}
reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode
}
void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
@ -411,20 +413,23 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
}
void VoxelTree::reaverageVoxelColors(VoxelNode *startNode) {
bool hasChildren = false;
// if our tree is a reaveraging tree, then we do this, otherwise we don't do anything
if (_shouldReaverage) {
bool hasChildren = false;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (startNode->getChildAtIndex(i)) {
reaverageVoxelColors(startNode->getChildAtIndex(i));
hasChildren = true;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (startNode->getChildAtIndex(i)) {
reaverageVoxelColors(startNode->getChildAtIndex(i));
hasChildren = true;
}
}
}
if (hasChildren) {
bool childrenCollapsed = startNode->collapseIdenticalLeaves();
if (hasChildren) {
bool childrenCollapsed = startNode->collapseIdenticalLeaves();
if (!childrenCollapsed) {
startNode->setColorFromAverageOfChildren();
if (!childrenCollapsed) {
startNode->setColorFromAverageOfChildren();
}
}
}
}

View file

@ -24,6 +24,10 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
#define NO_COLOR false
#define WANT_COLOR true
#define IGNORE_VIEW_FRUSTUM NULL
#define JUST_STAGE_DELETION true
#define ACTUALLY_DELETE false
#define COLLAPSE_EMPTY_TREE true
#define DONT_COLLAPSE false
class VoxelTree {
public:
@ -37,7 +41,7 @@ public:
SimpleMovingAverage voxelsColoredStats;
SimpleMovingAverage voxelsBytesReadStats;
VoxelTree();
VoxelTree(bool shouldReaverage = false);
~VoxelTree();
VoxelNode *rootNode;
@ -49,7 +53,8 @@ public:
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes,
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS);
void readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive = false);
void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = false);
void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = ACTUALLY_DELETE,
bool collapseEmptyTrees = DONT_COLLAPSE);
void printTreeForDebugging(VoxelNode *startNode);
void reaverageVoxelColors(VoxelNode *startNode);
@ -111,6 +116,7 @@ private:
bool _isDirty;
unsigned long int _nodesChangedFromBitstream;
bool _shouldReaverage;
};
int boundaryDistanceForRenderLevel(unsigned int renderLevel);

View file

@ -49,7 +49,7 @@ int PACKETS_PER_CLIENT_PER_INTERVAL = 50;
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
VoxelTree randomTree;
VoxelTree randomTree(true); // this is a reaveraging tree
bool wantVoxelPersist = true;
bool wantLocalDomain = false;
@ -225,12 +225,17 @@ void resInVoxelDistributor(AgentList* agentList,
}
}
pthread_mutex_t treeLock;
// Version of voxel distributor that sends the deepest LOD level at once
void deepestLevelVoxelDistributor(AgentList* agentList,
AgentList::iterator& agent,
VoxelAgentData* agentData,
bool viewFrustumChanged) {
pthread_mutex_lock(&::treeLock);
int maxLevelReached = 0;
double start = usecTimestampNow();
@ -356,6 +361,8 @@ void deepestLevelVoxelDistributor(AgentList* agentList,
} // end if bag wasn't empty, and so we sent stuff...
pthread_mutex_unlock(&::treeLock);
}
double lastPersistVoxels = 0;
@ -434,8 +441,10 @@ void attachVoxelAgentDataToAgent(Agent *newAgent) {
}
}
int main(int argc, const char * argv[])
{
int main(int argc, const char * argv[]) {
pthread_mutex_init(&::treeLock, NULL);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_VOXEL, VOXEL_LISTEN_PORT);
setvbuf(stdout, NULL, _IOLBF, 0);
@ -605,7 +614,9 @@ int main(int argc, const char * argv[])
// Send these bits off to the VoxelTree class to process them
//printf("got Erase Voxels message, have voxel tree do the work... randomTree.processRemoveVoxelBitstream()\n");
pthread_mutex_lock(&::treeLock);
randomTree.processRemoveVoxelBitstream((unsigned char*)packetData,receivedBytes);
pthread_mutex_unlock(&::treeLock);
}
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
@ -653,6 +664,7 @@ int main(int argc, const char * argv[])
}
pthread_join(sendVoxelThread, NULL);
pthread_mutex_destroy(&::treeLock);
return 0;
}