bool sendVoxelsOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = static_cast<VoxelTreeElement*>(element); SendVoxelsOperationArgs* args = static_cast<SendVoxelsOperationArgs*>(extraData); if (voxel->isColored()) { const unsigned char* nodeOctalCode = voxel->getOctalCode(); unsigned char* codeColorBuffer = NULL; int codeLength = 0; int bytesInCode = 0; int codeAndColorLength; // If the newBase is NULL, then don't rebase if (args->newBaseOctCode) { codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); bytesInCode = bytesRequiredForCodeLength(codeLength); codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; } else { codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode); bytesInCode = bytesRequiredForCodeLength(codeLength); codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; codeColorBuffer = new unsigned char[codeAndColorLength]; memcpy(codeColorBuffer, nodeOctalCode, bytesInCode); } // copy the colors over codeColorBuffer[bytesInCode + RED_INDEX] = voxel->getColor()[RED_INDEX]; codeColorBuffer[bytesInCode + GREEN_INDEX] = voxel->getColor()[GREEN_INDEX]; codeColorBuffer[bytesInCode + BLUE_INDEX] = voxel->getColor()[BLUE_INDEX]; args->packetSender->queueVoxelEditMessage(PacketTypeVoxelSetDestructive, codeColorBuffer, codeAndColorLength); delete[] codeColorBuffer; } return true; // keep going }
// 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 VoxelTreeElement::collapseChildren() { // 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 < NUMBER_OF_CHILDREN; i++) { VoxelTreeElement* childAt = getChildAtIndex(i); // if no child, child isn't a leaf, or child doesn't have a color if (!childAt || !childAt->isLeaf() || !childAt->isColored()) { allChildrenMatch=false; //qDebug("SADNESS child missing or not colored! i=%d\n",i); break; } else { if (i==0) { red = childAt->getColor()[0]; green = childAt->getColor()[1]; blue = childAt->getColor()[2]; } else if (red != childAt->getColor()[0] || green != childAt->getColor()[1] || blue != childAt->getColor()[2]) { allChildrenMatch=false; break; } } } if (allChildrenMatch) { //qDebug("allChildrenMatch: pruning tree\n"); for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { OctreeElement* childAt = getChildAtIndex(i); delete childAt; // delete all the child nodes setChildAtIndex(i, NULL); // set it to NULL } nodeColor collapsedColor; collapsedColor[0]=red; collapsedColor[1]=green; collapsedColor[2]=blue; collapsedColor[3]=1; // color is set setColor(collapsedColor); } return allChildrenMatch; }
// will average the child colors... void VoxelTreeElement::calculateAverageFromChildren() { int colorArray[4] = {0,0,0,0}; float density = 0.0f; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { VoxelTreeElement* childAt = getChildAtIndex(i); if (childAt && childAt->isColored()) { for (int j = 0; j < 3; j++) { colorArray[j] += childAt->getTrueColor()[j]; // color averaging should always be based on true colors } colorArray[3]++; } if (childAt) { density += childAt->getDensity(); } } density /= (float) NUMBER_OF_CHILDREN; // // The VISIBLE_ABOVE_DENSITY sets the density of matter above which an averaged color voxel will // be set. It is an important physical constant in our universe. A number below 0.5 will cause // things to get 'fatter' at a distance, because upward averaging will make larger voxels out of // less data, which is (probably) going to be preferable because it gives a sense that there is // something out there to go investigate. A number above 0.5 would cause the world to become // more 'empty' at a distance. Exactly 0.5 would match the physical world, at least for materials // that are not shiny and have equivalent ambient reflectance. // const float VISIBLE_ABOVE_DENSITY = 0.10f; nodeColor newColor = { 0, 0, 0, 0}; if (density > VISIBLE_ABOVE_DENSITY) { // The density of material in the space of the voxel sets whether it is actually colored for (int c = 0; c < 3; c++) { // set the average color value newColor[c] = colorArray[c] / colorArray[3]; } // set the alpha to 1 to indicate that this isn't transparent newColor[3] = 1; } // Set the color from the average of the child colors, and update the density setColor(newColor); setDensity(density); }