mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-23 11:04:02 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
dabb670f1a
25 changed files with 307 additions and 155 deletions
|
@ -57,7 +57,7 @@ void Agent::run() {
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
nodeList->setOwnerType(NODE_TYPE_AGENT);
|
nodeList->setOwnerType(NODE_TYPE_AGENT);
|
||||||
|
|
||||||
const char AGENT_NODE_TYPES_OF_INTEREST[2] = { NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AUDIO_MIXER };
|
const char AGENT_NODE_TYPES_OF_INTEREST[1] = { NODE_TYPE_VOXEL_SERVER };
|
||||||
|
|
||||||
nodeList->setNodeTypesOfInterest(AGENT_NODE_TYPES_OF_INTEREST, sizeof(AGENT_NODE_TYPES_OF_INTEREST));
|
nodeList->setNodeTypesOfInterest(AGENT_NODE_TYPES_OF_INTEREST, sizeof(AGENT_NODE_TYPES_OF_INTEREST));
|
||||||
|
|
||||||
|
@ -114,9 +114,11 @@ void Agent::run() {
|
||||||
|
|
||||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||||
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||||
|
|
||||||
|
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||||
|
|
||||||
// let the VoxelPacketSender know how frequently we plan to call it
|
// let the VoxelPacketSender know how frequently we plan to call it
|
||||||
voxelScripter.getVoxelPacketSender()->setProcessCallIntervalHint(INJECT_INTERVAL_USECS);
|
voxelScripter.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||||
|
|
||||||
// hook in a constructor for audio injectorss
|
// hook in a constructor for audio injectorss
|
||||||
AudioInjector scriptedAudioInjector(BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
AudioInjector scriptedAudioInjector(BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||||
|
@ -158,28 +160,14 @@ void Agent::run() {
|
||||||
NodeList::getInstance()->sendDomainServerCheckIn();
|
NodeList::getInstance()->sendDomainServerCheckIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the audio-mixer in the NodeList so we can inject audio at it
|
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
|
||||||
Node* audioMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
|
|
||||||
|
|
||||||
|
|
||||||
if (audioMixer && audioMixer->getActiveSocket()) {
|
|
||||||
emit willSendAudioDataCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow();
|
|
||||||
if (usecToSleep > 0) {
|
if (usecToSleep > 0) {
|
||||||
usleep(usecToSleep);
|
usleep(usecToSleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioMixer && NodeList::getInstance()->getNodeActiveSocketOrPing(audioMixer) && scriptedAudioInjector.hasSamplesToInject()) {
|
|
||||||
// we have an audio mixer and samples to inject, send those off
|
|
||||||
scriptedAudioInjector.injectAudio(NodeList::getInstance()->getNodeSocket(), audioMixer->getActiveSocket());
|
|
||||||
|
|
||||||
// clear out the audio injector so that it doesn't re-send what we just sent
|
|
||||||
scriptedAudioInjector.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (voxelScripter.getVoxelPacketSender()->voxelServersExist()) {
|
if (voxelScripter.getVoxelPacketSender()->voxelServersExist()) {
|
||||||
|
timeval thisSend = {};
|
||||||
|
gettimeofday(&thisSend, NULL);
|
||||||
// allow the scripter's call back to setup visual data
|
// allow the scripter's call back to setup visual data
|
||||||
emit willSendVisualDataCallback();
|
emit willSendVisualDataCallback();
|
||||||
|
|
||||||
|
@ -188,14 +176,13 @@ void Agent::run() {
|
||||||
|
|
||||||
// since we're in non-threaded mode, call process so that the packets are sent
|
// since we're in non-threaded mode, call process so that the packets are sent
|
||||||
voxelScripter.getVoxelPacketSender()->process();
|
voxelScripter.getVoxelPacketSender()->process();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (engine.hasUncaughtException()) {
|
if (engine.hasUncaughtException()) {
|
||||||
int line = engine.uncaughtExceptionLineNumber();
|
int line = engine.uncaughtExceptionLineNumber();
|
||||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
while (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)
|
while (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)
|
||||||
&& packetVersionMatch(receivedData)) {
|
&& packetVersionMatch(receivedData)) {
|
||||||
if (receivedData[0] == PACKET_TYPE_VOXEL_JURISDICTION) {
|
if (receivedData[0] == PACKET_TYPE_VOXEL_JURISDICTION) {
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
|
||||||
|
|
||||||
|
|
||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
|
|
|
@ -78,6 +78,11 @@ function updateCells() {
|
||||||
nextCells[i][j] = -1;
|
nextCells[i][j] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Math.random() < 0.001) {
|
||||||
|
// Random mutation to keep things interesting in there.
|
||||||
|
nextCells[i][j] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4094,11 +4094,13 @@ void Application::nodeKilled(Node* node) {
|
||||||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||||
|
|
||||||
// Add the jurisditionDetails object to the list of "fade outs"
|
// Add the jurisditionDetails object to the list of "fade outs"
|
||||||
VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE);
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) {
|
||||||
fade.voxelDetails = rootDetails;
|
VoxelFade fade(VoxelFade::FADE_OUT, NODE_KILLED_RED, NODE_KILLED_GREEN, NODE_KILLED_BLUE);
|
||||||
const float slightly_smaller = 0.99;
|
fade.voxelDetails = rootDetails;
|
||||||
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
const float slightly_smaller = 0.99;
|
||||||
_voxelFades.push_back(fade);
|
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
||||||
|
_voxelFades.push_back(fade);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (node->getLinkedData() == _lookatTargetAvatar) {
|
} else if (node->getLinkedData() == _lookatTargetAvatar) {
|
||||||
_lookatTargetAvatar = NULL;
|
_lookatTargetAvatar = NULL;
|
||||||
|
@ -4127,11 +4129,13 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng
|
||||||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||||
|
|
||||||
// Add the jurisditionDetails object to the list of "fade outs"
|
// Add the jurisditionDetails object to the list of "fade outs"
|
||||||
VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE);
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontFadeOnVoxelServerChanges)) {
|
||||||
fade.voxelDetails = rootDetails;
|
VoxelFade fade(VoxelFade::FADE_OUT, NODE_ADDED_RED, NODE_ADDED_GREEN, NODE_ADDED_BLUE);
|
||||||
const float slightly_smaller = 0.99;
|
fade.voxelDetails = rootDetails;
|
||||||
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
const float slightly_smaller = 0.99;
|
||||||
_voxelFades.push_back(fade);
|
fade.voxelDetails.s = fade.voxelDetails.s * slightly_smaller;
|
||||||
|
_voxelFades.push_back(fade);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// store jurisdiction details for later use
|
// store jurisdiction details for later use
|
||||||
// This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it
|
// This is bit of fiddling is because JurisdictionMap assumes it is the owner of the values used to construct it
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
|
@ -282,6 +283,7 @@ Menu::Menu() :
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
||||||
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges);
|
||||||
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
|
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
|
||||||
|
|
||||||
QMenu* cullingOptionsMenu = voxelOptionsMenu->addMenu("Culling Options");
|
QMenu* cullingOptionsMenu = voxelOptionsMenu->addMenu("Culling Options");
|
||||||
|
@ -718,16 +720,13 @@ void Menu::aboutApp() {
|
||||||
InfoView::forcedShow();
|
InfoView::forcedShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateDSHostname(const QString& domainServerHostname) {
|
void sendFakeEnterEvent() {
|
||||||
QString newHostname(DEFAULT_DOMAIN_HOSTNAME);
|
QPoint lastCursorPosition = QCursor::pos();
|
||||||
|
QGLWidget* glWidget = Application::getInstance()->getGLWidget();
|
||||||
|
|
||||||
if (domainServerHostname.size() > 0) {
|
QPoint windowPosition = glWidget->mapFromGlobal(lastCursorPosition);
|
||||||
// the user input a new hostname, use that
|
QEnterEvent enterEvent = QEnterEvent(windowPosition, windowPosition, lastCursorPosition);
|
||||||
newHostname = domainServerHostname;
|
QCoreApplication::sendEvent(glWidget, &enterEvent);
|
||||||
}
|
|
||||||
|
|
||||||
// give our nodeList the new domain-server hostname
|
|
||||||
NodeList::getInstance()->setDomainHostname(newHostname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int QLINE_MINIMUM_WIDTH = 400;
|
const int QLINE_MINIMUM_WIDTH = 400;
|
||||||
|
@ -743,11 +742,15 @@ void Menu::login() {
|
||||||
loginDialog.resize(loginDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, loginDialog.size().height());
|
loginDialog.resize(loginDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, loginDialog.size().height());
|
||||||
|
|
||||||
int dialogReturn = loginDialog.exec();
|
int dialogReturn = loginDialog.exec();
|
||||||
|
|
||||||
if (dialogReturn == QDialog::Accepted && !loginDialog.textValue().isEmpty() && loginDialog.textValue() != username) {
|
if (dialogReturn == QDialog::Accepted && !loginDialog.textValue().isEmpty() && loginDialog.textValue() != username) {
|
||||||
// there has been a username change
|
// there has been a username change
|
||||||
// ask for a profile reset with the new username
|
// ask for a profile reset with the new username
|
||||||
Application::getInstance()->resetProfile(loginDialog.textValue());
|
Application::getInstance()->resetProfile(loginDialog.textValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::editPreferences() {
|
void Menu::editPreferences() {
|
||||||
|
@ -811,52 +814,52 @@ void Menu::editPreferences() {
|
||||||
layout->addWidget(buttons);
|
layout->addWidget(buttons);
|
||||||
|
|
||||||
int ret = dialog.exec();
|
int ret = dialog.exec();
|
||||||
if (ret != QDialog::Accepted) {
|
if (ret == QDialog::Accepted) {
|
||||||
return;
|
QUrl faceModelURL(faceURLEdit->text());
|
||||||
}
|
|
||||||
|
|
||||||
QUrl faceModelURL(faceURLEdit->text());
|
|
||||||
|
|
||||||
if (faceModelURL.toString() != faceURLString) {
|
|
||||||
// change the faceModelURL in the profile, it will also update this user's BlendFace
|
|
||||||
applicationInstance->getProfile()->setFaceModelURL(faceModelURL);
|
|
||||||
|
|
||||||
// send the new face mesh URL to the data-server (if we have a client UUID)
|
if (faceModelURL.toString() != faceURLString) {
|
||||||
DataServerClient::putValueForKey(DataServerKey::FaceMeshURL,
|
// change the faceModelURL in the profile, it will also update this user's BlendFace
|
||||||
faceModelURL.toString().toLocal8Bit().constData());
|
applicationInstance->getProfile()->setFaceModelURL(faceModelURL);
|
||||||
}
|
|
||||||
|
// send the new face mesh URL to the data-server (if we have a client UUID)
|
||||||
QUrl skeletonModelURL(skeletonURLEdit->text());
|
DataServerClient::putValueForKey(DataServerKey::FaceMeshURL,
|
||||||
|
faceModelURL.toString().toLocal8Bit().constData());
|
||||||
if (skeletonModelURL.toString() != skeletonURLString) {
|
}
|
||||||
// change the skeletonModelURL in the profile, it will also update this user's Body
|
|
||||||
applicationInstance->getProfile()->setSkeletonModelURL(skeletonModelURL);
|
|
||||||
|
|
||||||
// send the new skeleton model URL to the data-server (if we have a client UUID)
|
QUrl skeletonModelURL(skeletonURLEdit->text());
|
||||||
DataServerClient::putValueForKey(DataServerKey::SkeletonURL,
|
|
||||||
skeletonModelURL.toString().toLocal8Bit().constData());
|
if (skeletonModelURL.toString() != skeletonURLString) {
|
||||||
|
// change the skeletonModelURL in the profile, it will also update this user's Body
|
||||||
|
applicationInstance->getProfile()->setSkeletonModelURL(skeletonModelURL);
|
||||||
|
|
||||||
|
// send the new skeleton model URL to the data-server (if we have a client UUID)
|
||||||
|
DataServerClient::putValueForKey(DataServerKey::SkeletonURL,
|
||||||
|
skeletonModelURL.toString().toLocal8Bit().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl avatarVoxelURL(avatarURL->text());
|
||||||
|
applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL);
|
||||||
|
|
||||||
|
Avatar::sendAvatarURLsMessage(avatarVoxelURL);
|
||||||
|
|
||||||
|
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
|
||||||
|
|
||||||
|
_maxVoxels = maxVoxels->value();
|
||||||
|
applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels);
|
||||||
|
|
||||||
|
applicationInstance->getAvatar()->setLeanScale(leanScale->value());
|
||||||
|
|
||||||
|
_audioJitterBufferSamples = audioJitterBufferSamples->value();
|
||||||
|
|
||||||
|
if (_audioJitterBufferSamples != 0) {
|
||||||
|
applicationInstance->getAudio()->setJitterBufferSamples(_audioJitterBufferSamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fieldOfView = fieldOfView->value();
|
||||||
|
applicationInstance->resizeGL(applicationInstance->getGLWidget()->width(), applicationInstance->getGLWidget()->height());
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl avatarVoxelURL(avatarURL->text());
|
sendFakeEnterEvent();
|
||||||
applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL);
|
|
||||||
|
|
||||||
Avatar::sendAvatarURLsMessage(avatarVoxelURL);
|
|
||||||
|
|
||||||
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
|
|
||||||
|
|
||||||
_maxVoxels = maxVoxels->value();
|
|
||||||
applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels);
|
|
||||||
|
|
||||||
applicationInstance->getAvatar()->setLeanScale(leanScale->value());
|
|
||||||
|
|
||||||
_audioJitterBufferSamples = audioJitterBufferSamples->value();
|
|
||||||
|
|
||||||
if (_audioJitterBufferSamples != 0) {
|
|
||||||
applicationInstance->getAudio()->setJitterBufferSamples(_audioJitterBufferSamples);
|
|
||||||
}
|
|
||||||
|
|
||||||
_fieldOfView = fieldOfView->value();
|
|
||||||
applicationInstance->resizeGL(applicationInstance->getGLWidget()->width(), applicationInstance->getGLWidget()->height());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goToDomain() {
|
void Menu::goToDomain() {
|
||||||
|
@ -876,9 +879,19 @@ void Menu::goToDomain() {
|
||||||
domainDialog.resize(domainDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, domainDialog.size().height());
|
domainDialog.resize(domainDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, domainDialog.size().height());
|
||||||
|
|
||||||
int dialogReturn = domainDialog.exec();
|
int dialogReturn = domainDialog.exec();
|
||||||
if (dialogReturn == QDialog::Accepted && !domainDialog.textValue().isEmpty()) {
|
if (dialogReturn == QDialog::Accepted) {
|
||||||
updateDSHostname(domainDialog.textValue());
|
QString newHostname(DEFAULT_DOMAIN_HOSTNAME);
|
||||||
|
|
||||||
|
if (domainDialog.textValue().size() > 0) {
|
||||||
|
// the user input a new hostname, use that
|
||||||
|
newHostname = domainDialog.textValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// give our nodeList the new domain-server hostname
|
||||||
|
NodeList::getInstance()->setDomainHostname(domainDialog.textValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goToLocation() {
|
void Menu::goToLocation() {
|
||||||
|
@ -918,6 +931,8 @@ void Menu::goToLocation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goToUser() {
|
void Menu::goToUser() {
|
||||||
|
@ -935,6 +950,8 @@ void Menu::goToUser() {
|
||||||
DataServerClient::getValuesForKeysAndUserString((QStringList() << DataServerKey::Domain << DataServerKey::Position),
|
DataServerClient::getValuesForKeysAndUserString((QStringList() << DataServerKey::Domain << DataServerKey::Position),
|
||||||
userDialog.textValue());
|
userDialog.textValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::bandwidthDetails() {
|
void Menu::bandwidthDetails() {
|
||||||
|
|
|
@ -165,6 +165,7 @@ namespace MenuOption {
|
||||||
const QString EchoAudio = "Echo Audio";
|
const QString EchoAudio = "Echo Audio";
|
||||||
const QString ExportVoxels = "Export Voxels";
|
const QString ExportVoxels = "Export Voxels";
|
||||||
const QString ExtraDebugging = "Extra Debugging";
|
const QString ExtraDebugging = "Extra Debugging";
|
||||||
|
const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes";
|
||||||
const QString HeadMouse = "Head Mouse";
|
const QString HeadMouse = "Head Mouse";
|
||||||
const QString FaceMode = "Cycle Face Mode";
|
const QString FaceMode = "Cycle Face Mode";
|
||||||
const QString FaceshiftTCP = "Faceshift (TCP)";
|
const QString FaceshiftTCP = "Faceshift (TCP)";
|
||||||
|
|
|
@ -2645,23 +2645,8 @@ bool VoxelSystem::killSourceVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||||
void VoxelSystem::nodeKilled(Node* node) {
|
void VoxelSystem::nodeKilled(Node* node) {
|
||||||
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
|
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
|
||||||
_voxelServerCount--;
|
_voxelServerCount--;
|
||||||
|
|
||||||
QUuid nodeUUID = node->getUUID();
|
QUuid nodeUUID = node->getUUID();
|
||||||
|
|
||||||
qDebug("VoxelSystem... voxel server %s removed...\n", nodeUUID.toString().toLocal8Bit().constData());
|
qDebug("VoxelSystem... voxel server %s removed...\n", nodeUUID.toString().toLocal8Bit().constData());
|
||||||
|
|
||||||
if (_voxelServerCount > 0) {
|
|
||||||
// Kill any voxels from the local tree that match this nodeID
|
|
||||||
// commenting out for removal of 16 bit node IDs
|
|
||||||
lockTree();
|
|
||||||
_tree->recurseTreeWithOperation(killSourceVoxelsOperation, &nodeUUID);
|
|
||||||
unlockTree();
|
|
||||||
_tree->setDirtyBit();
|
|
||||||
setupNewVoxelsForDrawing();
|
|
||||||
} else {
|
|
||||||
// Last server, take the easy way and kill all the local voxels!
|
|
||||||
killLocalVoxels();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,11 @@ Avatar::~Avatar() {
|
||||||
delete _balls;
|
delete _balls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::deleteOrDeleteLater() {
|
||||||
|
this->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Avatar::init() {
|
void Avatar::init() {
|
||||||
_head.init();
|
_head.init();
|
||||||
_hand.init();
|
_hand.init();
|
||||||
|
|
|
@ -134,6 +134,7 @@ public:
|
||||||
|
|
||||||
Avatar(Node* owningNode = NULL);
|
Avatar(Node* owningNode = NULL);
|
||||||
~Avatar();
|
~Avatar();
|
||||||
|
void deleteOrDeleteLater();
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void simulate(float deltaTime, Transmitter* transmitter);
|
void simulate(float deltaTime, Transmitter* transmitter);
|
||||||
|
|
|
@ -44,7 +44,7 @@ Node::~Node() {
|
||||||
delete _localSocket;
|
delete _localSocket;
|
||||||
|
|
||||||
if (_linkedData) {
|
if (_linkedData) {
|
||||||
_linkedData->deleteLater();
|
_linkedData->deleteOrDeleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _bytesReceivedMovingAverage;
|
delete _bytesReceivedMovingAverage;
|
||||||
|
|
|
@ -16,4 +16,8 @@ NodeData::NodeData(Node* owningNode) :
|
||||||
|
|
||||||
NodeData::~NodeData() {
|
NodeData::~NodeData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeData::deleteOrDeleteLater() {
|
||||||
|
delete this;
|
||||||
}
|
}
|
|
@ -21,6 +21,8 @@ public:
|
||||||
virtual ~NodeData() = 0;
|
virtual ~NodeData() = 0;
|
||||||
virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0;
|
virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0;
|
||||||
|
|
||||||
|
virtual void deleteOrDeleteLater();
|
||||||
|
|
||||||
Node* getOwningNode() { return _owningNode; }
|
Node* getOwningNode() { return _owningNode; }
|
||||||
protected:
|
protected:
|
||||||
Node* _owningNode;
|
Node* _owningNode;
|
||||||
|
|
|
@ -35,6 +35,8 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
|
||||||
_lastVoxelPacketLength = 0;
|
_lastVoxelPacketLength = 0;
|
||||||
_duplicatePacketCount = 0;
|
_duplicatePacketCount = 0;
|
||||||
resetVoxelPacket();
|
resetVoxelPacket();
|
||||||
|
|
||||||
|
qDebug("VoxelNodeData::VoxelNodeData() this=%p owningNode=%p\n", this, owningNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
|
void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
|
||||||
|
@ -42,6 +44,10 @@ void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) {
|
||||||
QUuid nodeUUID = getOwningNode()->getUUID();
|
QUuid nodeUUID = getOwningNode()->getUUID();
|
||||||
_voxelSendThread = new VoxelSendThread(nodeUUID, voxelServer);
|
_voxelSendThread = new VoxelSendThread(nodeUUID, voxelServer);
|
||||||
_voxelSendThread->initialize(true);
|
_voxelSendThread->initialize(true);
|
||||||
|
|
||||||
|
qDebug("VoxelNodeData::initializeVoxelSendThread() this=%p owningNode=%p _voxelSendThread=%p\n",
|
||||||
|
this, getOwningNode(), _voxelSendThread);
|
||||||
|
qDebug() << "VoxelNodeData::initializeVoxelSendThread() nodeUUID=" << nodeUUID << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelNodeData::packetIsDuplicate() const {
|
bool VoxelNodeData::packetIsDuplicate() const {
|
||||||
|
@ -111,12 +117,19 @@ void VoxelNodeData::writeToPacket(unsigned char* buffer, int bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelNodeData::~VoxelNodeData() {
|
VoxelNodeData::~VoxelNodeData() {
|
||||||
|
|
||||||
|
qDebug("VoxelNodeData::~VoxelNodeData() this=%p owningNode=%p _voxelSendThread=%p\n",
|
||||||
|
this, getOwningNode(), _voxelSendThread);
|
||||||
|
QUuid nodeUUID = getOwningNode()->getUUID();
|
||||||
|
qDebug() << "VoxelNodeData::~VoxelNodeData() nodeUUID=" << nodeUUID << "\n";
|
||||||
|
|
||||||
delete[] _voxelPacket;
|
delete[] _voxelPacket;
|
||||||
delete[] _lastVoxelPacket;
|
delete[] _lastVoxelPacket;
|
||||||
|
|
||||||
if (_voxelSendThread) {
|
if (_voxelSendThread) {
|
||||||
_voxelSendThread->terminate();
|
_voxelSendThread->terminate();
|
||||||
delete _voxelSendThread;
|
delete _voxelSendThread;
|
||||||
|
qDebug("VoxelNodeData::~VoxelNodeData() DELETED _voxelSendThread=%p\n", _voxelSendThread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class VoxelServer;
|
||||||
class VoxelNodeData : public VoxelQuery {
|
class VoxelNodeData : public VoxelQuery {
|
||||||
public:
|
public:
|
||||||
VoxelNodeData(Node* owningNode);
|
VoxelNodeData(Node* owningNode);
|
||||||
~VoxelNodeData();
|
virtual ~VoxelNodeData();
|
||||||
|
|
||||||
void resetVoxelPacket(); // resets voxel packet to after "V" header
|
void resetVoxelPacket(); // resets voxel packet to after "V" header
|
||||||
|
|
||||||
|
|
|
@ -20,30 +20,28 @@ VoxelPersistThread::VoxelPersistThread(VoxelTree* tree, const char* filename, in
|
||||||
_tree(tree),
|
_tree(tree),
|
||||||
_filename(filename),
|
_filename(filename),
|
||||||
_persistInterval(persistInterval),
|
_persistInterval(persistInterval),
|
||||||
_initialLoad(false) {
|
_initialLoadComplete(false),
|
||||||
|
_loadTimeUSecs(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelPersistThread::process() {
|
bool VoxelPersistThread::process() {
|
||||||
|
|
||||||
if (!_initialLoad) {
|
if (!_initialLoadComplete) {
|
||||||
_initialLoad = true;
|
uint64_t loadStarted = usecTimestampNow();
|
||||||
qDebug("loading voxels from file: %s...\n", _filename);
|
qDebug("loading voxels from file: %s...\n", _filename);
|
||||||
|
|
||||||
bool persistantFileRead;
|
bool persistantFileRead;
|
||||||
|
|
||||||
|
_tree->lockForWrite();
|
||||||
{
|
{
|
||||||
PerformanceWarning warn(true, "Loading Voxel File", true);
|
PerformanceWarning warn(true, "Loading Voxel File", true);
|
||||||
persistantFileRead = _tree->readFromSVOFile(_filename);
|
persistantFileRead = _tree->readFromSVOFile(_filename);
|
||||||
}
|
}
|
||||||
|
_tree->unlock();
|
||||||
|
|
||||||
if (persistantFileRead) {
|
_loadCompleted = time(0);
|
||||||
PerformanceWarning warn(true, "Voxels Re-Averaging", true);
|
uint64_t loadDone = usecTimestampNow();
|
||||||
|
_loadTimeUSecs = loadDone - loadStarted;
|
||||||
// after done inserting all these voxels, then reaverage colors
|
|
||||||
qDebug("BEGIN Voxels Re-Averaging\n");
|
|
||||||
_tree->reaverageVoxelColors(_tree->rootNode);
|
|
||||||
qDebug("DONE WITH Voxels Re-Averaging\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
_tree->clearDirtyBit(); // the tree is clean since we just loaded it
|
_tree->clearDirtyBit(); // the tree is clean since we just loaded it
|
||||||
qDebug("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead));
|
qDebug("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead));
|
||||||
|
@ -61,6 +59,7 @@ bool VoxelPersistThread::process() {
|
||||||
qDebug("setChildAtIndexCalls=%llu setChildAtIndexTime=%llu perSet=%lf\n",
|
qDebug("setChildAtIndexCalls=%llu setChildAtIndexTime=%llu perSet=%lf\n",
|
||||||
VoxelNode::getSetChildAtIndexTime(), VoxelNode::getSetChildAtIndexCalls(), usecPerSet);
|
VoxelNode::getSetChildAtIndexTime(), VoxelNode::getSetChildAtIndexCalls(), usecPerSet);
|
||||||
|
|
||||||
|
_initialLoadComplete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t MSECS_TO_USECS = 1000;
|
uint64_t MSECS_TO_USECS = 1000;
|
||||||
|
|
|
@ -21,6 +21,12 @@ public:
|
||||||
static const int DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
static const int DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
||||||
|
|
||||||
VoxelPersistThread(VoxelTree* tree, const char* filename, int persistInterval = DEFAULT_PERSIST_INTERVAL);
|
VoxelPersistThread(VoxelTree* tree, const char* filename, int persistInterval = DEFAULT_PERSIST_INTERVAL);
|
||||||
|
|
||||||
|
bool isInitialLoadComplete() const { return _initialLoadComplete; }
|
||||||
|
|
||||||
|
time_t* getLoadCompleted() { return &_loadCompleted; }
|
||||||
|
uint64_t getLoadElapsedTime() const { return _loadTimeUSecs; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Implements generic processing behavior for this thread.
|
/// Implements generic processing behavior for this thread.
|
||||||
virtual bool process();
|
virtual bool process();
|
||||||
|
@ -28,7 +34,10 @@ private:
|
||||||
VoxelTree* _tree;
|
VoxelTree* _tree;
|
||||||
const char* _filename;
|
const char* _filename;
|
||||||
int _persistInterval;
|
int _persistInterval;
|
||||||
bool _initialLoad;
|
bool _initialLoadComplete;
|
||||||
|
|
||||||
|
time_t _loadCompleted;
|
||||||
|
uint64_t _loadTimeUSecs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __voxel_server__VoxelPersistThread__
|
#endif // __voxel_server__VoxelPersistThread__
|
||||||
|
|
|
@ -26,28 +26,39 @@ VoxelSendThread::VoxelSendThread(const QUuid& nodeUUID, VoxelServer* myServer) :
|
||||||
bool VoxelSendThread::process() {
|
bool VoxelSendThread::process() {
|
||||||
uint64_t start = usecTimestampNow();
|
uint64_t start = usecTimestampNow();
|
||||||
|
|
||||||
Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
|
// don't do any send processing until the initial load of the voxels is complete...
|
||||||
VoxelNodeData* nodeData = NULL;
|
if (_myServer->isInitialLoadComplete()) {
|
||||||
|
Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
nodeData = (VoxelNodeData*) node->getLinkedData();
|
node->lock(); // make sure the node list doesn't kill our node while we're using it
|
||||||
}
|
VoxelNodeData* nodeData = NULL;
|
||||||
|
|
||||||
int packetsSent = 0;
|
nodeData = (VoxelNodeData*) node->getLinkedData();
|
||||||
|
|
||||||
|
int packetsSent = 0;
|
||||||
|
|
||||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||||
if (nodeData) {
|
if (nodeData) {
|
||||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||||
if (_myServer->wantsDebugVoxelSending()) {
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||||
}
|
}
|
||||||
packetsSent = deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
packetsSent = deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->unlock(); // we're done with this node for now.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_myServer->wantsDebugVoxelSending()) {
|
||||||
|
qDebug("VoxelSendThread::process() waiting for isInitialLoadComplete()\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// dynamically sleep until we need to fire off the next set of voxels
|
// dynamically sleep until we need to fire off the next set of voxels
|
||||||
int elapsed = (usecTimestampNow() - start);
|
int elapsed = (usecTimestampNow() - start);
|
||||||
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - elapsed;
|
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - elapsed;
|
||||||
|
|
||||||
if (usecToSleep > 0) {
|
if (usecToSleep > 0) {
|
||||||
usleep(usecToSleep);
|
usleep(usecToSleep);
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,6 +66,7 @@ bool VoxelSendThread::process() {
|
||||||
std::cout << "Last send took too much time, not sleeping!\n";
|
std::cout << "Last send took too much time, not sleeping!\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isStillRunning(); // keep running till they terminate us
|
return isStillRunning(); // keep running till they terminate us
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,8 +124,6 @@ int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
||||||
/// Version of voxel distributor that sends the deepest LOD level at once
|
/// Version of voxel distributor that sends the deepest LOD level at once
|
||||||
int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
||||||
|
|
||||||
_myServer->lockTree();
|
|
||||||
|
|
||||||
int truePacketsSent = 0;
|
int truePacketsSent = 0;
|
||||||
int trueBytesSent = 0;
|
int trueBytesSent = 0;
|
||||||
int packetsSentThisInterval = 0;
|
int packetsSentThisInterval = 0;
|
||||||
|
@ -284,10 +294,13 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
|
||||||
nodeData->getLastTimeBagEmpty(),
|
nodeData->getLastTimeBagEmpty(),
|
||||||
isFullScene, &nodeData->stats, _myServer->getJurisdiction());
|
isFullScene, &nodeData->stats, _myServer->getJurisdiction());
|
||||||
|
|
||||||
|
|
||||||
|
_myServer->getServerTree().lockForRead();
|
||||||
nodeData->stats.encodeStarted();
|
nodeData->stats.encodeStarted();
|
||||||
bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, _tempOutputBuffer, MAX_VOXEL_PACKET_SIZE - 1,
|
bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, _tempOutputBuffer, MAX_VOXEL_PACKET_SIZE - 1,
|
||||||
nodeData->nodeBag, params);
|
nodeData->nodeBag, params);
|
||||||
nodeData->stats.encodeStopped();
|
nodeData->stats.encodeStopped();
|
||||||
|
_myServer->getServerTree().unlock();
|
||||||
|
|
||||||
if (nodeData->getAvailable() >= bytesWritten) {
|
if (nodeData->getAvailable() >= bytesWritten) {
|
||||||
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
||||||
|
@ -355,8 +368,6 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
|
||||||
|
|
||||||
} // end if bag wasn't empty, and so we sent stuff...
|
} // end if bag wasn't empty, and so we sent stuff...
|
||||||
|
|
||||||
_myServer->unlockTree();
|
|
||||||
|
|
||||||
return truePacketsSent;
|
return truePacketsSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,11 @@ const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxe
|
||||||
|
|
||||||
void attachVoxelNodeDataToNode(Node* newNode) {
|
void attachVoxelNodeDataToNode(Node* newNode) {
|
||||||
if (newNode->getLinkedData() == NULL) {
|
if (newNode->getLinkedData() == NULL) {
|
||||||
newNode->setLinkedData(new VoxelNodeData(newNode));
|
VoxelNodeData* voxelNodeData = new VoxelNodeData(newNode);
|
||||||
|
QUuid nodeUUID = newNode->getUUID();
|
||||||
|
qDebug("attachVoxelNodeDataToNode() newNode=%p voxelNodeData=%p\n", newNode, voxelNodeData);
|
||||||
|
qDebug() << "attachVoxelNodeDataToNode() node UUID:" << nodeUUID << "\n";
|
||||||
|
newNode->setLinkedData(voxelNodeData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +175,47 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
||||||
mg_printf(connection, "%s", "\r\n");
|
mg_printf(connection, "%s", "\r\n");
|
||||||
mg_printf(connection, "%s", "\r\n");
|
mg_printf(connection, "%s", "\r\n");
|
||||||
|
|
||||||
|
|
||||||
|
// display voxel file load time
|
||||||
|
if (GetInstance()->isInitialLoadComplete()) {
|
||||||
|
tm* voxelsLoadedAtLocal = localtime(GetInstance()->getLoadCompleted());
|
||||||
|
const int MAX_TIME_LENGTH = 128;
|
||||||
|
char buffer[MAX_TIME_LENGTH];
|
||||||
|
strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtLocal);
|
||||||
|
mg_printf(connection, "Voxels Loaded At: %s", buffer);
|
||||||
|
|
||||||
|
// Convert now to tm struct for UTC
|
||||||
|
tm* voxelsLoadedAtUTM = gmtime(GetInstance()->getLoadCompleted());
|
||||||
|
if (gmtm != NULL) {
|
||||||
|
strftime(buffer, MAX_TIME_LENGTH, "%m/%d/%Y %X", voxelsLoadedAtUTM);
|
||||||
|
mg_printf(connection, " [%s UTM] ", buffer);
|
||||||
|
}
|
||||||
|
mg_printf(connection, "%s", "\r\n");
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t msecsElapsed = GetInstance()->getLoadElapsedTime() / USECS_PER_MSEC;;
|
||||||
|
float seconds = (msecsElapsed % MSECS_PER_MIN)/(float)MSECS_PER_SEC;
|
||||||
|
int minutes = (msecsElapsed/(MSECS_PER_MIN)) % MIN_PER_HOUR;
|
||||||
|
int hours = (msecsElapsed/(MSECS_PER_MIN * MIN_PER_HOUR));
|
||||||
|
|
||||||
|
mg_printf(connection, "%s", "Voxels Load Took: ");
|
||||||
|
if (hours > 0) {
|
||||||
|
mg_printf(connection, "%d hour%s ", hours, (hours > 1) ? "s" : "" );
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
mg_printf(connection, "%d minute%s ", minutes, (minutes > 1) ? "s" : "");
|
||||||
|
}
|
||||||
|
if (seconds > 0) {
|
||||||
|
mg_printf(connection, "%.3f seconds", seconds);
|
||||||
|
}
|
||||||
|
mg_printf(connection, "%s", "\r\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mg_printf(connection, "%s", "Voxels not yet loaded...\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_printf(connection, "%s", "\r\n");
|
||||||
|
|
||||||
mg_printf(connection, "%s", "\r\n");
|
mg_printf(connection, "%s", "\r\n");
|
||||||
mg_printf(connection, "%s", "Configuration: \r\n ");
|
mg_printf(connection, "%s", "Configuration: \r\n ");
|
||||||
for (int i = 1; i < GetInstance()->_argc; i++) {
|
for (int i = 1; i < GetInstance()->_argc; i++) {
|
||||||
|
@ -339,8 +384,6 @@ void VoxelServer::run() {
|
||||||
parsePayload();
|
parsePayload();
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_init(&_treeLock, NULL);
|
|
||||||
|
|
||||||
qInstallMessageHandler(Logging::verboseMessageHandler);
|
qInstallMessageHandler(Logging::verboseMessageHandler);
|
||||||
|
|
||||||
const char* STATUS_PORT = "--statusPort";
|
const char* STATUS_PORT = "--statusPort";
|
||||||
|
@ -510,8 +553,8 @@ void VoxelServer::run() {
|
||||||
|
|
||||||
// loop to send to nodes requesting data
|
// loop to send to nodes requesting data
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||||
|
qDebug() << "Exit loop... getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,28 +610,39 @@ void VoxelServer::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
qDebug() << "VoxelServer::run()... AFTER loop...\n";
|
||||||
|
|
||||||
delete _jurisdiction;
|
// call NodeList::clear() so that all of our node specific objects, including our sending threads, are
|
||||||
|
// properly shutdown and cleaned up.
|
||||||
|
NodeList::getInstance()->clear();
|
||||||
|
|
||||||
|
qDebug() << "VoxelServer::run()... terminating _jurisdictionSender\n";
|
||||||
if (_jurisdictionSender) {
|
if (_jurisdictionSender) {
|
||||||
_jurisdictionSender->terminate();
|
_jurisdictionSender->terminate();
|
||||||
delete _jurisdictionSender;
|
delete _jurisdictionSender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << "VoxelServer::run()... terminating _voxelServerPacketProcessor\n";
|
||||||
if (_voxelServerPacketProcessor) {
|
if (_voxelServerPacketProcessor) {
|
||||||
_voxelServerPacketProcessor->terminate();
|
_voxelServerPacketProcessor->terminate();
|
||||||
delete _voxelServerPacketProcessor;
|
delete _voxelServerPacketProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << "VoxelServer::run()... terminating _voxelPersistThread\n";
|
||||||
if (_voxelPersistThread) {
|
if (_voxelPersistThread) {
|
||||||
_voxelPersistThread->terminate();
|
_voxelPersistThread->terminate();
|
||||||
delete _voxelPersistThread;
|
delete _voxelPersistThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell our NodeList we're done with notifications
|
// tell our NodeList we're done with notifications
|
||||||
|
qDebug() << "VoxelServer::run()... nodeList->removeHook(&_nodeWatcher)\n";
|
||||||
nodeList->removeHook(&_nodeWatcher);
|
nodeList->removeHook(&_nodeWatcher);
|
||||||
|
|
||||||
pthread_mutex_destroy(&_treeLock);
|
qDebug() << "VoxelServer::run()... deleting _jurisdiction\n";
|
||||||
|
delete _jurisdiction;
|
||||||
|
_jurisdiction = NULL;
|
||||||
|
|
||||||
|
qDebug() << "VoxelServer::run()... DONE\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,6 @@ public:
|
||||||
VoxelTree& getServerTree() { return _serverTree; }
|
VoxelTree& getServerTree() { return _serverTree; }
|
||||||
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
|
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
|
||||||
|
|
||||||
void lockTree() { pthread_mutex_lock(&_treeLock); }
|
|
||||||
void unlockTree() { pthread_mutex_unlock(&_treeLock); }
|
|
||||||
VoxelTree* getTree() { return &_serverTree; }
|
|
||||||
|
|
||||||
int getPacketsPerClientPerInterval() const { return _packetsPerClientPerInterval; }
|
int getPacketsPerClientPerInterval() const { return _packetsPerClientPerInterval; }
|
||||||
bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; }
|
bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; }
|
||||||
EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; }
|
EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; }
|
||||||
|
@ -59,6 +55,10 @@ public:
|
||||||
|
|
||||||
static VoxelServer* GetInstance() { return _theInstance; }
|
static VoxelServer* GetInstance() { return _theInstance; }
|
||||||
|
|
||||||
|
bool isInitialLoadComplete() const { return (_voxelPersistThread) ? _voxelPersistThread->isInitialLoadComplete() : true; }
|
||||||
|
time_t* getLoadCompleted() { return (_voxelPersistThread) ? _voxelPersistThread->getLoadCompleted() : NULL; }
|
||||||
|
uint64_t getLoadElapsedTime() const { return (_voxelPersistThread) ? _voxelPersistThread->getLoadElapsedTime() : 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _argc;
|
int _argc;
|
||||||
const char** _argv;
|
const char** _argv;
|
||||||
|
@ -80,7 +80,6 @@ private:
|
||||||
JurisdictionSender* _jurisdictionSender;
|
JurisdictionSender* _jurisdictionSender;
|
||||||
VoxelServerPacketProcessor* _voxelServerPacketProcessor;
|
VoxelServerPacketProcessor* _voxelServerPacketProcessor;
|
||||||
VoxelPersistThread* _voxelPersistThread;
|
VoxelPersistThread* _voxelPersistThread;
|
||||||
pthread_mutex_t _treeLock;
|
|
||||||
EnvironmentData _environmentData[3];
|
EnvironmentData _environmentData[3];
|
||||||
|
|
||||||
NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed
|
NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed
|
||||||
|
|
|
@ -85,10 +85,10 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
|
||||||
printf("inserting voxel: %f,%f,%f r=%d,g=%d,b=%d\n", vertices[0], vertices[1], vertices[2], red, green, blue);
|
printf("inserting voxel: %f,%f,%f r=%d,g=%d,b=%d\n", vertices[0], vertices[1], vertices[2], red, green, blue);
|
||||||
delete[] vertices;
|
delete[] vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
_myServer->lockTree();
|
_myServer->getServerTree().lockForWrite();
|
||||||
_myServer->getServerTree().readCodeColorBufferToTree(voxelData, destructive);
|
_myServer->getServerTree().readCodeColorBufferToTree(voxelData, destructive);
|
||||||
_myServer->unlockTree();
|
_myServer->getServerTree().unlock();
|
||||||
|
|
||||||
// skip to next voxel edit record in the packet
|
// skip to next voxel edit record in the packet
|
||||||
voxelData += voxelDataSize;
|
voxelData += voxelDataSize;
|
||||||
|
@ -114,9 +114,9 @@ void VoxelServerPacketProcessor::processPacket(sockaddr& senderAddress, unsigned
|
||||||
} else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) {
|
} else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) {
|
||||||
|
|
||||||
// Send these bits off to the VoxelTree class to process them
|
// Send these bits off to the VoxelTree class to process them
|
||||||
_myServer->lockTree();
|
_myServer->getServerTree().lockForWrite();
|
||||||
_myServer->getServerTree().processRemoveVoxelBitstream((unsigned char*)packetData, packetLength);
|
_myServer->getServerTree().processRemoveVoxelBitstream((unsigned char*)packetData, packetLength);
|
||||||
_myServer->unlockTree();
|
_myServer->getServerTree().unlock();
|
||||||
|
|
||||||
// Make sure our Node and NodeList knows we've heard from this node.
|
// Make sure our Node and NodeList knows we've heard from this node.
|
||||||
Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress);
|
Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress);
|
||||||
|
|
|
@ -109,8 +109,47 @@ JurisdictionMap::JurisdictionMap(unsigned char* rootOctalCode, const std::vector
|
||||||
init(rootOctalCode, endNodes);
|
init(rootOctalCode, endNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void myDebugoutputBits(unsigned char byte, bool withNewLine) {
|
||||||
|
if (isalnum(byte)) {
|
||||||
|
printf("[ %d (%c): ", byte, byte);
|
||||||
|
} else {
|
||||||
|
printf("[ %d (0x%x): ", byte, byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
printf("%d", byte >> (7 - i) & 1);
|
||||||
|
}
|
||||||
|
printf(" ] ");
|
||||||
|
|
||||||
|
if (withNewLine) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void myDebugPrintOctalCode(const unsigned char* octalCode, bool withNewLine) {
|
||||||
|
if (!octalCode) {
|
||||||
|
printf("NULL");
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(octalCode)); i++) {
|
||||||
|
myDebugoutputBits(octalCode[i],false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (withNewLine) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHexCodes) {
|
JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHexCodes) {
|
||||||
|
|
||||||
|
qDebug("JurisdictionMap::JurisdictionMap(const char* rootHexCode=[%p] %s, const char* endNodesHexCodes=[%p] %s)\n",
|
||||||
|
rootHexCode, rootHexCode, endNodesHexCodes, endNodesHexCodes);
|
||||||
|
|
||||||
_rootOctalCode = hexStringToOctalCode(QString(rootHexCode));
|
_rootOctalCode = hexStringToOctalCode(QString(rootHexCode));
|
||||||
|
|
||||||
|
qDebug("JurisdictionMap::JurisdictionMap() _rootOctalCode=%p octalCode=", _rootOctalCode);
|
||||||
|
myDebugPrintOctalCode(_rootOctalCode, true);
|
||||||
|
|
||||||
QString endNodesHexStrings(endNodesHexCodes);
|
QString endNodesHexStrings(endNodesHexCodes);
|
||||||
QString delimiterPattern(",");
|
QString delimiterPattern(",");
|
||||||
|
@ -120,8 +159,16 @@ JurisdictionMap::JurisdictionMap(const char* rootHexCode, const char* endNodesHe
|
||||||
QString endNodeHexString = endNodeList.at(i);
|
QString endNodeHexString = endNodeList.at(i);
|
||||||
|
|
||||||
unsigned char* endNodeOctcode = hexStringToOctalCode(endNodeHexString);
|
unsigned char* endNodeOctcode = hexStringToOctalCode(endNodeHexString);
|
||||||
|
|
||||||
|
qDebug("JurisdictionMap::JurisdictionMap() endNodeList(%d)=%s\n",
|
||||||
|
i, endNodeHexString.toLocal8Bit().constData());
|
||||||
|
|
||||||
//printOctalCode(endNodeOctcode);
|
//printOctalCode(endNodeOctcode);
|
||||||
_endNodes.push_back(endNodeOctcode);
|
_endNodes.push_back(endNodeOctcode);
|
||||||
|
|
||||||
|
qDebug("JurisdictionMap::JurisdictionMap() endNodeOctcode=%p octalCode=", endNodeOctcode);
|
||||||
|
myDebugPrintOctalCode(endNodeOctcode, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ VoxelQuery::VoxelQuery(Node* owningNode) :
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelQuery::~VoxelQuery() {
|
VoxelQuery::~VoxelQuery() {
|
||||||
|
qDebug("VoxelQuery::~VoxelQuery()\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelQuery::getBroadcastData(unsigned char* destinationBuffer) {
|
int VoxelQuery::getBroadcastData(unsigned char* destinationBuffer) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ class VoxelQuery : public NodeData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VoxelQuery(Node* owningNode = NULL);
|
VoxelQuery(Node* owningNode = NULL);
|
||||||
~VoxelQuery();
|
virtual ~VoxelQuery();
|
||||||
|
|
||||||
int getBroadcastData(unsigned char* destinationBuffer);
|
int getBroadcastData(unsigned char* destinationBuffer);
|
||||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||||
|
|
|
@ -1806,9 +1806,10 @@ void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) {
|
||||||
while (!nodeBag.isEmpty()) {
|
while (!nodeBag.isEmpty()) {
|
||||||
VoxelNode* subTree = nodeBag.extract();
|
VoxelNode* subTree = nodeBag.extract();
|
||||||
|
|
||||||
|
lockForRead(); // do tree locking down here so that we have shorter slices and less thread contention
|
||||||
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
|
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
|
||||||
bytesWritten = encodeTreeBitstream(subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, params);
|
bytesWritten = encodeTreeBitstream(subTree, &outputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeBag, params);
|
||||||
|
unlock();
|
||||||
file.write((const char*)&outputBuffer[0], bytesWritten);
|
file.write((const char*)&outputBuffer[0], bytesWritten);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "VoxelEditPacketSender.h"
|
#include "VoxelEditPacketSender.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
// Callback function, for recuseTreeWithOperation
|
// Callback function, for recuseTreeWithOperation
|
||||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
||||||
|
@ -185,6 +186,13 @@ public:
|
||||||
// reads voxels from square image with alpha as a Y-axis
|
// reads voxels from square image with alpha as a Y-axis
|
||||||
bool readFromSquareARGB32Pixels(const char *filename);
|
bool readFromSquareARGB32Pixels(const char *filename);
|
||||||
bool readFromSchematicFile(const char* filename);
|
bool readFromSchematicFile(const char* filename);
|
||||||
|
|
||||||
|
// VoxelTree does not currently handle its own locking, caller must use these to lock/unlock
|
||||||
|
void lockForRead() { lock.lockForRead(); }
|
||||||
|
void tryLockForRead() { lock.tryLockForRead(); }
|
||||||
|
void lockForWrite() { lock.lockForWrite(); }
|
||||||
|
void tryLockForWrite() { lock.tryLockForWrite(); }
|
||||||
|
void unlock() { lock.unlock(); }
|
||||||
|
|
||||||
unsigned long getVoxelCount();
|
unsigned long getVoxelCount();
|
||||||
|
|
||||||
|
@ -266,6 +274,8 @@ private:
|
||||||
static bool nudgeCheck(VoxelNode* node, void* extraData);
|
static bool nudgeCheck(VoxelNode* node, void* extraData);
|
||||||
void nudgeLeaf(VoxelNode* node, void* extraData);
|
void nudgeLeaf(VoxelNode* node, void* extraData);
|
||||||
void chunkifyLeaf(VoxelNode* node);
|
void chunkifyLeaf(VoxelNode* node);
|
||||||
|
|
||||||
|
QReadWriteLock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
|
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
|
||||||
|
|
Loading…
Reference in a new issue