void VoxelsScriptingInterface::eraseVoxel(float x, float y, float z, float scale) { // setup a VoxelDetail struct with data VoxelDetail deleteVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, scale / (float)TREE_SCALE}; // handle the local tree also... if (_tree) { VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s); if (deleteVoxelElement) { deleteVoxelDetail.red = deleteVoxelElement->getColor()[0]; deleteVoxelDetail.green = deleteVoxelElement->getColor()[1]; deleteVoxelDetail.blue = deleteVoxelElement->getColor()[2]; } if (_undoStack) { DeleteVoxelCommand* command = new DeleteVoxelCommand(_tree, deleteVoxelDetail, getVoxelPacketSender()); // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. _undoStack->push(command); } else { getVoxelPacketSender()->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &deleteVoxelDetail); _tree->deleteVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s); } } }
void voxelTutorial(VoxelTree * tree) { printf("adding scene...\n"); // We want our corner voxels to be about 1/2 meter high, and our TREE_SCALE is in meters, so... float voxelSize = 0.5f / TREE_SCALE; // Here's an example of how to create a voxel. printf("creating corner points...\n"); tree->createVoxel(0, 0, 0, voxelSize, 255, 255 ,255); // Here's an example of how to test if a voxel exists VoxelTreeElement* node = tree->getVoxelAt(0, 0, 0, voxelSize); if (node) { // and how to access it's color printf("corner point 0,0,0 exists... color is (%d,%d,%d) \n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); } // here's an example of how to delete a voxel printf("attempting to delete corner point 0,0,0\n"); tree->deleteVoxelAt(0, 0, 0, voxelSize); // Test to see that the delete worked... it should be FALSE... if (tree->getVoxelAt(0, 0, 0, voxelSize)) { printf("corner point 0,0,0 exists...\n"); } else { printf("corner point 0,0,0 does not exists...\n"); } }
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 }
VoxelDetail VoxelsScriptingInterface::getVoxelEnclosingPoint(const glm::vec3& point) { VoxelDetail result = { 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 0 }; if (_tree) { OctreeElement* element = _tree->getElementEnclosingPoint(point / (float)TREE_SCALE); if (element) { VoxelTreeElement* voxel = static_cast<VoxelTreeElement*>(element); result.x = voxel->getCorner().x; result.y = voxel->getCorner().y; result.z = voxel->getCorner().z; result.s = voxel->getScale(); result.red = voxel->getColor()[0]; result.green = voxel->getColor()[1]; result.blue = voxel->getColor()[2]; } } return result; }
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersection(const PickRay& ray) { RayToVoxelIntersectionResult result; if (_tree) { OctreeElement* element; result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face); if (result.intersects) { VoxelTreeElement* voxel = (VoxelTreeElement*)element; result.voxel.x = voxel->getCorner().x; result.voxel.y = voxel->getCorner().y; result.voxel.z = voxel->getCorner().z; result.voxel.s = voxel->getScale(); result.voxel.red = voxel->getColor()[0]; result.voxel.green = voxel->getColor()[1]; result.voxel.blue = voxel->getColor()[2]; result.intersection = ray.origin + (ray.direction * result.distance); } } return result; }
// 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; }
DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) : QUndoCommand("Delete Voxel", parent), _tree(tree), _packetSender(packetSender), _voxel(voxel), _oldTree(NULL) { _tree->lockForRead(); VoxelTreeElement* element = _tree->getEnclosingVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); if (element->getScale() == _voxel.s) { if (!element->hasContent() && !element->isLeaf()) { _oldTree = new VoxelTree(); _tree->copySubTreeIntoNewTree(element, _oldTree, false); } else { _voxel.red = element->getColor()[0]; _voxel.green = element->getColor()[1]; _voxel.blue = element->getColor()[2]; } } else if (element->hasContent() && element->isLeaf()) { _voxel.red = element->getColor()[0]; _voxel.green = element->getColor()[1]; _voxel.blue = element->getColor()[2]; } else { _voxel.s = 0.0f; } _tree->unlock(); }
VoxelDetail VoxelsScriptingInterface::getVoxelAt(float x, float y, float z, float scale) { // setup a VoxelDetail struct with the data VoxelDetail result = {0,0,0,0,0,0,0}; if (_tree) { _tree->lockForRead(); VoxelTreeElement* voxel = static_cast<VoxelTreeElement*>(_tree->getOctreeElementAt(x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, scale / (float)TREE_SCALE)); _tree->unlock(); if (voxel) { // Note: these need to be in voxel space because the VoxelDetail -> js converter will upscale result.x = voxel->getCorner().x; result.y = voxel->getCorner().y; result.z = voxel->getCorner().z; result.s = voxel->getScale(); result.red = voxel->getColor()[RED_INDEX]; result.green = voxel->getColor()[GREEN_INDEX]; result.blue = voxel->getColor()[BLUE_INDEX]; } } return result; }
void VoxelsScriptingInterface::setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { // setup a VoxelDetail struct with the data VoxelDetail addVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE, scale / (float)TREE_SCALE, red, green, blue }; // handle the local tree also... if (_tree) { if (_undoStack) { AddVoxelCommand* addCommand = new AddVoxelCommand(_tree, addVoxelDetail, getVoxelPacketSender()); VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s); if (deleteVoxelElement) { nodeColor color; memcpy(&color, &deleteVoxelElement->getColor(), sizeof(nodeColor)); VoxelDetail deleteVoxelDetail = {addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, color[0], color[1], color[2] }; DeleteVoxelCommand* delCommand = new DeleteVoxelCommand(_tree, deleteVoxelDetail, getVoxelPacketSender()); _undoStack->beginMacro(addCommand->text()); // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. _undoStack->push(delCommand); _undoStack->push(addCommand); _undoStack->endMacro(); } else { // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. _undoStack->push(addCommand); } } else { // queue the destructive add queueVoxelAdd(PacketTypeVoxelSetDestructive, addVoxelDetail); _tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, true); } } }
void unitTest(VoxelTree * tree) { VoxelTreeElement* node = NULL; printf("unit tests...\n"); unsigned long nodeCount; // We want our corner voxels to be about 1/2 meter high, and our TREE_SCALE is in meters, so... float voxelSize = 0.5f / TREE_SCALE; // Here's an example of how to create a voxel. printf("creating corner points...\n"); tree->createVoxel(0, 0, 0, voxelSize, 255, 255 ,255); printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); // Here's an example of how to test if a voxel exists node = tree->getVoxelAt(0, 0, 0, voxelSize); if (node) { // and how to access it's color printf("CORRECT - corner point 0,0,0 exists... color is (%d,%d,%d) \n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); } printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); // here's an example of how to delete a voxel printf("attempting to delete corner point 0,0,0\n"); tree->deleteVoxelAt(0, 0, 0, voxelSize); printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); // Test to see that the delete worked... it should be FALSE... if ((node = tree->getVoxelAt(0, 0, 0, voxelSize))) { printf("FAIL corner point 0,0,0 exists...\n"); } else { printf("CORRECT corner point 0,0,0 does not exists...\n"); } printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); tree->createVoxel(0, 0, 0, voxelSize, 255, 255 ,255); if ((node = tree->getVoxelAt(0, 0, 0, voxelSize))) { printf("CORRECT - corner point 0,0,0 exists... color is (%d,%d,%d) \n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); } else { printf("FAIL corner point 0,0,0 does not exists...\n"); } printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); tree->createVoxel(voxelSize, 0, 0, voxelSize, 255, 255 ,0); if ((node = tree->getVoxelAt(voxelSize, 0, 0, voxelSize))) { printf("CORRECT - corner point voxelSize,0,0 exists... color is (%d,%d,%d) \n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); } else { printf("FAIL corner point voxelSize,0,0 does not exists...\n"); } printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); tree->createVoxel(0, 0, voxelSize, voxelSize, 255, 0 ,0); if ((node = tree->getVoxelAt(0, 0, voxelSize, voxelSize))) { printf("CORRECT - corner point 0, 0, voxelSize exists... color is (%d,%d,%d) \n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); } else { printf("FAILED corner point 0, 0, voxelSize does not exists...\n"); } printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); tree->createVoxel(voxelSize, 0, voxelSize, voxelSize, 0, 0 ,255); if ((node = tree->getVoxelAt(voxelSize, 0, voxelSize, voxelSize))) { printf("CORRECT - corner point voxelSize, 0, voxelSize exists... color is (%d,%d,%d) \n", node->getColor()[0], node->getColor()[1], node->getColor()[2]); } else { printf("corner point voxelSize, 0, voxelSize does not exists...\n"); } printf("Nodes at line %d... %ld nodes\n", __LINE__, tree->getOctreeElementsCount()); printf("check root voxel exists...\n"); if (tree->getVoxelAt(0,0,0,1.0)) { printf("of course it does\n"); } else { printf("WTH!?!\n"); } nodeCount = tree->getOctreeElementsCount(); printf("Nodes before writing file: %ld nodes\n", nodeCount); tree->writeToSVOFile("voxels.svo"); printf("erasing the tree...\n"); tree->eraseAllOctreeElements(); printf("check root voxel exists...\n"); if (tree->getVoxelAt(0,0,0,1.0)) { printf("of course it does\n"); } else { printf("WTH!?!\n"); } // this should not exist... we just deleted it... if (tree->getVoxelAt(voxelSize, 0, voxelSize, voxelSize)) { printf("corner point voxelSize, 0, voxelSize exists...\n"); } else { printf("corner point voxelSize, 0, voxelSize does not exists...\n"); } tree->readFromSVOFile("voxels.svo"); // this should exist... we just loaded it... if (tree->getVoxelAt(voxelSize, 0, voxelSize, voxelSize)) { printf("corner point voxelSize, 0, voxelSize exists...\n"); } else { printf("corner point voxelSize, 0, voxelSize does not exists...\n"); } nodeCount = tree->getOctreeElementsCount(); printf("Nodes after loading file: %ld nodes\n", nodeCount); }