mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 04:07:11 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
Conflicts: libraries/voxels/src/VoxelTree.h
This commit is contained in:
commit
4d33c462fe
9 changed files with 377 additions and 106 deletions
|
@ -10,4 +10,5 @@ add_subdirectory(interface)
|
|||
add_subdirectory(injector)
|
||||
add_subdirectory(pairing-server)
|
||||
add_subdirectory(space-server)
|
||||
add_subdirectory(voxel-server)
|
||||
add_subdirectory(voxel-server)
|
||||
add_subdirectory(voxel-edit)
|
|
@ -1556,6 +1556,15 @@ void Avatar::readAvatarDataFromFile() {
|
|||
FILE* avatarFile = fopen(AVATAR_DATA_FILENAME, "r");
|
||||
|
||||
if (avatarFile) {
|
||||
fscanf(avatarFile, "%f,%f,%f %f", &_position.x, &_position.y, &_position.z, &_bodyYaw);
|
||||
glm::vec3 readPosition;
|
||||
float readYaw;
|
||||
fscanf(avatarFile, "%f,%f,%f %f", &readPosition.x, &readPosition.y, &readPosition.z, &readYaw);
|
||||
|
||||
// make sure these values are sane
|
||||
if (!isnan(readPosition.x) && !isnan(readPosition.y) && !isnan(readPosition.z) && !isnan(readYaw)) {
|
||||
_position = readPosition;
|
||||
_bodyYaw = readYaw;
|
||||
}
|
||||
fclose(avatarFile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//---------------------------------------------------------------------
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <VoxelConstants.h>
|
||||
// #include "Log.h"
|
||||
|
||||
#include "Camera.h"
|
||||
|
@ -16,7 +17,7 @@ Camera::Camera() {
|
|||
_tightness = 10.0; // default
|
||||
_fieldOfView = 60.0; // default
|
||||
_nearClip = 0.08; // default
|
||||
_farClip = 50.0; // default
|
||||
_farClip = 50.0 * TREE_SCALE; // default
|
||||
_modeShift = 0.0;
|
||||
_yaw = 0.0;
|
||||
_pitch = 0.0;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef __hifi_VoxelConstants_h__
|
||||
#define __hifi_VoxelConstants_h__
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
const int MAX_VOXEL_PACKET_SIZE = 1492;
|
||||
const int MAX_TREE_SLICE_BYTES = 26;
|
||||
const int TREE_SCALE = 10;
|
||||
|
|
|
@ -69,7 +69,7 @@ void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperati
|
|||
}
|
||||
}
|
||||
|
||||
VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode) {
|
||||
VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode) const {
|
||||
// find the appropriate branch index based on this ancestorNode
|
||||
if (*needleCode > 0) {
|
||||
int branchForNeedle = branchIndexWithDescendant(ancestorNode->octalCode, needleCode);
|
||||
|
@ -157,16 +157,6 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
|||
bytesRead += 3;
|
||||
}
|
||||
}
|
||||
// average node's color based on color of children
|
||||
bool nodeWasDirty = destinationNode->isDirty();
|
||||
destinationNode->setColorFromAverageOfChildren();
|
||||
bool nodeIsDirty = destinationNode->isDirty();
|
||||
if (nodeIsDirty) {
|
||||
_isDirty = true;
|
||||
}
|
||||
if (!nodeWasDirty && nodeIsDirty) {
|
||||
_nodesChangedFromBitstream++;
|
||||
}
|
||||
|
||||
// give this destination node the child mask from the packet
|
||||
unsigned char childMask = *(nodeData + bytesRead);
|
||||
|
@ -205,7 +195,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
|||
return bytesRead;
|
||||
}
|
||||
|
||||
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes) {
|
||||
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes) {
|
||||
int bytesRead = 0;
|
||||
unsigned char* bitstreamAt = bitstream;
|
||||
|
||||
|
@ -245,6 +235,13 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt
|
|||
this->voxelsBytesReadStats.updateAverage(bufferSizeBytes);
|
||||
}
|
||||
|
||||
void VoxelTree::deleteVoxelAt(float x, float y, float z, float s) {
|
||||
unsigned char* octalCode = pointToVoxel(x,y,z,s,0,0,0);
|
||||
deleteVoxelCodeFromTree(octalCode);
|
||||
delete octalCode; // cleanup memory
|
||||
}
|
||||
|
||||
|
||||
// Note: uses the codeColorBuffer format, but the color's are ignored, because
|
||||
// this only finds and deletes the node from the tree.
|
||||
void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer) {
|
||||
|
@ -255,20 +252,14 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char *codeBuffer) {
|
|||
int lengthInBytes = bytesRequiredForCodeLength(*codeBuffer); // includes octet count, not color!
|
||||
|
||||
if (0 == memcmp(nodeToDelete->octalCode,codeBuffer,lengthInBytes)) {
|
||||
|
||||
float* vertices = firstVertexForCode(nodeToDelete->octalCode);
|
||||
delete[] vertices;
|
||||
|
||||
if (parentNode) {
|
||||
float* vertices = firstVertexForCode(parentNode->octalCode);
|
||||
delete[] vertices;
|
||||
|
||||
int childIndex = branchIndexWithDescendant(parentNode->octalCode, codeBuffer);
|
||||
|
||||
delete parentNode->children[childIndex]; // delete the child nodes
|
||||
parentNode->children[childIndex] = NULL; // set it to NULL
|
||||
|
||||
reaverageVoxelColors(rootNode); // Fix our colors!! Need to call it on rootNode
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +270,7 @@ void VoxelTree::eraseAllVoxels() {
|
|||
rootNode = new VoxelNode();
|
||||
rootNode->octalCode = new unsigned char[1];
|
||||
*rootNode->octalCode = 0;
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
||||
|
@ -287,6 +279,7 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
|||
// create the node if it does not exist
|
||||
if (*lastCreatedNode->octalCode != *codeColorBuffer) {
|
||||
lastCreatedNode = createMissingNode(lastCreatedNode, codeColorBuffer);
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
// give this node its color
|
||||
|
@ -296,6 +289,9 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
|||
memcpy(newColor, codeColorBuffer + octalCodeBytes, 3);
|
||||
newColor[3] = 1;
|
||||
lastCreatedNode->setColor(newColor);
|
||||
if (lastCreatedNode->isDirty()) {
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) {
|
||||
|
@ -438,6 +434,16 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
|||
}
|
||||
}
|
||||
|
||||
VoxelNode* VoxelTree::getVoxelAt(float x, float y, float z, float s) const {
|
||||
unsigned char* octalCode = pointToVoxel(x,y,z,s,0,0,0);
|
||||
VoxelNode* node = nodeForOctalCode(rootNode, octalCode, NULL);
|
||||
if (*node->octalCode != *octalCode) {
|
||||
node = NULL;
|
||||
}
|
||||
delete octalCode; // cleanup memory
|
||||
return node;
|
||||
}
|
||||
|
||||
void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue) {
|
||||
unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue);
|
||||
this->readCodeColorBufferToTree(voxelData);
|
||||
|
@ -664,15 +670,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;
|
||||
}
|
||||
|
||||
|
@ -686,8 +691,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, const Vi
|
|||
|
||||
int currentEncodeLevel = 0;
|
||||
int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel,
|
||||
node, viewFrustum,
|
||||
outputBuffer, availableBytes, bag);
|
||||
node, outputBuffer, availableBytes, bag, viewFrustum);
|
||||
|
||||
// if childBytesWritten == 1 then something went wrong... that's not possible
|
||||
assert(childBytesWritten != 1);
|
||||
|
@ -709,9 +713,8 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, const Vi
|
|||
}
|
||||
|
||||
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||
VoxelNode* node, const ViewFrustum& viewFrustum,
|
||||
unsigned char* outputBuffer, int availableBytes,
|
||||
VoxelNodeBag& bag) const {
|
||||
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 bytesAtThisLevel = 0;
|
||||
|
||||
|
@ -723,21 +726,24 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
|||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
float distance = node->distanceToCamera(viewFrustum);
|
||||
float boundaryDistance = boundaryDistanceForRenderLevel(*node->octalCode + 1);
|
||||
// caller can pass NULL as viewFrustum if they want everything
|
||||
if (viewFrustum) {
|
||||
float distance = node->distanceToCamera(*viewFrustum);
|
||||
float boundaryDistance = boundaryDistanceForRenderLevel(*node->octalCode + 1);
|
||||
|
||||
// If we're too far away for our render level, then just return
|
||||
if (distance >= boundaryDistance) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
// If we're too far away for our render level, then just return
|
||||
if (distance >= boundaryDistance) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
|
||||
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
|
||||
// we're out of view
|
||||
if (!node->isInView(viewFrustum)) {
|
||||
return bytesAtThisLevel;
|
||||
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
|
||||
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
|
||||
// we're out of view
|
||||
if (!node->isInView(*viewFrustum)) {
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool keepDiggingDeeper = true; // Assuming we're in view we have a great work ethic, we're always ready for more!
|
||||
|
||||
// At any given point in writing the bitstream, the largest minimum we might need to flesh out the current level
|
||||
|
@ -765,11 +771,11 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
|||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
VoxelNode* childNode = node->children[i];
|
||||
bool childExists = (childNode != NULL);
|
||||
bool childIsInView = (childExists && childNode->isInView(viewFrustum));
|
||||
bool childIsInView = (childExists && (!viewFrustum || childNode->isInView(*viewFrustum)));
|
||||
if (childIsInView) {
|
||||
// Before we determine consider this further, let's see if it's in our LOD scope...
|
||||
float distance = childNode->distanceToCamera(viewFrustum);
|
||||
float boundaryDistance = boundaryDistanceForRenderLevel(*childNode->octalCode + 1);
|
||||
float distance = viewFrustum ? childNode->distanceToCamera(*viewFrustum) : 0;
|
||||
float boundaryDistance = viewFrustum ? boundaryDistanceForRenderLevel(*childNode->octalCode + 1) : 1;
|
||||
|
||||
if (distance < boundaryDistance) {
|
||||
inViewCount++;
|
||||
|
@ -842,7 +848,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
|||
|
||||
int thisLevel = currentEncodeLevel;
|
||||
int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode,
|
||||
viewFrustum, outputBuffer, availableBytes, bag);
|
||||
outputBuffer, availableBytes, bag, viewFrustum);
|
||||
|
||||
// if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space,
|
||||
// basically, the children below don't contain any info.
|
||||
|
@ -882,3 +888,46 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
|||
} // end keepDiggingDeeper
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
bool VoxelTree::readFromFileV2(const char* fileName) {
|
||||
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 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[fileLength];
|
||||
file.read((char*)entireFile, fileLength);
|
||||
readBitstreamToTree(entireFile, fileLength);
|
||||
delete[] entireFile;
|
||||
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VoxelTree::writeToFileV2(const char* fileName) const {
|
||||
|
||||
std::ofstream file(fileName, std::ios::out|std::ios::binary);
|
||||
|
||||
if(file.is_open()) {
|
||||
VoxelNodeBag nodeBag;
|
||||
nodeBag.insert(rootNode);
|
||||
|
||||
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();
|
||||
bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, NULL);
|
||||
|
||||
file.write((const char*)&outputBuffer[0], bytesWritten);
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,22 +39,22 @@ public:
|
|||
void eraseAllVoxels();
|
||||
|
||||
void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes);
|
||||
void readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes);
|
||||
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes);
|
||||
void readCodeColorBufferToTree(unsigned char *codeColorBuffer);
|
||||
void deleteVoxelCodeFromTree(unsigned char *codeBuffer);
|
||||
void printTreeForDebugging(VoxelNode *startNode);
|
||||
void reaverageVoxelColors(VoxelNode *startNode);
|
||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||
void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
||||
void deleteVoxelAt(float x, float y, float z, float s);
|
||||
VoxelNode* getVoxelAt(float x, float y, float z, float s) const;
|
||||
void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue);
|
||||
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||
|
||||
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,18 +63,24 @@ public:
|
|||
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelNode*& node, float& distance);
|
||||
|
||||
// Note: this assumes the fileFormat is the HIO individual voxels code files
|
||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||
|
||||
// these will read/write files that match the wireformat, excluding the 'V' leading
|
||||
void writeToFileV2(const char* filename) const;
|
||||
bool readFromFileV2(const char* filename);
|
||||
|
||||
private:
|
||||
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||
VoxelNode* node, const ViewFrustum& viewFrustum,
|
||||
unsigned char* outputBuffer, int availableBytes,
|
||||
VoxelNodeBag& bag) const;
|
||||
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);
|
||||
|
||||
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
|
||||
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode);
|
||||
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode) const;
|
||||
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
||||
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes);
|
||||
|
||||
|
|
26
voxel-edit/CMakeLists.txt
Normal file
26
voxel-edit/CMakeLists.txt
Normal file
|
@ -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})
|
||||
|
||||
|
135
voxel-edit/src/main.cpp
Normal file
135
voxel-edit/src/main.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
//
|
||||
// main.cpp
|
||||
// Voxel Edit
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 05/03/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <VoxelTree.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
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[])
|
||||
{
|
||||
const char* SAY_HELLO = "--sayHello";
|
||||
if (cmdOptionExists(argc, argv, SAY_HELLO)) {
|
||||
printf("I'm just saying hello...\n");
|
||||
}
|
||||
|
||||
const char* DONT_CREATE_FILE = "--dontCreateSceneFile";
|
||||
bool dontCreateFile = cmdOptionExists(argc, argv, DONT_CREATE_FILE);
|
||||
|
||||
if (dontCreateFile) {
|
||||
printf("You asked us not to create a scene file, so we will not.\n");
|
||||
} else {
|
||||
printf("Creating Scene File...\n");
|
||||
addScene(&myTree);
|
||||
myTree.writeToFileV2("voxels.hio2");
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -43,6 +43,7 @@ int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
|||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||
|
||||
VoxelTree randomTree;
|
||||
bool wantVoxelPersist = true;
|
||||
|
||||
bool wantColorRandomizer = false;
|
||||
bool debugVoxelSending = false;
|
||||
|
@ -83,8 +84,6 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
|
|||
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 );
|
||||
|
@ -245,9 +244,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);
|
||||
|
@ -299,6 +298,16 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
|||
}
|
||||
}
|
||||
|
||||
void persistVoxelsWhenDirty() {
|
||||
// check the dirty bit and persist here...
|
||||
if (::wantVoxelPersist && ::randomTree.isDirty()) {
|
||||
printf("saving voxels to file...\n");
|
||||
randomTree.writeToFileV2("voxels.hio2");
|
||||
randomTree.clearDirtyBit(); // tree is clean after saving
|
||||
printf("DONE saving voxels to file...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void *distributeVoxelsToListeners(void *args) {
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
|
@ -349,7 +358,6 @@ void attachVoxelAgentDataToAgent(Agent *newAgent) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_VOXEL, VOXEL_LISTEN_PORT);
|
||||
|
@ -359,9 +367,9 @@ int main(int argc, const char * argv[])
|
|||
const char* local = "--local";
|
||||
bool wantLocalDomain = cmdOptionExists(argc, argv,local);
|
||||
if (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));
|
||||
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));
|
||||
}
|
||||
|
||||
agentList->linkedDataCreateCallback = &attachVoxelAgentDataToAgent;
|
||||
|
@ -370,56 +378,87 @@ int main(int argc, const char * argv[])
|
|||
|
||||
srand((unsigned)time(0));
|
||||
|
||||
const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending";
|
||||
const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending";
|
||||
::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING);
|
||||
printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no"));
|
||||
|
||||
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
||||
printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no"));
|
||||
|
||||
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
||||
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
||||
printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no"));
|
||||
printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no"));
|
||||
|
||||
// Check to see if the user passed in a command line option for loading a local
|
||||
// Voxel File. If so, load it now.
|
||||
const char* INPUT_FILE = "-i";
|
||||
const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE);
|
||||
if (voxelsFilename) {
|
||||
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||
}
|
||||
// By default we will voxel persist, if you want to disable this, then pass in this parameter
|
||||
const char* NO_VOXEL_PERSIST = "--NoVoxelPersist";
|
||||
if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) {
|
||||
::wantVoxelPersist = false;
|
||||
}
|
||||
printf("wantVoxelPersist=%s\n", (::wantVoxelPersist ? "yes" : "no"));
|
||||
|
||||
// Check to see if the user passed in a command line option for setting packet send rate
|
||||
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
||||
const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND);
|
||||
if (packetsPerSecond) {
|
||||
PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10;
|
||||
if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) {
|
||||
PACKETS_PER_CLIENT_PER_INTERVAL = 1;
|
||||
}
|
||||
printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL);
|
||||
}
|
||||
|
||||
const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels";
|
||||
if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) {
|
||||
// create an octal code buffer and load it with 0 so that the recursive tree fill can give
|
||||
// octal codes to the tree nodes that it is creating
|
||||
randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode);
|
||||
}
|
||||
|
||||
const char* ADD_SPHERE = "--AddSphere";
|
||||
const char* ADD_RANDOM_SPHERE = "--AddRandomSphere";
|
||||
if (cmdOptionExists(argc, argv, ADD_SPHERE)) {
|
||||
addSphere(&randomTree,false,wantColorRandomizer);
|
||||
} else if (cmdOptionExists(argc, argv, ADD_RANDOM_SPHERE)) {
|
||||
addSphere(&randomTree,true,wantColorRandomizer);
|
||||
// if we want Voxel Persistance, load the local file now...
|
||||
bool persistantFileRead = false;
|
||||
if (::wantVoxelPersist) {
|
||||
printf("loading voxels from file...\n");
|
||||
persistantFileRead = ::randomTree.readFromFileV2("voxels.hio2");
|
||||
::randomTree.clearDirtyBit(); // the tree is clean since we just loaded it
|
||||
printf("DONE loading voxels from file...\n");
|
||||
_nodeCount=0;
|
||||
::randomTree.recurseTreeWithOperation(countVoxelsOperation);
|
||||
printf("Nodes after loading scene %d nodes\n", _nodeCount);
|
||||
}
|
||||
|
||||
const char* NO_ADD_SCENE = "--NoAddScene";
|
||||
if (!cmdOptionExists(argc, argv, NO_ADD_SCENE)) {
|
||||
addSphereScene(&randomTree,wantColorRandomizer);
|
||||
// Check to see if the user passed in a command line option for loading an old style local
|
||||
// Voxel File. If so, load it now. This is not the same as a voxel persist file
|
||||
const char* INPUT_FILE = "-i";
|
||||
const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE);
|
||||
if (voxelsFilename) {
|
||||
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||
}
|
||||
|
||||
// Check to see if the user passed in a command line option for setting packet send rate
|
||||
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
||||
const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND);
|
||||
if (packetsPerSecond) {
|
||||
PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10;
|
||||
if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) {
|
||||
PACKETS_PER_CLIENT_PER_INTERVAL = 1;
|
||||
}
|
||||
printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL);
|
||||
}
|
||||
|
||||
const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels";
|
||||
if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) {
|
||||
// create an octal code buffer and load it with 0 so that the recursive tree fill can give
|
||||
// octal codes to the tree nodes that it is creating
|
||||
randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, randomTree.rootNode);
|
||||
}
|
||||
|
||||
const char* ADD_SPHERE = "--AddSphere";
|
||||
const char* ADD_RANDOM_SPHERE = "--AddRandomSphere";
|
||||
if (cmdOptionExists(argc, argv, ADD_SPHERE)) {
|
||||
addSphere(&randomTree,false,wantColorRandomizer);
|
||||
} else if (cmdOptionExists(argc, argv, ADD_RANDOM_SPHERE)) {
|
||||
addSphere(&randomTree,true,wantColorRandomizer);
|
||||
}
|
||||
|
||||
const char* ADD_SCENE = "--AddScene";
|
||||
bool addScene = cmdOptionExists(argc, argv, ADD_SCENE);
|
||||
const char* NO_ADD_SCENE = "--NoAddScene";
|
||||
bool noAddScene = cmdOptionExists(argc, argv, NO_ADD_SCENE);
|
||||
if (addScene && noAddScene) {
|
||||
printf("WARNING! --AddScene and --NoAddScene are mutually exclusive. We will honor --NoAddScene\n");
|
||||
}
|
||||
|
||||
// We will add a scene if...
|
||||
// 1) we attempted to load a persistant file and it wasn't there
|
||||
// 2) you asked us to add a scene
|
||||
// HOWEVER -- we will NEVER add a scene if you explicitly tell us not to!
|
||||
bool actuallyAddScene = !noAddScene && (addScene || (::wantVoxelPersist && !persistantFileRead));
|
||||
if (actuallyAddScene) {
|
||||
addSphereScene(&randomTree,wantColorRandomizer);
|
||||
}
|
||||
|
||||
pthread_t sendVoxelThread;
|
||||
pthread_create(&sendVoxelThread, NULL, distributeVoxelsToListeners, NULL);
|
||||
|
||||
|
||||
sockaddr agentPublicAddress;
|
||||
|
||||
unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE];
|
||||
|
@ -427,6 +466,9 @@ int main(int argc, const char * argv[])
|
|||
|
||||
// loop to send to agents requesting data
|
||||
while (true) {
|
||||
// check to see if we need to persist our voxel state
|
||||
persistVoxelsWhenDirty();
|
||||
|
||||
if (agentList->getAgentSocket().receive(&agentPublicAddress, packetData, &receivedBytes)) {
|
||||
// XXXBHG: Hacked in support for 'S' SET command
|
||||
if (packetData[0] == PACKET_HEADER_SET_VOXEL) {
|
||||
|
|
Loading…
Reference in a new issue