mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-16 17:46:46 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into avatardata_optimization
This commit is contained in:
commit
026fb5b344
14 changed files with 466 additions and 55 deletions
|
@ -32,6 +32,8 @@
|
|||
#include <QShortcut>
|
||||
#include <QTimer>
|
||||
#include <QtDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <PairingHandler.h>
|
||||
|
||||
#include <AgentTypes.h>
|
||||
|
@ -39,6 +41,7 @@
|
|||
#include <PerfStat.h>
|
||||
#include <AudioInjectionManager.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <OctalCode.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
@ -614,6 +617,12 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
}
|
||||
resizeGL(_glWidget->width(), _glWidget->height());
|
||||
break;
|
||||
case Qt::Key_Backspace:
|
||||
case Qt::Key_Delete:
|
||||
if (_selectVoxelMode->isChecked()) {
|
||||
deleteVoxelUnderCursor();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
event->ignore();
|
||||
|
@ -1002,7 +1011,7 @@ void Application::idle() {
|
|||
_mouseVoxel.z += faceVector.z * _mouseVoxel.s;
|
||||
}
|
||||
}
|
||||
} else if (_addVoxelMode->isChecked()) {
|
||||
} else if (_addVoxelMode->isChecked() || _selectVoxelMode->isChecked()) {
|
||||
// place the voxel a fixed distance away
|
||||
float worldMouseVoxelScale = _mouseVoxelScale * TREE_SCALE;
|
||||
glm::vec3 pt = mouseRayOrigin + mouseRayDirection * (2.0f + worldMouseVoxelScale * 0.5f);
|
||||
|
@ -1016,7 +1025,10 @@ void Application::idle() {
|
|||
// red indicates deletion
|
||||
_mouseVoxel.red = 255;
|
||||
_mouseVoxel.green = _mouseVoxel.blue = 0;
|
||||
|
||||
} else if (_selectVoxelMode->isChecked()) {
|
||||
// yellow indicates deletion
|
||||
_mouseVoxel.red = _mouseVoxel.green = 255;
|
||||
_mouseVoxel.blue = 0;
|
||||
} else { // _addVoxelMode->isChecked() || _colorVoxelMode->isChecked()
|
||||
QColor paintColor = _voxelPaintColor->data().value<QColor>();
|
||||
_mouseVoxel.red = paintColor.red();
|
||||
|
@ -1286,7 +1298,170 @@ void Application::chooseVoxelPaintColor() {
|
|||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
}
|
||||
|
||||
const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500;
|
||||
struct SendVoxelsOperationArgs {
|
||||
unsigned char* newBaseOctCode;
|
||||
unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE];
|
||||
int bufferInUse;
|
||||
|
||||
};
|
||||
|
||||
bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||
SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData;
|
||||
if (node->isColored()) {
|
||||
unsigned char* nodeOctalCode = node->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 ] = node->getColor()[RED_INDEX ];
|
||||
codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
||||
codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
||||
|
||||
// if we have room don't have room in the buffer, then send the previously generated message first
|
||||
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
||||
AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1);
|
||||
args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // reset
|
||||
}
|
||||
|
||||
// copy this node's code color details into our buffer.
|
||||
memcpy(&args->messageBuffer[args->bufferInUse], codeColorBuffer, codeAndColorLength);
|
||||
args->bufferInUse += codeAndColorLength;
|
||||
}
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
void Application::exportVoxels() {
|
||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||
QString suggestedName = desktopLocation.append("/voxels.svo");
|
||||
|
||||
QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), suggestedName,
|
||||
tr("Sparse Voxel Octree Files (*.svo)"));
|
||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||
const char* fileName = fileNameAscii.data();
|
||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
if (selectedNode) {
|
||||
VoxelTree exportTree;
|
||||
_voxels.copySubTreeIntoNewTree(selectedNode, &exportTree, true);
|
||||
exportTree.writeToSVOFile(fileName);
|
||||
}
|
||||
|
||||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
}
|
||||
|
||||
void Application::importVoxels() {
|
||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
|
||||
tr("Sparse Voxel Octree Files (*.svo)"));
|
||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||
const char* fileName = fileNameAscii.data();
|
||||
|
||||
// Read the file into a tree
|
||||
VoxelTree importVoxels;
|
||||
importVoxels.readFromSVOFile(fileName);
|
||||
|
||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
|
||||
// Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to
|
||||
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||
unsigned char* calculatedOctCode = NULL;
|
||||
SendVoxelsOperationArgs args;
|
||||
args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
||||
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)];
|
||||
*sequenceAt = 0;
|
||||
args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence
|
||||
|
||||
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||
// voxel size/position details.
|
||||
if (selectedNode) {
|
||||
args.newBaseOctCode = selectedNode->getOctalCode();
|
||||
} else {
|
||||
args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
}
|
||||
|
||||
importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args);
|
||||
|
||||
// If we have voxels left in the packet, then send the packet
|
||||
if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) {
|
||||
AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1);
|
||||
}
|
||||
|
||||
if (calculatedOctCode) {
|
||||
delete calculatedOctCode;
|
||||
}
|
||||
|
||||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
}
|
||||
|
||||
void Application::cutVoxels() {
|
||||
copyVoxels();
|
||||
deleteVoxelUnderCursor();
|
||||
}
|
||||
|
||||
void Application::copyVoxels() {
|
||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
if (selectedNode) {
|
||||
// clear the clipboard first...
|
||||
_clipboardTree.eraseAllVoxels();
|
||||
|
||||
// then copy onto it
|
||||
_voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::pasteVoxels() {
|
||||
unsigned char* calculatedOctCode = NULL;
|
||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
|
||||
// Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to
|
||||
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||
SendVoxelsOperationArgs args;
|
||||
args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
||||
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)];
|
||||
*sequenceAt = 0;
|
||||
args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence
|
||||
|
||||
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||
// voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a
|
||||
// target octalCode for where the user is pointing.
|
||||
if (selectedNode) {
|
||||
args.newBaseOctCode = selectedNode->getOctalCode();
|
||||
} else {
|
||||
args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
}
|
||||
|
||||
_clipboardTree.recurseTreeWithOperation(sendVoxelsOperation, &args);
|
||||
|
||||
// If we have voxels left in the packet, then send the packet
|
||||
if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) {
|
||||
AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1);
|
||||
}
|
||||
|
||||
if (calculatedOctCode) {
|
||||
delete calculatedOctCode;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::initMenu() {
|
||||
QMenuBar* menuBar = new QMenuBar();
|
||||
_window->setMenuBar(menuBar);
|
||||
|
@ -1345,26 +1520,40 @@ void Application::initMenu() {
|
|||
QMenu* voxelMenu = menuBar->addMenu("Voxels");
|
||||
_voxelModeActions = new QActionGroup(this);
|
||||
_voxelModeActions->setExclusive(false); // exclusivity implies one is always checked
|
||||
|
||||
(_addVoxelMode = voxelMenu->addAction(
|
||||
"Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_1))->setCheckable(true);
|
||||
"Add Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_A))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_addVoxelMode);
|
||||
(_deleteVoxelMode = voxelMenu->addAction(
|
||||
"Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_2))->setCheckable(true);
|
||||
"Delete Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_D))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_deleteVoxelMode);
|
||||
(_colorVoxelMode = voxelMenu->addAction(
|
||||
"Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::Key_3))->setCheckable(true);
|
||||
"Color Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_B))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_colorVoxelMode);
|
||||
(_selectVoxelMode = voxelMenu->addAction(
|
||||
"Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_selectVoxelMode);
|
||||
(_eyedropperMode = voxelMenu->addAction(
|
||||
"Get Color Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_G))->setCheckable(true);
|
||||
_voxelModeActions->addAction(_eyedropperMode);
|
||||
|
||||
voxelMenu->addAction("Place Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::Key_4);
|
||||
voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), Qt::Key_5);
|
||||
voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), Qt::Key_6);
|
||||
voxelMenu->addAction("Place New Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::Key_N);
|
||||
voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut);
|
||||
voxelMenu->addAction("Increase Voxel Size", this, SLOT(increaseVoxelSize()), QKeySequence::ZoomIn);
|
||||
|
||||
_voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this, SLOT(chooseVoxelPaintColor()), Qt::Key_7);
|
||||
_voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this,
|
||||
SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C);
|
||||
QColor paintColor(128, 128, 128);
|
||||
_voxelPaintColor->setData(paintColor);
|
||||
_voxelPaintColor->setIcon(createSwatchIcon(paintColor));
|
||||
(_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true);
|
||||
|
||||
voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E);
|
||||
voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I);
|
||||
voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X);
|
||||
voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C);
|
||||
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
|
||||
|
||||
QMenu* frustumMenu = menuBar->addMenu("Frustum");
|
||||
(_frustumOn = frustumMenu->addAction("Display Frustum"))->setCheckable(true);
|
||||
_frustumOn->setShortcut(Qt::SHIFT | Qt::Key_F);
|
||||
|
@ -2161,7 +2350,6 @@ void Application::maybeEditVoxelUnderCursor() {
|
|||
//_myAvatar.getPosition()
|
||||
voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw());
|
||||
voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value
|
||||
// printf("mousevoxelscale is %f\n", _mouseVoxel.s);
|
||||
|
||||
/* for (int i = 0; i
|
||||
< 22050; i++) {
|
||||
|
@ -2212,6 +2400,8 @@ void Application::maybeEditVoxelUnderCursor() {
|
|||
}
|
||||
} else if (_deleteVoxelMode->isChecked()) {
|
||||
deleteVoxelUnderCursor();
|
||||
} else if (_eyedropperMode->isChecked()) {
|
||||
eyedropperVoxelUnderCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2227,7 +2417,7 @@ void Application::deleteVoxelUnderCursor() {
|
|||
|
||||
for (int i = 0; i < 5000; i++) {
|
||||
voxelInjector->addSample(10000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 500.0)))); //FM 3 resonant pulse
|
||||
// voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter
|
||||
//voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter
|
||||
}
|
||||
|
||||
AudioInjectionManager::threadInjector(voxelInjector);
|
||||
|
@ -2236,6 +2426,20 @@ void Application::deleteVoxelUnderCursor() {
|
|||
_justEditedVoxel = true;
|
||||
}
|
||||
|
||||
void Application::eyedropperVoxelUnderCursor() {
|
||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||
if (selectedNode && selectedNode->isColored()) {
|
||||
QColor selectedColor(selectedNode->getColor()[RED_INDEX],
|
||||
selectedNode->getColor()[GREEN_INDEX],
|
||||
selectedNode->getColor()[BLUE_INDEX]);
|
||||
|
||||
if (selectedColor.isValid()) {
|
||||
_voxelPaintColor->setData(selectedColor);
|
||||
_voxelPaintColor->setIcon(createSwatchIcon(selectedColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::goHome() {
|
||||
_myAvatar.setPosition(START_LOCATION);
|
||||
}
|
||||
|
|
|
@ -154,8 +154,15 @@ private slots:
|
|||
void decreaseVoxelSize();
|
||||
void increaseVoxelSize();
|
||||
void chooseVoxelPaintColor();
|
||||
|
||||
void exportVoxels();
|
||||
void importVoxels();
|
||||
void cutVoxels();
|
||||
void copyVoxels();
|
||||
void pasteVoxels();
|
||||
|
||||
private:
|
||||
|
||||
static bool sendVoxelsOperation(VoxelNode* node, void* extraData);
|
||||
|
||||
void initMenu();
|
||||
void updateFrustumRenderModeAction();
|
||||
|
@ -176,7 +183,7 @@ private:
|
|||
void shiftPaintingColor();
|
||||
void maybeEditVoxelUnderCursor();
|
||||
void deleteVoxelUnderCursor();
|
||||
|
||||
void eyedropperVoxelUnderCursor();
|
||||
void goHome();
|
||||
void resetSensors();
|
||||
|
||||
|
@ -218,6 +225,8 @@ private:
|
|||
QAction* _addVoxelMode; // Whether add voxel mode is enabled
|
||||
QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled
|
||||
QAction* _colorVoxelMode; // Whether color voxel mode is enabled
|
||||
QAction* _selectVoxelMode; // Whether select voxel mode is enabled
|
||||
QAction* _eyedropperMode; // Whether voxel color eyedropper mode is enabled
|
||||
QAction* _voxelPaintColor; // The color with which to paint voxels
|
||||
QAction* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive
|
||||
QAction* _frustumOn; // Whether or not to display the debug view frustum
|
||||
|
@ -242,6 +251,8 @@ private:
|
|||
Stars _stars;
|
||||
|
||||
VoxelSystem _voxels;
|
||||
VoxelTree _clipboardTree; // if I copy/paste
|
||||
|
||||
QByteArray _voxelsFilename;
|
||||
bool _wantToKillLocalVoxels;
|
||||
|
||||
|
|
|
@ -70,6 +70,18 @@ void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer)
|
|||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
void VoxelSystem::writeToSVOFile(const char* filename, VoxelNode* node) const {
|
||||
_tree->writeToSVOFile(filename, node);
|
||||
}
|
||||
|
||||
bool VoxelSystem::readFromSVOFile(const char* filename) {
|
||||
bool result = _tree->readFromSVOFile(filename);
|
||||
if (result) {
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
long int VoxelSystem::getVoxelsCreated() {
|
||||
return _tree->voxelsCreated;
|
||||
}
|
||||
|
@ -1147,3 +1159,12 @@ void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bo
|
|||
_tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug);
|
||||
setupNewVoxelsForDrawing();
|
||||
};
|
||||
|
||||
void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) {
|
||||
_tree->copySubTreeIntoNewTree(startNode, destinationTree, rebaseToRoot);
|
||||
}
|
||||
|
||||
void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) {
|
||||
_tree->copyFromTreeIntoSubTree(sourceTree, destinationNode);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; };
|
||||
void setCamera(Camera* newCamera) { _camera = newCamera; };
|
||||
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
|
||||
void writeToSVOFile(const char* filename, VoxelNode* node) const;
|
||||
bool readFromSVOFile(const char* filename);
|
||||
|
||||
long int getVoxelsCreated();
|
||||
long int getVoxelsColored();
|
||||
|
@ -83,6 +85,10 @@ public:
|
|||
void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive = false);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid,
|
||||
creationMode mode, bool destructive = false, bool debug = false);
|
||||
|
||||
void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot);
|
||||
void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode);
|
||||
|
||||
private:
|
||||
// disallow copying of VoxelSystem objects
|
||||
VoxelSystem(const VoxelSystem&);
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <OctalCode.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
timeval startup_time;
|
||||
gettimeofday(&startup_time, NULL);
|
||||
|
||||
|
|
|
@ -59,7 +59,6 @@ void* AudioInjectionManager::injectAudioViaThread(void* args) {
|
|||
// if we don't have an explicit destination socket then pull active socket for current audio mixer from agent list
|
||||
if (!_isDestinationSocketExplicit) {
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer) {
|
||||
_destinationSocket = *audioMixer->getActiveSocket();
|
||||
}
|
||||
|
|
|
@ -168,3 +168,88 @@ OctalCodeComparison compareOctalCodes(unsigned char* codeA, unsigned char* codeB
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
char getOctalCodeSectionValue(unsigned char* octalCode, int section) {
|
||||
int startAtByte = 1 + (BITS_IN_OCTAL * section / BITS_IN_BYTE);
|
||||
char startIndexInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE;
|
||||
unsigned char* startByte = octalCode + startAtByte;
|
||||
|
||||
return sectionValue(startByte, startIndexInByte);
|
||||
}
|
||||
|
||||
void setOctalCodeSectionValue(unsigned char* octalCode, int section, char sectionValue) {
|
||||
int byteForSection = (BITS_IN_OCTAL * section / BITS_IN_BYTE);
|
||||
unsigned char* byteAt = octalCode + 1 + byteForSection;
|
||||
char bitInByte = (BITS_IN_OCTAL * section) % BITS_IN_BYTE;
|
||||
char shiftBy = BITS_IN_BYTE - bitInByte - BITS_IN_OCTAL;
|
||||
const unsigned char UNSHIFTED_MASK = 0x07;
|
||||
unsigned char shiftedMask;
|
||||
unsigned char shiftedValue;
|
||||
if (shiftBy >=0) {
|
||||
shiftedMask = UNSHIFTED_MASK << shiftBy;
|
||||
shiftedValue = sectionValue << shiftBy;
|
||||
} else {
|
||||
shiftedMask = UNSHIFTED_MASK >> -shiftBy;
|
||||
shiftedValue = sectionValue >> -shiftBy;
|
||||
}
|
||||
unsigned char oldValue = *byteAt & ~shiftedMask;
|
||||
unsigned char newValue = oldValue | shiftedValue;
|
||||
*byteAt = newValue;
|
||||
|
||||
// If the requested section is partially in the byte, then we
|
||||
// need to also set the portion of the section value in the next byte
|
||||
// there's only two cases where this happens, if the bit in byte is
|
||||
// 6, then it means that 1 extra bit lives in the next byte. If the
|
||||
// bit in this byte is 7 then 2 extra bits live in the next byte.
|
||||
const int FIRST_PARTIAL_BIT = 6;
|
||||
if (bitInByte >= FIRST_PARTIAL_BIT) {
|
||||
int bitsInFirstByte = BITS_IN_BYTE - bitInByte;
|
||||
int bitsInSecondByte = BITS_IN_OCTAL - bitsInFirstByte;
|
||||
shiftBy = BITS_IN_BYTE - bitsInSecondByte;
|
||||
|
||||
shiftedMask = UNSHIFTED_MASK << shiftBy;
|
||||
shiftedValue = sectionValue << shiftBy;
|
||||
|
||||
oldValue = byteAt[1] & ~shiftedMask;
|
||||
newValue = oldValue | shiftedValue;
|
||||
byteAt[1] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels) {
|
||||
int codeLength = numberOfThreeBitSectionsInCode(originalOctalCode);
|
||||
unsigned char* newCode = NULL;
|
||||
if (codeLength > chopLevels) {
|
||||
int newLength = codeLength - chopLevels;
|
||||
newCode = new unsigned char[newLength+1];
|
||||
*newCode = newLength; // set the length byte
|
||||
|
||||
for (int section = chopLevels; section < codeLength; section++) {
|
||||
char sectionValue = getOctalCodeSectionValue(originalOctalCode, section);
|
||||
setOctalCodeSectionValue(newCode, section - chopLevels, sectionValue);
|
||||
}
|
||||
}
|
||||
return newCode;
|
||||
}
|
||||
|
||||
unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode, bool includeColorSpace) {
|
||||
int oldCodeLength = numberOfThreeBitSectionsInCode(originalOctalCode);
|
||||
int newParentCodeLength = numberOfThreeBitSectionsInCode(newParentOctalCode);
|
||||
int newCodeLength = newParentCodeLength + oldCodeLength;
|
||||
int bufferLength = newCodeLength + (includeColorSpace ? SIZE_OF_COLOR_DATA : 0);
|
||||
unsigned char* newCode = new unsigned char[bufferLength];
|
||||
*newCode = newCodeLength; // set the length byte
|
||||
|
||||
// copy parent code section first
|
||||
for (int sectionFromParent = 0; sectionFromParent < newParentCodeLength; sectionFromParent++) {
|
||||
char sectionValue = getOctalCodeSectionValue(newParentOctalCode, sectionFromParent);
|
||||
setOctalCodeSectionValue(newCode, sectionFromParent, sectionValue);
|
||||
}
|
||||
// copy original code section next
|
||||
for (int sectionFromOriginal = 0; sectionFromOriginal < oldCodeLength; sectionFromOriginal++) {
|
||||
char sectionValue = getOctalCodeSectionValue(originalOctalCode, sectionFromOriginal);
|
||||
setOctalCodeSectionValue(newCode, sectionFromOriginal + newParentCodeLength, sectionValue);
|
||||
}
|
||||
return newCode;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,12 +11,23 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
const int BITS_IN_BYTE = 8;
|
||||
const int BITS_IN_OCTAL = 3;
|
||||
const int NUMBER_OF_COLORS = 3; // RGB!
|
||||
const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes
|
||||
const int RED_INDEX = 0;
|
||||
const int GREEN_INDEX = 1;
|
||||
const int BLUE_INDEX = 2;
|
||||
|
||||
void printOctalCode(unsigned char * octalCode);
|
||||
int bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
||||
bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode);
|
||||
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
|
||||
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber);
|
||||
|
||||
int numberOfThreeBitSectionsInCode(unsigned char * octalCode);
|
||||
unsigned char* chopOctalCode(unsigned char* originalOctalCode, int chopLevels);
|
||||
unsigned char* rebaseOctalCode(unsigned char* originalOctalCode, unsigned char* newParentOctalCode,
|
||||
bool includeColorSpace = false);
|
||||
|
||||
// Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return
|
||||
// but other than that these do the same thing.
|
||||
|
|
|
@ -75,7 +75,7 @@ struct VoxelDetail {
|
|||
unsigned char blue;
|
||||
};
|
||||
|
||||
unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, unsigned char g, unsigned char b );
|
||||
unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r = 0, unsigned char g = 0, unsigned char b = 0);
|
||||
bool createVoxelEditMessage(unsigned char command, short int sequence,
|
||||
int voxelCount, VoxelDetail* voxelDetails, unsigned char*& bufferOut, int& sizeOut);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define __hifi_VoxelConstants_h__
|
||||
|
||||
#include <limits.h>
|
||||
#include <OctalCode.h>
|
||||
|
||||
const int TREE_SCALE = 128;
|
||||
|
||||
|
@ -23,11 +24,12 @@ const int MAX_VOXELS_PER_SYSTEM = 200000;
|
|||
const int VERTICES_PER_VOXEL = 24;
|
||||
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
const int INDICES_PER_VOXEL = 3 * 12;
|
||||
const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL;
|
||||
|
||||
typedef unsigned long int glBufferIndex;
|
||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||
|
||||
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
||||
const double VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0; // once a second is fine
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,7 +53,7 @@ VoxelTree::~VoxelTree() {
|
|||
// Recurses voxel tree calling the RecurseVoxelTreeOperation function for each node.
|
||||
// stops recursion if operation function returns false.
|
||||
void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData) {
|
||||
recurseNodeWithOperation(rootNode, operation,extraData);
|
||||
recurseNodeWithOperation(rootNode, operation, extraData);
|
||||
}
|
||||
|
||||
// Recurses voxel node with an operation function
|
||||
|
@ -212,10 +212,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
|
|||
}
|
||||
|
||||
void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes,
|
||||
bool includeColor, bool includeExistsBits) {
|
||||
bool includeColor, bool includeExistsBits, VoxelNode* destinationNode) {
|
||||
int bytesRead = 0;
|
||||
unsigned char* bitstreamAt = bitstream;
|
||||
|
||||
// If destination node is not included, set it to root
|
||||
if (!destinationNode) {
|
||||
destinationNode = rootNode;
|
||||
}
|
||||
|
||||
_nodesChangedFromBitstream = 0;
|
||||
|
||||
// Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes
|
||||
|
@ -223,14 +228,14 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int
|
|||
// if there are more bytes after that, it's assumed to be another root relative tree
|
||||
|
||||
while (bitstreamAt < bitstream + bufferSizeBytes) {
|
||||
VoxelNode* bitstreamRootNode = nodeForOctalCode(rootNode, (unsigned char *)bitstreamAt, NULL);
|
||||
VoxelNode* bitstreamRootNode = nodeForOctalCode(destinationNode, (unsigned char *)bitstreamAt, NULL);
|
||||
if (*bitstreamAt != *bitstreamRootNode->getOctalCode()) {
|
||||
// if the octal code returned is not on the same level as
|
||||
// the code being searched for, we have VoxelNodes to create
|
||||
|
||||
// Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial
|
||||
// octal code is always relative to root!
|
||||
bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt);
|
||||
bitstreamRootNode = createMissingNode(destinationNode, (unsigned char*) bitstreamAt);
|
||||
if (bitstreamRootNode->isDirty()) {
|
||||
_isDirty = true;
|
||||
_nodesChangedFromBitstream++;
|
||||
|
@ -281,9 +286,9 @@ void VoxelTree::deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage, b
|
|||
}
|
||||
}
|
||||
|
||||
// If we're not a colored leaf, and we have no children, then delete ourselves
|
||||
// This will collapse the empty tree above us.
|
||||
if (collapseEmptyTrees && parentNode->getChildCount() == 0 && !parentNode->isColored()) {
|
||||
// If we're in collapseEmptyTrees mode, and we're the last child of this parent, then delete the parent.
|
||||
// This will collapse the empty tree above us.
|
||||
if (collapseEmptyTrees && parentNode->getChildCount() == 0) {
|
||||
// Can't delete the root this way.
|
||||
if (parentNode != rootNode) {
|
||||
deleteVoxelCodeFromTree(parentNode->getOctalCode(), stage, collapseEmptyTrees);
|
||||
|
@ -862,7 +867,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
|
|||
|
||||
int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
||||
VoxelNodeBag& bag, const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
||||
int chopLevels, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
||||
|
||||
// How many bytes have we written so far at this level;
|
||||
int bytesWritten = 0;
|
||||
|
@ -873,16 +878,29 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
|
|||
}
|
||||
|
||||
// write the octal code
|
||||
int codeLength = bytesRequiredForCodeLength(*node->getOctalCode());
|
||||
memcpy(outputBuffer,node->getOctalCode(),codeLength);
|
||||
|
||||
int codeLength;
|
||||
if (chopLevels) {
|
||||
unsigned char* newCode = chopOctalCode(node->getOctalCode(), chopLevels);
|
||||
if (newCode) {
|
||||
codeLength = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(newCode));
|
||||
memcpy(outputBuffer, newCode, codeLength);
|
||||
delete newCode;
|
||||
} else {
|
||||
codeLength = 1; // chopped to root!
|
||||
*outputBuffer = 0; // root
|
||||
}
|
||||
} else {
|
||||
codeLength = bytesRequiredForCodeLength(*node->getOctalCode());
|
||||
memcpy(outputBuffer, node->getOctalCode(), codeLength);
|
||||
}
|
||||
|
||||
outputBuffer += codeLength; // move the pointer
|
||||
bytesWritten += codeLength; // keep track of byte count
|
||||
availableBytes -= codeLength; // keep track or remaining space
|
||||
|
||||
int currentEncodeLevel = 0;
|
||||
int childBytesWritten = encodeTreeBitstreamRecursion(maxEncodeLevel, currentEncodeLevel, node, outputBuffer, availableBytes,
|
||||
bag, viewFrustum, includeColor, includeExistsBits,
|
||||
bag, viewFrustum, includeColor, includeExistsBits, chopLevels,
|
||||
deltaViewFrustum, lastViewFrustum);
|
||||
|
||||
// if childBytesWritten == 1 then something went wrong... that's not possible
|
||||
|
@ -907,7 +925,7 @@ int VoxelTree::encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned
|
|||
int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, VoxelNode* node,
|
||||
unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
|
||||
const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
||||
int chopLevels, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const {
|
||||
|
||||
// How many bytes have we written so far at this level;
|
||||
int bytesAtThisLevel = 0;
|
||||
|
@ -1062,7 +1080,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
|||
int thisLevel = currentEncodeLevel;
|
||||
int childTreeBytesOut = encodeTreeBitstreamRecursion(maxEncodeLevel, thisLevel, childNode,
|
||||
outputBuffer, availableBytes, bag,
|
||||
viewFrustum, includeColor, includeExistsBits,
|
||||
viewFrustum, includeColor, includeExistsBits, chopLevels,
|
||||
deltaViewFrustum, lastViewFrustum);
|
||||
|
||||
// if the child wrote 0 bytes, it means that nothing below exists or was in view, or we ran out of space,
|
||||
|
@ -1105,7 +1123,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
|
|||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
bool VoxelTree::readFromFileV2(const char* fileName) {
|
||||
bool VoxelTree::readFromSVOFile(const char* fileName) {
|
||||
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
|
||||
if(file.is_open()) {
|
||||
printLog("loading file %s...\n", fileName);
|
||||
|
@ -1126,7 +1144,7 @@ bool VoxelTree::readFromFileV2(const char* fileName) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void VoxelTree::writeToFileV2(const char* fileName) const {
|
||||
void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) const {
|
||||
|
||||
std::ofstream file(fileName, std::ios::out|std::ios::binary);
|
||||
|
||||
|
@ -1134,7 +1152,12 @@ void VoxelTree::writeToFileV2(const char* fileName) const {
|
|||
printLog("saving to file %s...\n", fileName);
|
||||
|
||||
VoxelNodeBag nodeBag;
|
||||
nodeBag.insert(rootNode);
|
||||
// If we were given a specific node, start from there, otherwise start from root
|
||||
if (node) {
|
||||
nodeBag.insert(node);
|
||||
} else {
|
||||
nodeBag.insert(rootNode);
|
||||
}
|
||||
|
||||
static unsigned char outputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
|
||||
int bytesWritten = 0;
|
||||
|
@ -1160,3 +1183,47 @@ bool VoxelTree::countVoxelsOperation(VoxelNode* node, void* extraData) {
|
|||
(*(unsigned long*)extraData)++;
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
void VoxelTree::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) {
|
||||
VoxelNodeBag nodeBag;
|
||||
nodeBag.insert(startNode);
|
||||
int chopLevels = 0;
|
||||
if (rebaseToRoot) {
|
||||
chopLevels = numberOfThreeBitSectionsInCode(startNode->getOctalCode());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// ask our tree to write a bitsteam
|
||||
bytesWritten = encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0],
|
||||
MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels);
|
||||
|
||||
// ask destination tree to read the bitstream
|
||||
destinationTree->readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS);
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) {
|
||||
VoxelNodeBag nodeBag;
|
||||
// If we were given a specific node, start from there, otherwise start from root
|
||||
nodeBag.insert(sourceTree->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();
|
||||
|
||||
// ask our tree to write a bitsteam
|
||||
bytesWritten = sourceTree->encodeTreeBitstream(INT_MAX, subTree, &outputBuffer[0],
|
||||
MAX_VOXEL_PACKET_SIZE - 1, nodeBag, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
|
||||
|
||||
// ask destination tree to read the bitstream
|
||||
readBitstreamToTree(&outputBuffer[0], bytesWritten, WANT_COLOR, NO_EXISTS_BITS, destinationNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,19 +44,20 @@ public:
|
|||
VoxelTree(bool shouldReaverage = false);
|
||||
~VoxelTree();
|
||||
|
||||
VoxelNode *rootNode;
|
||||
VoxelNode* rootNode;
|
||||
int leavesWrittenToBitstream;
|
||||
|
||||
void eraseAllVoxels();
|
||||
|
||||
void processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes);
|
||||
void readBitstreamToTree(unsigned char * bitstream, unsigned long int bufferSizeBytes,
|
||||
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS);
|
||||
void readCodeColorBufferToTree(unsigned char *codeColorBuffer, bool destructive = false);
|
||||
void deleteVoxelCodeFromTree(unsigned char *codeBuffer, bool stage = ACTUALLY_DELETE,
|
||||
void processRemoveVoxelBitstream(unsigned char* bitstream, int bufferSizeBytes);
|
||||
void readBitstreamToTree(unsigned char* bitstream, unsigned long int bufferSizeBytes,
|
||||
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS,
|
||||
VoxelNode* destinationNode = NULL);
|
||||
void readCodeColorBufferToTree(unsigned char* codeColorBuffer, bool destructive = false);
|
||||
void deleteVoxelCodeFromTree(unsigned char* codeBuffer, bool stage = ACTUALLY_DELETE,
|
||||
bool collapseEmptyTrees = DONT_COLLAPSE);
|
||||
void printTreeForDebugging(VoxelNode *startNode);
|
||||
void reaverageVoxelColors(VoxelNode *startNode);
|
||||
void printTreeForDebugging(VoxelNode* startNode);
|
||||
void reaverageVoxelColors(VoxelNode* startNode);
|
||||
|
||||
void deleteVoxelAt(float x, float y, float z, float s, bool stage = false);
|
||||
VoxelNode* getVoxelAt(float x, float y, float z, float s) const;
|
||||
|
@ -70,7 +71,7 @@ public:
|
|||
|
||||
int encodeTreeBitstream(int maxEncodeLevel, VoxelNode* node, unsigned char* outputBuffer, int availableBytes,
|
||||
VoxelNodeBag& bag, const ViewFrustum* viewFrustum,
|
||||
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS,
|
||||
bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, int chopLevels = 0,
|
||||
bool deltaViewFrustum = false, const ViewFrustum* lastViewFrustum = NULL) const;
|
||||
|
||||
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag,
|
||||
|
@ -91,16 +92,19 @@ public:
|
|||
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);
|
||||
void writeToSVOFile(const char* filename, VoxelNode* node = NULL) const;
|
||||
bool readFromSVOFile(const char* filename);
|
||||
|
||||
unsigned long getVoxelCount();
|
||||
|
||||
void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot);
|
||||
void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode);
|
||||
|
||||
private:
|
||||
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||
VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
|
||||
const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||
bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const;
|
||||
const ViewFrustum* viewFrustum, bool includeColor, bool includeExistsBits,
|
||||
int chopLevels, bool deltaViewFrustum, const ViewFrustum* lastViewFrustum) const;
|
||||
|
||||
int searchForColoredNodesRecursion(int maxSearchLevel, int& currentSearchLevel,
|
||||
VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag,
|
||||
|
|
|
@ -92,7 +92,7 @@ int main(int argc, const char * argv[])
|
|||
unsigned long nodeCount = myTree.getVoxelCount();
|
||||
printf("Nodes after adding scenes: %ld nodes\n", nodeCount);
|
||||
|
||||
myTree.writeToFileV2("voxels.hio2");
|
||||
myTree.writeToSVOFile("voxels.svo");
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.hio2";
|
||||
const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.hio2";
|
||||
const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo";
|
||||
const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo";
|
||||
const double VOXEL_PERSIST_INTERVAL = 1000.0 * 30; // every 30 seconds
|
||||
|
||||
const int VOXEL_LISTEN_PORT = 40106;
|
||||
|
@ -399,10 +399,10 @@ void persistVoxelsWhenDirty() {
|
|||
|
||||
{
|
||||
PerformanceWarning warn(::shouldShowAnimationDebug,
|
||||
"persistVoxelsWhenDirty() - writeToFileV2()", ::shouldShowAnimationDebug);
|
||||
"persistVoxelsWhenDirty() - writeToSVOFile()", ::shouldShowAnimationDebug);
|
||||
|
||||
printf("saving voxels to file...\n");
|
||||
randomTree.writeToFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
||||
randomTree.writeToSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
||||
randomTree.clearDirtyBit(); // tree is clean after saving
|
||||
printf("DONE saving voxels to file...\n");
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ int main(int argc, const char * argv[]) {
|
|||
bool persistantFileRead = false;
|
||||
if (::wantVoxelPersist) {
|
||||
printf("loading voxels from file...\n");
|
||||
persistantFileRead = ::randomTree.readFromFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
||||
persistantFileRead = ::randomTree.readFromSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE);
|
||||
::randomTree.clearDirtyBit(); // the tree is clean since we just loaded it
|
||||
printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead));
|
||||
unsigned long nodeCount = ::randomTree.getVoxelCount();
|
||||
|
@ -517,7 +517,7 @@ int main(int argc, const char * argv[]) {
|
|||
const char* INPUT_FILE = "-i";
|
||||
const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE);
|
||||
if (voxelsFilename) {
|
||||
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||
randomTree.readFromSVOFile(voxelsFilename);
|
||||
}
|
||||
|
||||
// Check to see if the user passed in a command line option for setting packet send rate
|
||||
|
|
Loading…
Reference in a new issue