From 00787a31d6e76b55505642b946ac2f45918cd433 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 28 Mar 2013 23:38:34 -0700 Subject: [PATCH] Added VoxelNode::collapseIdenticalLeaves() Fixed small bug in setColorFromAverageOfChildren() Changed sphere color randomization to be more dramatic --- shared/src/VoxelNode.cpp | 47 +++++++++++++++++++++++++++++++++++---- shared/src/VoxelNode.h | 1 + shared/src/VoxelTree.cpp | 48 ++++++++++++++++++++++++++-------------- voxel/src/main.cpp | 5 ++--- 4 files changed, 78 insertions(+), 23 deletions(-) diff --git a/shared/src/VoxelNode.cpp b/shared/src/VoxelNode.cpp index 94d82f387a..19a71dc7c4 100644 --- a/shared/src/VoxelNode.cpp +++ b/shared/src/VoxelNode.cpp @@ -36,17 +36,17 @@ void VoxelNode::addChildAtIndex(int childIndex) { children[childIndex]->octalCode = childOctalCode(octalCode, childIndex); } +// will average the child colors... void VoxelNode::setColorFromAverageOfChildren(int * colorArray) { if (colorArray == NULL) { colorArray = new int[4]; - memset(colorArray, 0, 4); + memset(colorArray, 0, 4*sizeof(int)); for (int i = 0; i < 8; i++) { if (children[i] != NULL && children[i]->color[3] == 1) { for (int j = 0; j < 3; j++) { colorArray[j] += children[i]->color[j]; } - colorArray[3]++; } } @@ -60,14 +60,53 @@ void VoxelNode::setColorFromAverageOfChildren(int * colorArray) { // set the average color value color[c] = colorArray[c] / colorArray[3]; } - // set the alpha to 1 to indicate that this isn't transparent color[3] = 1; } else { // some children, but not enough // set this node's alpha to 0 color[3] = 0; - } + } +} + +// will detect if children are leaves AND the same color +// and in that case will delete the children and make this node +// a leaf, returns TRUE if all the leaves are collapsed into a +// single node +bool VoxelNode::collapseIdenticalLeaves() { + // scan children, verify that they are ALL present and accounted for + bool allChildrenMatch = true; // assume the best (ottimista) + int red,green,blue; + for (int i = 0; i < 8; i++) { + // if no child, or child doesn't have a color + if (children[i] == NULL || children[i]->color[3] != 1) { + allChildrenMatch=false; + //printf("SADNESS child missing or not colored! i=%d\n",i); + break; + } else { + if (i==0) { + red = children[i]->color[0]; + green = children[i]->color[1]; + blue = children[i]->color[2]; + } else if (red != children[i]->color[0] || green != children[i]->color[1] || blue != children[i]->color[2]) { + allChildrenMatch=false; + break; + } + } + } + + + if (allChildrenMatch) { + for (int i = 0; i < 8; i++) { + delete children[i]; // delete all the child nodes + children[i]=NULL; // set it to NULL + } + color[0]=red; + color[1]=green; + color[2]=blue; + color[3]=1; // color is set + } + return allChildrenMatch; } void VoxelNode::setRandomColor(int minimumBrightness) { diff --git a/shared/src/VoxelNode.h b/shared/src/VoxelNode.h index 0074a7066e..9be1b64c70 100644 --- a/shared/src/VoxelNode.h +++ b/shared/src/VoxelNode.h @@ -19,6 +19,7 @@ public: void addChildAtIndex(int childIndex); void setColorFromAverageOfChildren(int * colorArray = NULL); void setRandomColor(int minimumBrightness); + bool collapseIdenticalLeaves(); unsigned char *octalCode; unsigned char color[4]; diff --git a/shared/src/VoxelTree.cpp b/shared/src/VoxelTree.cpp index b811f77b72..a2ab7012d7 100644 --- a/shared/src/VoxelTree.cpp +++ b/shared/src/VoxelTree.cpp @@ -395,7 +395,10 @@ void VoxelTree::reaverageVoxelColors(VoxelNode *startNode) { } if (hasChildren) { - startNode->setColorFromAverageOfChildren(); + bool childrenCollapsed = startNode->collapseIdenticalLeaves(); + if (!childrenCollapsed) { + startNode->setColorFromAverageOfChildren(); + } } } @@ -466,21 +469,27 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { // About the color of the sphere... we're going to make this sphere be a gradient // between two RGB colors. We will do the gradient along the phi spectrum - unsigned char r1 = randomColorValue(165); - unsigned char g1 = randomColorValue(165); - unsigned char b1 = randomColorValue(165); - unsigned char r2 = randomColorValue(65); - unsigned char g2 = randomColorValue(65); - unsigned char b2 = randomColorValue(65); + unsigned char dominantColor1 = randIntInRange(1,3); //1=r, 2=g, 3=b dominant + unsigned char dominantColor2 = randIntInRange(1,3); - // we don't want them to match!! - if (r1==r2 && g1==g2 && b1==b2) { - r2=r1/2; - g2=g1/2; - b2=b1/2; + if (dominantColor1==dominantColor2) { + dominantColor2 = dominantColor1+1%3; } + + unsigned char r1 = (dominantColor1==1)?randIntInRange(200,255):randIntInRange(40,100); + unsigned char g1 = (dominantColor1==2)?randIntInRange(200,255):randIntInRange(40,100); + unsigned char b1 = (dominantColor1==3)?randIntInRange(200,255):randIntInRange(40,100); + unsigned char r2 = (dominantColor2==1)?randIntInRange(200,255):randIntInRange(40,100); + unsigned char g2 = (dominantColor2==2)?randIntInRange(200,255):randIntInRange(40,100); + unsigned char b2 = (dominantColor2==3)?randIntInRange(200,255):randIntInRange(40,100); - // Psuedocode for creating a sphere: + // We initialize our rgb to be either "grey" in case of randomized surface, or + // the average of the gradient, in the case of the gradient sphere. + unsigned char red = wantColorRandomizer ? 128 : (r1+r2)/2; // average of the colors + unsigned char green = wantColorRandomizer ? 128 : (g1+g2)/2; + unsigned char blue = wantColorRandomizer ? 128 : (b1+b2)/2; + + // Psuedocode for creating a sphere: // // for (theta from 0 to 2pi): // for (phi from 0 to pi): @@ -498,9 +507,11 @@ void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool // assume solid for now float ri = 0.0; + if (!solid) { ri=r; // just the outer surface } + // If you also iterate form the interior of the sphere to the radius, makeing // larger and larger sphere's you'd end up with a solid sphere. And lots of voxels! for (; ri <= r; ri+=s) { @@ -514,9 +525,14 @@ void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool // gradient color data float gradient = (phi/M_PI); - unsigned char red = wantColorRandomizer ? randomColorValue(165) : r1+((r2-r1)*gradient); - unsigned char green = wantColorRandomizer ? randomColorValue(165) : g1+((g2-g1)*gradient); - unsigned char blue = wantColorRandomizer ? randomColorValue(165) : b1+((b2-b1)*gradient); + + // only use our actual desired color on the outer edge, otherwise + // use our "average" color + if (ri==r) { + red = wantColorRandomizer ? randomColorValue(165) : r1+((r2-r1)*gradient); + green = wantColorRandomizer ? randomColorValue(165) : g1+((g2-g1)*gradient); + blue = wantColorRandomizer ? randomColorValue(165) : b1+((b2-b1)*gradient); + } unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); this->readCodeColorBufferToTree(voxelData); diff --git a/voxel/src/main.cpp b/voxel/src/main.cpp index 879248ddb5..121d82a394 100644 --- a/voxel/src/main.cpp +++ b/voxel/src/main.cpp @@ -219,6 +219,8 @@ int main(int argc, const char * argv[]) const char* NO_COLOR_RANDOMIZER="--NoColorRandomizer"; const char* INPUT_FILE="-i"; bool wantColorRandomizer = !cmdOptionExists(argc, argv, NO_COLOR_RANDOMIZER); + + printf("wantColorRandomizer=%s\n",(wantColorRandomizer?"yes":"no")); const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); if (voxelsFilename) { @@ -235,13 +237,10 @@ int main(int argc, const char * argv[]) const char* ADD_SPHERE="--AddSphere"; const char* ADD_RANDOM_SPHERE="--AddRandomSphere"; if (cmdOptionExists(argc, argv, ADD_SPHERE)) { -printf("adding sphere\n"); addSphere(&randomTree,false,wantColorRandomizer); } else if (cmdOptionExists(argc, argv, ADD_RANDOM_SPHERE)) { -printf("adding random sphere\n"); addSphere(&randomTree,true,wantColorRandomizer); } -printf("past adding spheres...\n"); pthread_t sendVoxelThread; pthread_create(&sendVoxelThread, NULL, distributeVoxelsToListeners, NULL);