diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a4a8d6c01..9af86e2891 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,4 +10,5 @@ add_subdirectory(interface) add_subdirectory(injector) add_subdirectory(pairing-server) add_subdirectory(space-server) -add_subdirectory(voxel-server) \ No newline at end of file +add_subdirectory(voxel-server) +add_subdirectory(voxel-edit) \ No newline at end of file diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index bfa59b965b..7a1fa48fa4 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -644,15 +644,14 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe return maxChildLevel; } -int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, const ViewFrustum& viewFrustum, - unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag) { +int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, + VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const { // How many bytes have we written so far at this level; int bytesWritten = 0; // If we're at a node that is out of view, then we can return, because no nodes below us will be in view! - if (!node->isInView(viewFrustum)) { + if (viewFrustum && !node->isInView(*viewFrustum)) { return bytesWritten; } @@ -666,7 +665,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, const Vi int currentEncodeLevel = 0; int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, - node, outputBuffer, availableBytes, bag, &viewFrustum); + node, outputBuffer, availableBytes, bag, viewFrustum); // if childBytesWritten == 1 then something went wrong... that's not possible assert(childBytesWritten != 1); @@ -865,21 +864,18 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco } void VoxelTree::readFromFileV2(const char* fileName, bool reset) { - std::ifstream file(fileName, std::ios::in|std::ios::binary); - + std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate); if(file.is_open()) { printLog("loading file...\n"); // get file length.... - unsigned long start = file.tellg(); - file.seekg( 0, std::ios::end ); - unsigned long end = file.tellg(); - unsigned long size = end - start; + unsigned long fileLength = file.tellg(); + file.seekg( 0, std::ios::beg ); // read the entire file into a buffer, WHAT!? Why not. - unsigned char* entireFile = new unsigned char[size]; - file.read((char*)entireFile, size); - readBitstreamToTree(entireFile,size); + unsigned char* entireFile = new unsigned char[fileLength]; + file.read((char*)entireFile, fileLength); + readBitstreamToTree(entireFile, fileLength); delete[] entireFile; file.close(); @@ -894,17 +890,14 @@ void VoxelTree::writeToFileV2(const char* fileName) const { VoxelNodeBag nodeBag; nodeBag.insert(rootNode); - static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static + static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static int bytesWritten = 0; - + while (!nodeBag.isEmpty()) { VoxelNode* subTree = nodeBag.extract(); - int currentEncodeLevel = 0; - bytesWritten = encodeTreeBitstreamRecursion(INT_MAX, currentEncodeLevel, subTree, - &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, - nodeBag, NULL); + bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL); - file.write((const char*)&tempOutputBuffer[0], bytesWritten); + file.write((const char*)&outputBuffer[0], bytesWritten); } } file.close(); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index db4f78b9b4..440345e119 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -53,9 +53,8 @@ public: void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); - int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, const ViewFrustum& viewFrustum, - unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag); + int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes, + VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const; int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag); @@ -63,10 +62,6 @@ public: void clearDirtyBit() { _isDirty = false; }; unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; }; - int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, - VoxelNode* node, unsigned char* outputBuffer, int availableBytes, - VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const; - // Note: this assumes the fileFormat is the HIO individual voxels code files void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); @@ -75,6 +70,10 @@ public: void readFromFileV2(const char* filename, bool reset); private: + int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, + VoxelNode* node, unsigned char* outputBuffer, int availableBytes, + VoxelNodeBag& bag, const ViewFrustum* viewFrustum) const; + int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag); diff --git a/voxel-edit/CMakeLists.txt b/voxel-edit/CMakeLists.txt new file mode 100644 index 0000000000..f7acb26e92 --- /dev/null +++ b/voxel-edit/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 2.8) + +set(TARGET_NAME voxel-edit) + +set(ROOT_DIR ..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") + +# set up the external glm library +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +include(${MACRO_DIR}/SetupHifiProject.cmake) + +setup_hifi_project(${TARGET_NAME}) + +# link in the shared library +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link in the hifi voxels library +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) + + diff --git a/voxel-edit/src/main.cpp b/voxel-edit/src/main.cpp new file mode 100644 index 0000000000..929b696650 --- /dev/null +++ b/voxel-edit/src/main.cpp @@ -0,0 +1,122 @@ +// +// main.cpp +// Voxel Edit +// +// Created by Brad Hefta-Gaub on 05/03/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include + +VoxelTree myTree; + +int _nodeCount=0; +bool countVoxelsOperation(VoxelNode* node, void* extraData) { + if (node->isColored()){ + _nodeCount++; + } + return true; // keep going +} + +void addScene(VoxelTree * tree) { + printf("adding scene...\n"); + + float voxelSize = 1.f/32; + + // 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 + VoxelNode* 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"); + } + + // Now some more examples... a little more complex + printf("creating corner points...\n"); + tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); + + + tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 ); + tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 ); + tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255); + tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255); + tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 ); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255); + printf("DONE creating corner points...\n"); + + // Now some more examples... creating some lines using the line primitive + printf("creating voxel lines...\n"); + float lineVoxelSize = 0.99f/256; + rgbColor red = {255,0,0}; + rgbColor green = {0,255,0}; + rgbColor blue = {0,0,255}; + tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), lineVoxelSize, blue); + tree->createLine(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), lineVoxelSize, red); + tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), lineVoxelSize, green); + printf("DONE creating lines...\n"); + + // Now some more examples... creating some spheres using the sphere primitive + int sphereBaseSize = 512; + printf("creating spheres...\n"); + tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, false); + printf("one sphere added...\n"); + tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + + + printf("two spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("three spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true); + printf("four spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("five spheres added...\n"); + tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true); + + float radius = 0.0125f; + printf("6 spheres added...\n"); + tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("7 spheres added...\n"); + tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("8 spheres added...\n"); + tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("9 spheres added...\n"); + tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("10 spheres added...\n"); + tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("11 spheres added...\n"); + printf("DONE creating spheres...\n"); + + // Here's an example of how to recurse the tree and do some operation on the nodes as you recurse them. + // This one is really simple, it just couts them... + // Look at the function countVoxelsOperation() for an example of how you could use this function + _nodeCount=0; + tree->recurseTreeWithOperation(countVoxelsOperation); + printf("Nodes after adding scene %d nodes\n", _nodeCount); + + printf("DONE adding scene of spheres...\n"); +} + + +int main(int argc, const char * argv[]) +{ + addScene(&myTree); + myTree.writeToFileV2("voxels.hio2"); + + return 0; +} \ No newline at end of file diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index d029edaeff..678ef9ef00 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -284,9 +284,9 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) { if (!agentData->nodeBag.isEmpty()) { VoxelNode* subTree = agentData->nodeBag.extract(); - bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree, viewFrustum, + bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, - agentData->nodeBag); + agentData->nodeBag, &viewFrustum); if (agentData->getAvailable() >= bytesWritten) { agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten); @@ -390,7 +390,11 @@ void attachVoxelAgentDataToAgent(Agent *newAgent) { void terminate (int sig) { printf("terminating now...\n"); - if (::wantVoxelPersist) { + if (false && ::wantVoxelPersist) { + _nodeCount=0; + ::randomTree.recurseTreeWithOperation(countVoxelsOperation); + printf("Nodes in scene before saving: %d nodes\n", _nodeCount); + printf("saving voxels to file...\n"); randomTree.writeToFileV2("voxels.hio2"); printf("DONE saving voxels to file...\n"); @@ -408,8 +412,11 @@ int main(int argc, const char * argv[]) // if we want Voxel Persistance, load the local file now... if (::wantVoxelPersist) { printf("loading voxels from file...\n"); - randomTree.readFromFileV2("voxels.hio2",true); + ::randomTree.readFromFileV2("voxels.hio2",true); printf("DONE loading voxels from file...\n"); + _nodeCount=0; + ::randomTree.recurseTreeWithOperation(countVoxelsOperation); + printf("Nodes after loading scene %d nodes\n", _nodeCount); } AgentList* agentList = AgentList::createInstance(AGENT_TYPE_VOXEL, VOXEL_LISTEN_PORT); @@ -418,7 +425,7 @@ int main(int argc, const char * argv[]) // Handle Local Domain testing with the --local command line const char* local = "--local"; bool wantLocalDomain = cmdOptionExists(argc, argv,local); - if (wantLocalDomain) { + if (true || wantLocalDomain) { printf("Local Domain MODE!\n"); int ip = getLocalAddress(); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));