From 02bc25f79748761a5df9c3f55e1206d23737c977 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Sep 2013 09:51:15 -0700 Subject: [PATCH] implement SVO fill down in voxel-edit --- voxel-edit/src/main.cpp | 267 ++++++++++++++++++++++++++++------------ 1 file changed, 188 insertions(+), 79 deletions(-) diff --git a/voxel-edit/src/main.cpp b/voxel-edit/src/main.cpp index 990f0fa5b8..11242452dd 100644 --- a/voxel-edit/src/main.cpp +++ b/voxel-edit/src/main.cpp @@ -55,6 +55,184 @@ void voxelTutorial(VoxelTree * tree) { } } + +void processSplitSVOFile(const char* splitSVOFile,const char* splitJurisdictionRoot,const char* splitJurisdictionEndNodes) { + char outputFileName[512]; + + printf("splitSVOFile: %s Jurisdictions Root: %s EndNodes: %s\n", + splitSVOFile, splitJurisdictionRoot, splitJurisdictionEndNodes); + + VoxelTree rootSVO; + + rootSVO.readFromSVOFile(splitSVOFile); + JurisdictionMap jurisdiction(splitJurisdictionRoot, splitJurisdictionEndNodes); + + printf("Jurisdiction Root Octcode: "); + printOctalCode(jurisdiction.getRootOctalCode()); + + printf("Jurisdiction End Nodes: %d \n", jurisdiction.getEndNodeCount()); + for (int i = 0; i < jurisdiction.getEndNodeCount(); i++) { + unsigned char* endNodeCode = jurisdiction.getEndNodeOctalCode(i); + printf("End Node: %d ", i); + printOctalCode(endNodeCode); + + // get the endNode details + VoxelPositionSize endNodeDetails; + voxelDetailsForCode(endNodeCode, endNodeDetails); + + // Now, create a split SVO for the EndNode. + // copy the EndNode into a temporary tree + VoxelTree endNodeTree; + + // create a small voxels at corners of the endNode Tree, this will is a hack + // to work around a bug in voxel server that will send Voxel not exists + // for regions that don't contain anything even if they're not in the + // jurisdiction of the server + // This hack assumes the end nodes for demo dinner since it only guarantees + // nodes in the 8 child voxels of the main root voxel + const float verySmall = 0.015625; + endNodeTree.createVoxel(0.0, 0.0, 0.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(1.0, 0.0, 0.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(0.0, 1.0, 0.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(0.0, 0.0, 1.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(1.0, 1.0, 1.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(1.0, 1.0, 0.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(0.0, 1.0, 1.0, verySmall, 1, 1, 1, true); + endNodeTree.createVoxel(1.0, 0.0, 1.0, verySmall, 1, 1, 1, true); + + // Delete the voxel for the EndNode from the temporary tree, so we can + // import our endNode content into it... + endNodeTree.deleteVoxelCodeFromTree(endNodeCode, COLLAPSE_EMPTY_TREE); + + VoxelNode* endNode = rootSVO.getVoxelAt(endNodeDetails.x, + endNodeDetails.y, + endNodeDetails.z, + endNodeDetails.s); + + rootSVO.copySubTreeIntoNewTree(endNode, &endNodeTree, false); + + sprintf(outputFileName, "splitENDNODE%d%s", i, splitSVOFile); + printf("outputFile: %s\n", outputFileName); + endNodeTree.writeToSVOFile(outputFileName); + + // Delete the voxel for the EndNode from the root tree... + rootSVO.deleteVoxelCodeFromTree(endNodeCode, COLLAPSE_EMPTY_TREE); + + // create a small voxel in center of each EndNode, this will is a hack + // to work around a bug in voxel server that will send Voxel not exists + // for regions that don't contain anything even if they're not in the + // jurisdiction of the server + float x = endNodeDetails.x + endNodeDetails.s * 0.5; + float y = endNodeDetails.y + endNodeDetails.s * 0.5; + float z = endNodeDetails.z + endNodeDetails.s * 0.5; + float s = endNodeDetails.s * verySmall; + + rootSVO.createVoxel(x, y, z, s, 1, 1, 1, true); + + } + + sprintf(outputFileName, "splitROOT%s", splitSVOFile); + printf("outputFile: %s\n", outputFileName); + rootSVO.writeToSVOFile(outputFileName); + + printf("exiting now\n"); +} + +class copyAndFillArgs { +public: + VoxelTree* destinationTree; + unsigned long outCount; + unsigned long inCount; + unsigned long originalCount; + +}; + +bool copyAndFillOperation(VoxelNode* node, void* extraData) { + copyAndFillArgs* args = (copyAndFillArgs*)extraData; + char outputMessage[128]; + + args->inCount++; + int percentDone = (100*args->inCount/args->originalCount); + + // For each leaf node... + if (node->isLeaf()) { + // create a copy of the leaf in the copy destination + float x = node->getCorner().x; + float y = node->getCorner().y; + float z = node->getCorner().z; + float s = node->getScale(); + unsigned char red = node->getTrueColor()[RED_INDEX]; + unsigned char green = node->getTrueColor()[GREEN_INDEX]; + unsigned char blue = node->getTrueColor()[BLUE_INDEX]; + bool destructive = true; + + args->destinationTree->createVoxel(x, y, z, s, red, green, blue, destructive); + args->outCount++; + + sprintf(outputMessage,"Completed: %d%% (%lu of %lu) - Creating voxel %lu at [%f,%f,%f,%f]", + percentDone,args->inCount,args->originalCount,args->outCount,x,y,z,s); + printf("%s",outputMessage); + for (int b = 0; b < strlen(outputMessage); b++) { + printf("\b"); + } + + // and create same sized leafs from this leaf voxel down to zero in the destination tree + for (float yFill = y-s; yFill >= 0.0f; yFill -= s) { + args->destinationTree->createVoxel(x, yFill, z, s, red, green, blue, destructive); + + args->outCount++; + + sprintf(outputMessage,"Completed: %d%% (%lu of %lu) - Creating fill voxel %lu at [%f,%f,%f,%f]", + percentDone,args->inCount,args->originalCount,args->outCount,x,y,z,s); + printf("%s",outputMessage); + for (int b = 0; b < strlen(outputMessage); b++) { + printf("\b"); + } + } + } + return true; +} + +void processFillSVOFile(const char* fillSVOFile) { + char outputFileName[512]; + + printf("fillSVOFile: %s\n", fillSVOFile); + + VoxelTree originalSVO(true); // reaveraging + VoxelTree filledSVO(true); // reaveraging + + originalSVO.readFromSVOFile(fillSVOFile); + qDebug("Nodes after loading %lu nodes\n", originalSVO.getVoxelCount()); + originalSVO.reaverageVoxelColors(originalSVO.rootNode); + qDebug("Original Voxels reAveraged\n"); + qDebug("Nodes after reaveraging %lu nodes\n", originalSVO.getVoxelCount()); + + copyAndFillArgs args; + args.destinationTree = &filledSVO; + args.inCount = 0; + args.outCount = 0; + args.originalCount = originalSVO.getVoxelCount(); + + printf("Begin processing...\n"); + originalSVO.recurseTreeWithOperation(copyAndFillOperation, &args); + printf("DONE processing...\n"); + + qDebug("Original input nodes used for filling %lu nodes\n", args.originalCount); + qDebug("Input nodes traversed during filling %lu nodes\n", args.inCount); + qDebug("Nodes created during filling %lu nodes\n", args.outCount); + qDebug("Nodes after filling %lu nodes\n", filledSVO.getVoxelCount()); + + filledSVO.reaverageVoxelColors(filledSVO.rootNode); + qDebug("Nodes after reaveraging %lu nodes\n", filledSVO.getVoxelCount()); + + sprintf(outputFileName, "filled%s", fillSVOFile); + printf("outputFile: %s\n", outputFileName); + filledSVO.writeToSVOFile(outputFileName); + + printf("exiting now\n"); +} + + int main(int argc, const char * argv[]) { qInstallMessageHandler(sharedMessageHandler); @@ -68,88 +246,19 @@ int main(int argc, const char * argv[]) const char* splitJurisdictionRoot = getCmdOption(argc, argv, SPLIT_JURISDICTION_ROOT); const char* splitJurisdictionEndNodes = getCmdOption(argc, argv, SPLIT_JURISDICTION_ENDNODES); if (splitSVOFile && splitJurisdictionRoot && splitJurisdictionEndNodes) { - char outputFileName[512]; - - printf("splitSVOFile: %s Jurisdictions Root: %s EndNodes: %s\n", - splitSVOFile, splitJurisdictionRoot, splitJurisdictionEndNodes); - - VoxelTree rootSVO; - - rootSVO.readFromSVOFile(splitSVOFile); - JurisdictionMap jurisdiction(splitJurisdictionRoot, splitJurisdictionEndNodes); - - printf("Jurisdiction Root Octcode: "); - printOctalCode(jurisdiction.getRootOctalCode()); - - printf("Jurisdiction End Nodes: %d \n", jurisdiction.getEndNodeCount()); - for (int i = 0; i < jurisdiction.getEndNodeCount(); i++) { - unsigned char* endNodeCode = jurisdiction.getEndNodeOctalCode(i); - printf("End Node: %d ", i); - printOctalCode(endNodeCode); - - // get the endNode details - VoxelPositionSize endNodeDetails; - voxelDetailsForCode(endNodeCode, endNodeDetails); - - // Now, create a split SVO for the EndNode. - // copy the EndNode into a temporary tree - VoxelTree endNodeTree; - - // create a small voxels at corners of the endNode Tree, this will is a hack - // to work around a bug in voxel server that will send Voxel not exists - // for regions that don't contain anything even if they're not in the - // jurisdiction of the server - // This hack assumes the end nodes for demo dinner since it only guarantees - // nodes in the 8 child voxels of the main root voxel - const float verySmall = 0.015625; - endNodeTree.createVoxel(0.0, 0.0, 0.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(1.0, 0.0, 0.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(0.0, 1.0, 0.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(0.0, 0.0, 1.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(1.0, 1.0, 1.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(1.0, 1.0, 0.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(0.0, 1.0, 1.0, verySmall, 1, 1, 1, true); - endNodeTree.createVoxel(1.0, 0.0, 1.0, verySmall, 1, 1, 1, true); - - // Delete the voxel for the EndNode from the temporary tree, so we can - // import our endNode content into it... - endNodeTree.deleteVoxelCodeFromTree(endNodeCode, COLLAPSE_EMPTY_TREE); - - VoxelNode* endNode = rootSVO.getVoxelAt(endNodeDetails.x, - endNodeDetails.y, - endNodeDetails.z, - endNodeDetails.s); - - rootSVO.copySubTreeIntoNewTree(endNode, &endNodeTree, false); - - sprintf(outputFileName, "splitENDNODE%d%s", i, splitSVOFile); - printf("outputFile: %s\n", outputFileName); - endNodeTree.writeToSVOFile(outputFileName); - - // Delete the voxel for the EndNode from the root tree... - rootSVO.deleteVoxelCodeFromTree(endNodeCode, COLLAPSE_EMPTY_TREE); - - // create a small voxel in center of each EndNode, this will is a hack - // to work around a bug in voxel server that will send Voxel not exists - // for regions that don't contain anything even if they're not in the - // jurisdiction of the server - float x = endNodeDetails.x + endNodeDetails.s * 0.5; - float y = endNodeDetails.y + endNodeDetails.s * 0.5; - float z = endNodeDetails.z + endNodeDetails.s * 0.5; - float s = endNodeDetails.s * verySmall; - - rootSVO.createVoxel(x, y, z, s, 1, 1, 1, true); - - } - - sprintf(outputFileName, "splitROOT%s", splitSVOFile); - printf("outputFile: %s\n", outputFileName); - rootSVO.writeToSVOFile(outputFileName); - - printf("exiting now\n"); + processSplitSVOFile(splitSVOFile, splitJurisdictionRoot, splitJurisdictionEndNodes); return 0; } + + // Handles taking an SVO and filling in the empty space below the voxels to make it solid. + const char* FILL_SVO = "--fillSVO"; + const char* fillSVOFile = getCmdOption(argc, argv, FILL_SVO); + if (fillSVOFile) { + processFillSVOFile(fillSVOFile); + return 0; + } + const char* DONT_CREATE_FILE = "--dontCreateSceneFile"; bool dontCreateFile = cmdOptionExists(argc, argv, DONT_CREATE_FILE);