} break; } } } return true; // keep going!} bool VoxelSystem::isViewChanging() { bool result = false; // assume the best // If our viewFrustum has changed since our _lastKnowViewFrustum if (!_lastKnowViewFrustum.matches(Application::getInstance()->getViewFrustum())) { result = true; _lastKnowViewFrustum = *Application::getInstance()->getViewFrustum(); // save last known } return result;} bool VoxelSystem::hasViewChanged() { bool result = false; // assume the best // If we're still changing, report no change yet. if (isViewChanging()) { return false; } // If our viewFrustum has changed since our _lastKnowViewFrustum if (!_lastStableViewFrustum.matches(Application::getInstance()->getViewFrustum())) { result = true; _lastStableViewFrustum = *Application::getInstance()->getViewFrustum(); // save last stable } return result;} void VoxelSystem::removeOutOfView() { PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); removeOutOfViewArgs args(this); _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args); if (args.nodesRemoved) { _tree->setDirtyBit(); } bool showRemoveDebugDetails = false; if (showRemoveDebugDetails) { qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n", args.nodesScanned, args.nodesRemoved, args.nodesInside, args.nodesIntersect, args.nodesOutside, _removedVoxels.count() ); }} bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance, BoxFace& face) { pthread_mutex_lock(&_treeLock); VoxelNode* node; if (!_tree->findRayIntersection(origin, direction, node, distance, face)) { pthread_mutex_unlock(&_treeLock); return false; } detail.x = node->getCorner().x; detail.y = node->getCorner().y; detail.z = node->getCorner().z; detail.s = node->getScale(); detail.red = node->getColor()[0]; detail.green = node->getColor()[1]; detail.blue = node->getColor()[2]; pthread_mutex_unlock(&_treeLock); return true;} bool VoxelSystem::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) { pthread_mutex_lock(&_treeLock); bool result = _tree->findSpherePenetration(center, radius, penetration); pthread_mutex_unlock(&_treeLock); return result;} bool VoxelSystem::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) { pthread_mutex_lock(&_treeLock); bool result = _tree->findCapsulePenetration(start, end, radius, penetration); pthread_mutex_unlock(&_treeLock); return result;} class falseColorizeRandomEveryOtherArgs {public: falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {}; unsigned long totalNodes; unsigned long colorableNodes; unsigned long coloredNodes; bool colorThis;}; bool VoxelSystem::falseColorizeRandomEveryOtherOperation(VoxelNode* node, void* extraData) { falseColorizeRandomEveryOtherArgs* args = (falseColorizeRandomEveryOtherArgs*)extraData; args->totalNodes++; if (node->isColored()) { args->colorableNodes++; if (args->colorThis) { args->coloredNodes++; node->setFalseColor(255, randomColorValue(150), randomColorValue(150)); } args->colorThis = !args->colorThis; } return true; // keep going!} void VoxelSystem::falseColorizeRandomEveryOther() { falseColorizeRandomEveryOtherArgs args; _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args); qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n", args.totalNodes, args.colorableNodes, args.coloredNodes); _tree->setDirtyBit(); setupNewVoxelsForDrawing();} class collectStatsForTreesAndVBOsArgs {public: collectStatsForTreesAndVBOsArgs() : totalNodes(0), dirtyNodes(0), shouldRenderNodes(0), coloredNodes(0), nodesInVBO(0), nodesInVBONotShouldRender(0), nodesInVBOOverExpectedMax(0), duplicateVBOIndex(0), leafNodes(0) { memset(hasIndexFound, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); }; unsigned long totalNodes; unsigned long dirtyNodes; unsigned long shouldRenderNodes; unsigned long coloredNodes; unsigned long nodesInVBO; unsigned long nodesInVBONotShouldRender; unsigned long nodesInVBOOverExpectedMax; unsigned long duplicateVBOIndex; unsigned long leafNodes; unsigned long expectedMax; bool hasIndexFound[MAX_VOXELS_PER_SYSTEM];}; bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) { collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData; args->totalNodes++; if (node->isLeaf()) { args->leafNodes++; } if (node->isColored()) { args->coloredNodes++; } if (node->getShouldRender()) { args->shouldRenderNodes++; } if (node->isDirty()) { args->dirtyNodes++; } if (node->isKnownBufferIndex()) { args->nodesInVBO++; unsigned long nodeIndex = node->getBufferIndex(); if (args->hasIndexFound[nodeIndex]) { args->duplicateVBOIndex++; qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex, debug::valueOf(node->isDirty()), debug::valueOf(node->getShouldRender())); } else { args->hasIndexFound[nodeIndex] = true; } if (nodeIndex > args->expectedMax) { args->nodesInVBOOverExpectedMax++; } // if it's in VBO but not-shouldRender, track that also... if (!node->getShouldRender()) { args->nodesInVBONotShouldRender++; } } return true; // keep going!} void VoxelSystem::collectStatsForTreesAndVBOs() { PerformanceWarning warn(true, "collectStatsForTreesAndVBOs()", true); glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN; glBufferIndex maxDirty = 0; for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { if (_writeVoxelDirtyArray[i]) { minDirty = std::min(minDirty,i); maxDirty = std::max(maxDirty,i); } } collectStatsForTreesAndVBOsArgs args; args.expectedMax = _voxelsInWriteArrays; _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args); qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n", args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes); qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty), _voxelsInWriteArrays, minDirty, maxDirty); qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n", args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender); glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; glBufferIndex maxInVBO = 0; for (glBufferIndex i = 0; i < MAX_VOXELS_PER_SYSTEM; i++) { if (args.hasIndexFound[i]) { minInVBO = std::min(minInVBO,i); maxInVBO = std::max(maxInVBO,i); } } qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n", minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); } void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { pthread_mutex_lock(&_treeLock); _tree->deleteVoxelAt(x, y, z, s); // redraw! setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? pthread_mutex_unlock(&_treeLock);}; VoxelNode* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { return _tree->getVoxelAt(x, y, z, s); }; void VoxelSystem::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive) { pthread_mutex_lock(&_treeLock); //qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s); _tree->createVoxel(x, y, z, s, red, green, blue, destructive); setupNewVoxelsForDrawing(); pthread_mutex_unlock(&_treeLock);}; void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) { _tree->createLine(point1, point2, unitSize, color, destructive); setupNewVoxelsForDrawing(); }; void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, creationMode mode, bool destructive, bool debug) { _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug); setupNewVoxelsForDrawing(); }; void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) { _tree->copySubTreeIntoNewTree(startNode, destinationTree, rebaseToRoot);} void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) { _tree->copyFromTreeIntoSubTree(sourceTree, destinationNode);} struct FalseColorizeOccludedArgs { ViewFrustum* viewFrustum; CoverageMap* map; CoverageMapV2* mapV2; VoxelTree* tree; long totalVoxels; long coloredVoxels; long occludedVoxels; long notOccludedVoxels; long outOfView; long subtreeVoxelsSkipped; long nonLeaves; long nonLeavesOutOfView; long nonLeavesOccluded;}; struct FalseColorizeSubTreeOperationArgs { unsigned char color[NUMBER_OF_COLORS]; long voxelsTouched;}; bool VoxelSystem::falseColorizeSubTreeOperation(VoxelNode* node, void* extraData) { if (node->getShouldRender()) { FalseColorizeSubTreeOperationArgs* args = (FalseColorizeSubTreeOperationArgs*) extraData; node->setFalseColor(args->color[0], args->color[1], args->color[2]); args->voxelsTouched++; } return true; } bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraData) { FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; args->totalVoxels++; // If we are a parent, let's see if we're completely occluded. if (!node->isLeaf()) { args->nonLeaves++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->nonLeavesOutOfView++; delete voxelPolygon; return true; } CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, false); if (result == OCCLUDED) { args->nonLeavesOccluded++; delete voxelPolygon; FalseColorizeSubTreeOperationArgs subArgs; subArgs.color[0] = 0; subArgs.color[1] = 255; subArgs.color[2] = 0; subArgs.voxelsTouched = 0; args->tree->recurseNodeWithOperation(node, falseColorizeSubTreeOperation, &subArgs ); args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); args->totalVoxels += (subArgs.voxelsTouched - 1); return false; } delete voxelPolygon; return true; // keep looking... } if (node->isLeaf() && node->isColored() && node->getShouldRender()) { args->coloredVoxels++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->outOfView++; delete voxelPolygon; return true; } CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, true); if (result == OCCLUDED) { node->setFalseColor(255, 0, 0); args->occludedVoxels++; } else if (result == STORED) { args->notOccludedVoxels++; //qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n"); } else if (result == DOESNT_FIT) { //qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n"); } } return true; // keep going!} void VoxelSystem::falseColorizeOccluded() { PerformanceWarning warn(true, "falseColorizeOccluded()",true); myCoverageMap.erase(); FalseColorizeOccludedArgs args; args.viewFrustum = Application::getInstance()->getViewFrustum(); args.map = &myCoverageMap; args.totalVoxels = 0; args.coloredVoxels = 0; args.occludedVoxels = 0; args.notOccludedVoxels = 0; args.outOfView = 0; args.subtreeVoxelsSkipped = 0; args.nonLeaves = 0; args.nonLeavesOutOfView = 0; args.nonLeavesOccluded = 0; args.tree = _tree; VoxelProjectedPolygon::pointInside_calls = 0; VoxelProjectedPolygon::occludes_calls = 0; VoxelProjectedPolygon::intersects_calls = 0; glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE); _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args); qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n", position.x, position.y, args.totalVoxels, args.coloredVoxels, args.occludedVoxels, args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded, VoxelProjectedPolygon::pointInside_calls, VoxelProjectedPolygon::occludes_calls, VoxelProjectedPolygon::intersects_calls ); //myCoverageMap.erase(); _tree->setDirtyBit(); setupNewVoxelsForDrawing();} bool VoxelSystem::falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData) { FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; args->totalVoxels++; // If we are a parent, let's see if we're completely occluded. if (!node->isLeaf()) { args->nonLeaves++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->nonLeavesOutOfView++; delete voxelPolygon; return true; } CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, false); if (result == V2_OCCLUDED) { args->nonLeavesOccluded++; delete voxelPolygon; FalseColorizeSubTreeOperationArgs subArgs; subArgs.color[0] = 0; subArgs.color[1] = 255; subArgs.color[2] = 0; subArgs.voxelsTouched = 0; args->tree->recurseNodeWithOperation(node, falseColorizeSubTreeOperation, &subArgs ); args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); args->totalVoxels += (subArgs.voxelsTouched - 1); return false; } delete voxelPolygon; return true; // keep looking... } if (node->isLeaf() && node->isColored() && node->getShouldRender()) { args->coloredVoxels++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->outOfView++; delete voxelPolygon; return true; } CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, true); if (result == V2_OCCLUDED) { node->setFalseColor(255, 0, 0); args->occludedVoxels++; } else if (result == V2_STORED) { args->notOccludedVoxels++; //qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n"); } else if (result == V2_DOESNT_FIT) { //qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n"); } delete voxelPolygon; // V2 maps don't store polygons, so we're always in charge of freeing } return true; // keep going!} void VoxelSystem::falseColorizeOccludedV2() { PerformanceWarning warn(true, "falseColorizeOccludedV2()",true); myCoverageMapV2.erase(); CoverageMapV2::wantDebugging = true;Lines 1001–1500 of 1579. Previous lines Load more
} break; } } } return true; // keep going! } bool VoxelSystem::isViewChanging() { bool result = false; // assume the best // If our viewFrustum has changed since our _lastKnowViewFrustum if (!_lastKnowViewFrustum.matches(Application::getInstance()->getViewFrustum())) { result = true; _lastKnowViewFrustum = *Application::getInstance()->getViewFrustum(); // save last known } return result; } bool VoxelSystem::hasViewChanged() { bool result = false; // assume the best // If we're still changing, report no change yet. if (isViewChanging()) { return false; } // If our viewFrustum has changed since our _lastKnowViewFrustum if (!_lastStableViewFrustum.matches(Application::getInstance()->getViewFrustum())) { result = true; _lastStableViewFrustum = *Application::getInstance()->getViewFrustum(); // save last stable } return result; } void VoxelSystem::removeOutOfView() { PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); removeOutOfViewArgs args(this); _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args); if (args.nodesRemoved) { _tree->setDirtyBit(); } bool showRemoveDebugDetails = false; if (showRemoveDebugDetails) { qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n", args.nodesScanned, args.nodesRemoved, args.nodesInside, args.nodesIntersect, args.nodesOutside, _removedVoxels.count() ); } } bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance, BoxFace& face) { pthread_mutex_lock(&_treeLock); VoxelNode* node; if (!_tree->findRayIntersection(origin, direction, node, distance, face)) { pthread_mutex_unlock(&_treeLock); return false; } detail.x = node->getCorner().x; detail.y = node->getCorner().y; detail.z = node->getCorner().z; detail.s = node->getScale(); detail.red = node->getColor()[0]; detail.green = node->getColor()[1]; detail.blue = node->getColor()[2]; pthread_mutex_unlock(&_treeLock); return true; } bool VoxelSystem::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) { pthread_mutex_lock(&_treeLock); bool result = _tree->findSpherePenetration(center, radius, penetration); pthread_mutex_unlock(&_treeLock); return result; } bool VoxelSystem::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) { pthread_mutex_lock(&_treeLock); bool result = _tree->findCapsulePenetration(start, end, radius, penetration); pthread_mutex_unlock(&_treeLock); return result; } class falseColorizeRandomEveryOtherArgs { public: falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {}; unsigned long totalNodes; unsigned long colorableNodes; unsigned long coloredNodes; bool colorThis; }; bool VoxelSystem::falseColorizeRandomEveryOtherOperation(VoxelNode* node, void* extraData) { falseColorizeRandomEveryOtherArgs* args = (falseColorizeRandomEveryOtherArgs*)extraData; args->totalNodes++; if (node->isColored()) { args->colorableNodes++; if (args->colorThis) { args->coloredNodes++; node->setFalseColor(255, randomColorValue(150), randomColorValue(150)); } args->colorThis = !args->colorThis; } return true; // keep going! } void VoxelSystem::falseColorizeRandomEveryOther() { falseColorizeRandomEveryOtherArgs args; _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args); qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n", args.totalNodes, args.colorableNodes, args.coloredNodes); _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } class collectStatsForTreesAndVBOsArgs { public: collectStatsForTreesAndVBOsArgs() : totalNodes(0), dirtyNodes(0), shouldRenderNodes(0), coloredNodes(0), nodesInVBO(0), nodesInVBONotShouldRender(0), nodesInVBOOverExpectedMax(0), duplicateVBOIndex(0), leafNodes(0) { memset(hasIndexFound, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); }; unsigned long totalNodes; unsigned long dirtyNodes; unsigned long shouldRenderNodes; unsigned long coloredNodes; unsigned long nodesInVBO; unsigned long nodesInVBONotShouldRender; unsigned long nodesInVBOOverExpectedMax; unsigned long duplicateVBOIndex; unsigned long leafNodes; unsigned long expectedMax; bool hasIndexFound[MAX_VOXELS_PER_SYSTEM]; }; bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) { collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData; args->totalNodes++; if (node->isLeaf()) { args->leafNodes++; } if (node->isColored()) { args->coloredNodes++; } if (node->getShouldRender()) { args->shouldRenderNodes++; } if (node->isDirty()) { args->dirtyNodes++; } if (node->isKnownBufferIndex()) { args->nodesInVBO++; unsigned long nodeIndex = node->getBufferIndex(); if (args->hasIndexFound[nodeIndex]) { args->duplicateVBOIndex++; qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex, debug::valueOf(node->isDirty()), debug::valueOf(node->getShouldRender())); } else { args->hasIndexFound[nodeIndex] = true; } if (nodeIndex > args->expectedMax) { args->nodesInVBOOverExpectedMax++; } // if it's in VBO but not-shouldRender, track that also... if (!node->getShouldRender()) { args->nodesInVBONotShouldRender++; } } return true; // keep going! } void VoxelSystem::collectStatsForTreesAndVBOs() { PerformanceWarning warn(true, "collectStatsForTreesAndVBOs()", true); glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN; glBufferIndex maxDirty = 0; for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { if (_writeVoxelDirtyArray[i]) { minDirty = std::min(minDirty,i); maxDirty = std::max(maxDirty,i); } } collectStatsForTreesAndVBOsArgs args; args.expectedMax = _voxelsInWriteArrays; _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args); qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n", args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes); qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty), _voxelsInWriteArrays, minDirty, maxDirty); qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n", args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender); glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; glBufferIndex maxInVBO = 0; for (glBufferIndex i = 0; i < MAX_VOXELS_PER_SYSTEM; i++) { if (args.hasIndexFound[i]) { minInVBO = std::min(minInVBO,i); maxInVBO = std::max(maxInVBO,i); } } qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n", minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); } void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { pthread_mutex_lock(&_treeLock); _tree->deleteVoxelAt(x, y, z, s); // redraw! setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? pthread_mutex_unlock(&_treeLock); }; VoxelNode* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { return _tree->getVoxelAt(x, y, z, s); }; void VoxelSystem::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive) { pthread_mutex_lock(&_treeLock); //qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s); _tree->createVoxel(x, y, z, s, red, green, blue, destructive); setupNewVoxelsForDrawing(); pthread_mutex_unlock(&_treeLock); }; void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) { _tree->createLine(point1, point2, unitSize, color, destructive); setupNewVoxelsForDrawing(); }; void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, creationMode mode, bool destructive, bool debug) { _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug); setupNewVoxelsForDrawing(); }; void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) { _tree->copySubTreeIntoNewTree(startNode, destinationTree, rebaseToRoot); } void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) { _tree->copyFromTreeIntoSubTree(sourceTree, destinationNode); } struct FalseColorizeOccludedArgs { ViewFrustum* viewFrustum; CoverageMap* map; CoverageMapV2* mapV2; VoxelTree* tree; long totalVoxels; long coloredVoxels; long occludedVoxels; long notOccludedVoxels; long outOfView; long subtreeVoxelsSkipped; long nonLeaves; long nonLeavesOutOfView; long nonLeavesOccluded; }; struct FalseColorizeSubTreeOperationArgs { unsigned char color[NUMBER_OF_COLORS]; long voxelsTouched; }; bool VoxelSystem::falseColorizeSubTreeOperation(VoxelNode* node, void* extraData) { if (node->getShouldRender()) { FalseColorizeSubTreeOperationArgs* args = (FalseColorizeSubTreeOperationArgs*) extraData; node->setFalseColor(args->color[0], args->color[1], args->color[2]); args->voxelsTouched++; } return true; } bool VoxelSystem::falseColorizeOccludedOperation(VoxelNode* node, void* extraData) { FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; args->totalVoxels++; // If we are a parent, let's see if we're completely occluded. if (!node->isLeaf()) { args->nonLeaves++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->nonLeavesOutOfView++; delete voxelPolygon; return true; } CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, false); if (result == OCCLUDED) { args->nonLeavesOccluded++; delete voxelPolygon; FalseColorizeSubTreeOperationArgs subArgs; subArgs.color[0] = 0; subArgs.color[1] = 255; subArgs.color[2] = 0; subArgs.voxelsTouched = 0; args->tree->recurseNodeWithOperation(node, falseColorizeSubTreeOperation, &subArgs ); args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); args->totalVoxels += (subArgs.voxelsTouched - 1); return false; } delete voxelPolygon; return true; // keep looking... } if (node->isLeaf() && node->isColored() && node->getShouldRender()) { args->coloredVoxels++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->outOfView++; delete voxelPolygon; return true; } CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, true); if (result == OCCLUDED) { node->setFalseColor(255, 0, 0); args->occludedVoxels++; } else if (result == STORED) { args->notOccludedVoxels++; //qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n"); } else if (result == DOESNT_FIT) { //qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n"); } } return true; // keep going! } void VoxelSystem::falseColorizeOccluded() { PerformanceWarning warn(true, "falseColorizeOccluded()",true); myCoverageMap.erase(); FalseColorizeOccludedArgs args; args.viewFrustum = Application::getInstance()->getViewFrustum(); args.map = &myCoverageMap; args.totalVoxels = 0; args.coloredVoxels = 0; args.occludedVoxels = 0; args.notOccludedVoxels = 0; args.outOfView = 0; args.subtreeVoxelsSkipped = 0; args.nonLeaves = 0; args.nonLeavesOutOfView = 0; args.nonLeavesOccluded = 0; args.tree = _tree; VoxelProjectedPolygon::pointInside_calls = 0; VoxelProjectedPolygon::occludes_calls = 0; VoxelProjectedPolygon::intersects_calls = 0; glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE); _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args); qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n", position.x, position.y, args.totalVoxels, args.coloredVoxels, args.occludedVoxels, args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded, VoxelProjectedPolygon::pointInside_calls, VoxelProjectedPolygon::occludes_calls, VoxelProjectedPolygon::intersects_calls ); //myCoverageMap.erase(); _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } bool VoxelSystem::falseColorizeOccludedV2Operation(VoxelNode* node, void* extraData) { FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; args->totalVoxels++; // If we are a parent, let's see if we're completely occluded. if (!node->isLeaf()) { args->nonLeaves++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->nonLeavesOutOfView++; delete voxelPolygon; return true; } CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, false); if (result == V2_OCCLUDED) { args->nonLeavesOccluded++; delete voxelPolygon; FalseColorizeSubTreeOperationArgs subArgs; subArgs.color[0] = 0; subArgs.color[1] = 255; subArgs.color[2] = 0; subArgs.voxelsTouched = 0; args->tree->recurseNodeWithOperation(node, falseColorizeSubTreeOperation, &subArgs ); args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); args->totalVoxels += (subArgs.voxelsTouched - 1); return false; } delete voxelPolygon; return true; // keep looking... } if (node->isLeaf() && node->isColored() && node->getShouldRender()) { args->coloredVoxels++; AABox voxelBox = node->getAABox(); voxelBox.scale(TREE_SCALE); VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); // If we're not all in view, then ignore it, and just return. But keep searching... if (!voxelPolygon->getAllInView()) { args->outOfView++; delete voxelPolygon; return true; } CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, true); if (result == V2_OCCLUDED) { node->setFalseColor(255, 0, 0); args->occludedVoxels++; } else if (result == V2_STORED) { args->notOccludedVoxels++; //qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n"); } else if (result == V2_DOESNT_FIT) { //qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n"); } delete voxelPolygon; // V2 maps don't store polygons, so we're always in charge of freeing } return true; // keep going! } void VoxelSystem::falseColorizeOccludedV2() { PerformanceWarning warn(true, "falseColorizeOccludedV2()",true); myCoverageMapV2.erase(); CoverageMapV2::wantDebugging = true;