mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 19:02:55 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into pointy
This commit is contained in:
commit
fd1671a44f
14 changed files with 322 additions and 108 deletions
|
@ -697,8 +697,7 @@ int main(int argc, const char * argv[])
|
||||||
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
||||||
if (::wantLocalDomain) {
|
if (::wantLocalDomain) {
|
||||||
printf("Local Domain MODE!\n");
|
printf("Local Domain MODE!\n");
|
||||||
int ip = getLocalAddress();
|
nodeList->setDomainIPToLocalhost();
|
||||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
|
nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
|
||||||
|
|
|
@ -70,17 +70,16 @@ bool wantLocalDomain = false;
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
|
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
|
||||||
|
|
||||||
// Handle Local Domain testing with the --local command line
|
// Handle Local Domain testing with the --local command line
|
||||||
const char* local = "--local";
|
const char* local = "--local";
|
||||||
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
||||||
if (::wantLocalDomain) {
|
if (::wantLocalDomain) {
|
||||||
printf("Local Domain MODE!\n");
|
printf("Local Domain MODE!\n");
|
||||||
int ip = getLocalAddress();
|
nodeList->setDomainIPToLocalhost();
|
||||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::createInstance(NODE_TYPE_AUDIO_MIXER, MIXER_LISTEN_PORT);
|
|
||||||
|
|
||||||
ssize_t receivedBytes = 0;
|
ssize_t receivedBytes = 0;
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = attachNewBufferToNode;
|
nodeList->linkedDataCreateCallback = attachNewBufferToNode;
|
||||||
|
|
|
@ -60,8 +60,7 @@ int main(int argc, const char* argv[]) {
|
||||||
const char* local = "--local";
|
const char* local = "--local";
|
||||||
if (cmdOptionExists(argc, argv, local)) {
|
if (cmdOptionExists(argc, argv, local)) {
|
||||||
printf("Local Domain MODE!\n");
|
printf("Local Domain MODE!\n");
|
||||||
int ip = getLocalAddress();
|
nodeList->setDomainIPToLocalhost();
|
||||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
|
nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
|
||||||
|
|
|
@ -82,6 +82,7 @@ const glm::vec3 START_LOCATION(4.f, 0.f, 5.f); // Where one's own node begins
|
||||||
|
|
||||||
const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff
|
const int IDLE_SIMULATE_MSECS = 16; // How often should call simulate and other stuff
|
||||||
// in the idle loop? (60 FPS is default)
|
// in the idle loop? (60 FPS is default)
|
||||||
|
static QTimer* idleTimer = NULL;
|
||||||
|
|
||||||
const int STARTUP_JITTER_SAMPLES = PACKET_LENGTH_SAMPLES_PER_CHANNEL / 2;
|
const int STARTUP_JITTER_SAMPLES = PACKET_LENGTH_SAMPLES_PER_CHANNEL / 2;
|
||||||
// Startup optimistically with small jitter buffer that
|
// Startup optimistically with small jitter buffer that
|
||||||
|
@ -227,14 +228,14 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
|
|
||||||
const char* domainIP = getCmdOption(argc, constArgv, "--domain");
|
const char* domainIP = getCmdOption(argc, constArgv, "--domain");
|
||||||
if (domainIP) {
|
if (domainIP) {
|
||||||
strcpy(DOMAIN_IP, domainIP);
|
NodeList::getInstance()->setDomainIP(domainIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Local Domain testing with the --local command line
|
// Handle Local Domain testing with the --local command line
|
||||||
if (cmdOptionExists(argc, constArgv, "--local")) {
|
if (cmdOptionExists(argc, constArgv, "--local")) {
|
||||||
printLog("Local Domain MODE!\n");
|
printLog("Local Domain MODE!\n");
|
||||||
int ip = getLocalAddress();
|
|
||||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
NodeList::getInstance()->setDomainIPToLocalhost();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the user passed in a command line option for loading a local
|
// Check to see if the user passed in a command line option for loading a local
|
||||||
|
@ -341,7 +342,7 @@ void Application::initializeGL() {
|
||||||
timer->start(1000);
|
timer->start(1000);
|
||||||
|
|
||||||
// call our idle function whenever we can
|
// call our idle function whenever we can
|
||||||
QTimer* idleTimer = new QTimer(this);
|
idleTimer = new QTimer(this);
|
||||||
connect(idleTimer, SIGNAL(timeout()), SLOT(idle()));
|
connect(idleTimer, SIGNAL(timeout()), SLOT(idle()));
|
||||||
idleTimer->start(0);
|
idleTimer->start(0);
|
||||||
_idleLoopStdev.reset();
|
_idleLoopStdev.reset();
|
||||||
|
@ -973,19 +974,9 @@ void Application::idle() {
|
||||||
gettimeofday(&check, NULL);
|
gettimeofday(&check, NULL);
|
||||||
|
|
||||||
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
|
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
|
||||||
sendPostedEvents(NULL, QEvent::TouchBegin);
|
|
||||||
sendPostedEvents(NULL, QEvent::TouchUpdate);
|
|
||||||
sendPostedEvents(NULL, QEvent::TouchEnd);
|
|
||||||
|
|
||||||
double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check);
|
double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check);
|
||||||
if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
|
if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
|
||||||
|
|
||||||
// If we're using multi-touch look, immediately process any
|
|
||||||
// touch events, and no other events.
|
|
||||||
// This is necessary because id the idle() call takes longer than the
|
|
||||||
// interval between idle() calls, the event loop never gets to run,
|
|
||||||
// and touch events get delayed.
|
|
||||||
|
|
||||||
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
||||||
_glWidget->updateGL();
|
_glWidget->updateGL();
|
||||||
|
@ -998,6 +989,9 @@ void Application::idle() {
|
||||||
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
|
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
|
||||||
_idleLoopStdev.reset();
|
_idleLoopStdev.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
|
||||||
|
idleTimer->start(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Application::terminate() {
|
void Application::terminate() {
|
||||||
|
@ -1101,8 +1095,14 @@ void Application::editPreferences() {
|
||||||
QFormLayout* form = new QFormLayout();
|
QFormLayout* form = new QFormLayout();
|
||||||
layout->addLayout(form, 1);
|
layout->addLayout(form, 1);
|
||||||
|
|
||||||
|
const int QLINE_MINIMUM_WIDTH = 400;
|
||||||
|
|
||||||
|
QLineEdit* domainServerHostname = new QLineEdit(QString(NodeList::getInstance()->getDomainHostname()));
|
||||||
|
domainServerHostname->setMinimumWidth(QLINE_MINIMUM_WIDTH);
|
||||||
|
form->addRow("Domain server:", domainServerHostname);
|
||||||
|
|
||||||
QLineEdit* avatarURL = new QLineEdit(_myAvatar.getVoxels()->getVoxelURL().toString());
|
QLineEdit* avatarURL = new QLineEdit(_myAvatar.getVoxels()->getVoxelURL().toString());
|
||||||
avatarURL->setMinimumWidth(400);
|
avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
|
||||||
form->addRow("Avatar URL:", avatarURL);
|
form->addRow("Avatar URL:", avatarURL);
|
||||||
|
|
||||||
QSpinBox* horizontalFieldOfView = new QSpinBox();
|
QSpinBox* horizontalFieldOfView = new QSpinBox();
|
||||||
|
@ -1133,9 +1133,33 @@ void Application::editPreferences() {
|
||||||
if (dialog.exec() != QDialog::Accepted) {
|
if (dialog.exec() != QDialog::Accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* newHostname = domainServerHostname->text().toLocal8Bit().data();
|
||||||
|
|
||||||
|
// check if the domain server hostname is new
|
||||||
|
if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname, sizeof(&newHostname)) != 0) {
|
||||||
|
// if so we need to clear the nodelist and delete the local voxels
|
||||||
|
Node *voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
|
||||||
|
|
||||||
|
if (voxelServer) {
|
||||||
|
voxelServer->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
_voxels.killLocalVoxels();
|
||||||
|
|
||||||
|
if (voxelServer) {
|
||||||
|
voxelServer->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeList::getInstance()->clear();
|
||||||
|
NodeList::getInstance()->setDomainHostname(newHostname);
|
||||||
|
}
|
||||||
|
|
||||||
QUrl url(avatarURL->text());
|
QUrl url(avatarURL->text());
|
||||||
_myAvatar.getVoxels()->setVoxelURL(url);
|
_myAvatar.getVoxels()->setVoxelURL(url);
|
||||||
sendAvatarVoxelURLMessage(url);
|
sendAvatarVoxelURLMessage(url);
|
||||||
|
|
||||||
_headCameraPitchYawScale = headCameraPitchYawScale->value();
|
_headCameraPitchYawScale = headCameraPitchYawScale->value();
|
||||||
_myAvatar.setLeanScale(leanScale->value());
|
_myAvatar.setLeanScale(leanScale->value());
|
||||||
_audioJitterBufferSamples = audioJitterBufferSamples->value();
|
_audioJitterBufferSamples = audioJitterBufferSamples->value();
|
||||||
|
@ -1214,6 +1238,12 @@ void Application::setRenderWarnings(bool renderWarnings) {
|
||||||
_voxels.setRenderPipelineWarnings(renderWarnings);
|
_voxels.setRenderPipelineWarnings(renderWarnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setRenderVoxels(bool voxelRender) {
|
||||||
|
if (!voxelRender) {
|
||||||
|
doKillLocalVoxels();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::doKillLocalVoxels() {
|
void Application::doKillLocalVoxels() {
|
||||||
_wantToKillLocalVoxels = true;
|
_wantToKillLocalVoxels = true;
|
||||||
}
|
}
|
||||||
|
@ -1333,7 +1363,9 @@ struct SendVoxelsOperationArgs {
|
||||||
unsigned char* newBaseOctCode;
|
unsigned char* newBaseOctCode;
|
||||||
unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE];
|
unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE];
|
||||||
int bufferInUse;
|
int bufferInUse;
|
||||||
|
uint64_t lastSendTime;
|
||||||
|
int packetsSent;
|
||||||
|
uint64_t bytesSent;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||||
|
@ -1365,17 +1397,30 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||||
codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
||||||
codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
||||||
|
|
||||||
// TODO: sendVoxelsOperation() is sending voxels too fast.
|
|
||||||
// This printf function accidently slowed down sending
|
|
||||||
// and hot-fixed the bug when importing
|
|
||||||
// large PNG models (256x256 px and more)
|
|
||||||
static unsigned int sendVoxelsOperationCalled = 0; printf("sending voxel #%u\n", ++sendVoxelsOperationCalled);
|
|
||||||
|
|
||||||
// if we have room don't have room in the buffer, then send the previously generated message first
|
// 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) {
|
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
||||||
|
|
||||||
|
args->packetsSent++;
|
||||||
|
args->bytesSent += args->bufferInUse;
|
||||||
|
|
||||||
controlledBroadcastToNodes(args->messageBuffer, args->bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
controlledBroadcastToNodes(args->messageBuffer, args->bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
args->bufferInUse = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_SET_VOXEL_DESTRUCTIVE)
|
args->bufferInUse = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_SET_VOXEL_DESTRUCTIVE)
|
||||||
+ sizeof(unsigned short int); // reset
|
+ sizeof(unsigned short int); // reset
|
||||||
|
|
||||||
|
uint64_t now = usecTimestampNow();
|
||||||
|
// dynamically sleep until we need to fire off the next set of voxels
|
||||||
|
const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packet every 10 milliseconds
|
||||||
|
uint64_t elapsed = now - args->lastSendTime;
|
||||||
|
int usecToSleep = CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS - elapsed;
|
||||||
|
if (usecToSleep > 0) {
|
||||||
|
printLog("sendVoxelsOperation: packet: %d bytes:%ld elapsed %ld usecs, sleeping for %d usecs!\n",
|
||||||
|
args->packetsSent, args->bytesSent, elapsed, usecToSleep);
|
||||||
|
usleep(usecToSleep);
|
||||||
|
} else {
|
||||||
|
printLog("sendVoxelsOperation: packet: %d bytes:%ld elapsed %ld usecs, no need to sleep!\n",
|
||||||
|
args->packetsSent, args->bytesSent, elapsed);
|
||||||
|
}
|
||||||
|
args->lastSendTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy this node's code color details into our buffer.
|
// copy this node's code color details into our buffer.
|
||||||
|
@ -1404,13 +1449,14 @@ void Application::exportVoxels() {
|
||||||
_window->activateWindow();
|
_window->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::importVoxels() {
|
const char* IMPORT_FILE_TYPES = "Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)";
|
||||||
|
void Application::importVoxelsToClipboard() {
|
||||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||||
QString fileNameString = QFileDialog::getOpenFileName(
|
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels to Clipboard"), desktopLocation,
|
||||||
_glWidget, tr("Import Voxels"), desktopLocation,
|
tr(IMPORT_FILE_TYPES));
|
||||||
tr("Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)"));
|
|
||||||
|
|
||||||
const char* fileName = fileNameString.toAscii().data();
|
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||||
|
const char* fileName = fileNameAscii.data();
|
||||||
|
|
||||||
_clipboardTree.eraseAllVoxels();
|
_clipboardTree.eraseAllVoxels();
|
||||||
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
|
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
|
||||||
|
@ -1427,7 +1473,6 @@ void Application::importVoxels() {
|
||||||
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
|
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
|
||||||
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
|
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
|
||||||
}
|
}
|
||||||
|
|
||||||
_clipboardTree.readFromSquareARGB32Pixels(pixels, pngImage.height());
|
_clipboardTree.readFromSquareARGB32Pixels(pixels, pngImage.height());
|
||||||
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
|
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
|
||||||
_clipboardTree.readFromSVOFile(fileName);
|
_clipboardTree.readFromSVOFile(fileName);
|
||||||
|
@ -1439,6 +1484,76 @@ void Application::importVoxels() {
|
||||||
_window->activateWindow();
|
_window->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::importVoxels() {
|
||||||
|
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||||
|
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
|
||||||
|
tr(IMPORT_FILE_TYPES));
|
||||||
|
|
||||||
|
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||||
|
const char* fileName = fileNameAscii.data();
|
||||||
|
|
||||||
|
VoxelTree importVoxels;
|
||||||
|
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
|
||||||
|
QImage pngImage = QImage(fileName);
|
||||||
|
if (pngImage.height() != pngImage.width()) {
|
||||||
|
printLog("ERROR: Bad PNG size: height != width.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t* pixels;
|
||||||
|
if (pngImage.format() == QImage::Format_ARGB32) {
|
||||||
|
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
|
||||||
|
} else {
|
||||||
|
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
|
||||||
|
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
|
||||||
|
}
|
||||||
|
|
||||||
|
importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height());
|
||||||
|
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
|
||||||
|
importVoxels.readFromSVOFile(fileName);
|
||||||
|
} else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) {
|
||||||
|
importVoxels.readFromSchematicFile(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.lastSendTime = usecTimestampNow();
|
||||||
|
args.packetsSent = 0;
|
||||||
|
args.bytesSent = 0;
|
||||||
|
|
||||||
|
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
||||||
|
|
||||||
|
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader];
|
||||||
|
*sequenceAt = 0;
|
||||||
|
args.bufferInUse = numBytesPacketHeader + 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 > (numBytesPacketHeader + sizeof(unsigned short int))) {
|
||||||
|
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calculatedOctCode) {
|
||||||
|
delete[] calculatedOctCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore the main window's active state
|
||||||
|
_window->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
void Application::cutVoxels() {
|
void Application::cutVoxels() {
|
||||||
copyVoxels();
|
copyVoxels();
|
||||||
deleteVoxelUnderCursor();
|
deleteVoxelUnderCursor();
|
||||||
|
@ -1462,6 +1577,9 @@ void Application::pasteVoxels() {
|
||||||
// Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to
|
// 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
|
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||||
SendVoxelsOperationArgs args;
|
SendVoxelsOperationArgs args;
|
||||||
|
args.lastSendTime = usecTimestampNow();
|
||||||
|
args.packetsSent = 0;
|
||||||
|
args.bytesSent = 0;
|
||||||
|
|
||||||
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
||||||
|
|
||||||
|
@ -1483,6 +1601,9 @@ void Application::pasteVoxels() {
|
||||||
// If we have voxels left in the packet, then send the packet
|
// If we have voxels left in the packet, then send the packet
|
||||||
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
|
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
|
||||||
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
|
printLog("sending packet: %d\n", ++args.packetsSent);
|
||||||
|
args.bytesSent += args.bufferInUse;
|
||||||
|
printLog("total bytes sent: %ld\n", args.bytesSent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculatedOctCode) {
|
if (calculatedOctCode) {
|
||||||
|
@ -1524,9 +1645,8 @@ void Application::initMenu() {
|
||||||
optionsMenu->addAction("Go Home", this, SLOT(goHome()));
|
optionsMenu->addAction("Go Home", this, SLOT(goHome()));
|
||||||
|
|
||||||
QMenu* renderMenu = menuBar->addMenu("Render");
|
QMenu* renderMenu = menuBar->addMenu("Render");
|
||||||
(_renderVoxels = renderMenu->addAction("Voxels"))->setCheckable(true);
|
(_renderVoxels = renderMenu->addAction("Voxels", this, SLOT(setRenderVoxels(bool)), Qt::SHIFT | Qt::Key_V))->setCheckable(true);
|
||||||
_renderVoxels->setChecked(true);
|
_renderVoxels->setChecked(true);
|
||||||
_renderVoxels->setShortcut(Qt::SHIFT | Qt::Key_V);
|
|
||||||
(_renderVoxelTextures = renderMenu->addAction("Voxel Textures"))->setCheckable(true);
|
(_renderVoxelTextures = renderMenu->addAction("Voxel Textures"))->setCheckable(true);
|
||||||
(_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true);
|
(_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true);
|
||||||
_renderStarsOn->setChecked(true);
|
_renderStarsOn->setChecked(true);
|
||||||
|
@ -1602,6 +1722,7 @@ void Application::initMenu() {
|
||||||
|
|
||||||
voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E);
|
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("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I);
|
||||||
|
voxelMenu->addAction("Import Voxels to Clipboard", this, SLOT(importVoxelsToClipboard()), Qt::SHIFT | Qt::CTRL | Qt::Key_I);
|
||||||
voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X);
|
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("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C);
|
||||||
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
|
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
|
||||||
|
@ -1927,8 +2048,8 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
//loop through all the other avatars and simulate them...
|
//loop through all the other avatars and simulate them...
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
nodeList->lock();
|
|
||||||
for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
node->lock();
|
||||||
if (node->getLinkedData() != NULL) {
|
if (node->getLinkedData() != NULL) {
|
||||||
Avatar *avatar = (Avatar *)node->getLinkedData();
|
Avatar *avatar = (Avatar *)node->getLinkedData();
|
||||||
if (!avatar->isInitialized()) {
|
if (!avatar->isInitialized()) {
|
||||||
|
@ -1937,8 +2058,8 @@ void Application::update(float deltaTime) {
|
||||||
avatar->simulate(deltaTime, NULL);
|
avatar->simulate(deltaTime, NULL);
|
||||||
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
|
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||||
}
|
}
|
||||||
|
node->unlock();
|
||||||
}
|
}
|
||||||
nodeList->unlock();
|
|
||||||
|
|
||||||
// Simulate myself
|
// Simulate myself
|
||||||
if (_gravityUse->isChecked()) {
|
if (_gravityUse->isChecked()) {
|
||||||
|
@ -2427,8 +2548,10 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
if (_renderAvatarsOn->isChecked()) {
|
if (_renderAvatarsOn->isChecked()) {
|
||||||
// Render avatars of other nodes
|
// Render avatars of other nodes
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
nodeList->lock();
|
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
node->lock();
|
||||||
|
|
||||||
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
|
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
|
||||||
Avatar *avatar = (Avatar *)node->getLinkedData();
|
Avatar *avatar = (Avatar *)node->getLinkedData();
|
||||||
if (!avatar->isInitialized()) {
|
if (!avatar->isInitialized()) {
|
||||||
|
@ -2437,8 +2560,9 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
avatar->render(false, _renderAvatarBalls->isChecked());
|
avatar->render(false, _renderAvatarBalls->isChecked());
|
||||||
avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked());
|
avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->unlock();
|
||||||
}
|
}
|
||||||
nodeList->unlock();
|
|
||||||
|
|
||||||
// Render my own Avatar
|
// Render my own Avatar
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
|
@ -3208,11 +3332,23 @@ void* Application::networkReceive(void* args) {
|
||||||
case PACKET_TYPE_VOXEL_DATA_MONOCHROME:
|
case PACKET_TYPE_VOXEL_DATA_MONOCHROME:
|
||||||
case PACKET_TYPE_Z_COMMAND:
|
case PACKET_TYPE_Z_COMMAND:
|
||||||
case PACKET_TYPE_ERASE_VOXEL:
|
case PACKET_TYPE_ERASE_VOXEL:
|
||||||
app->_voxels.parseData(app->_incomingPacket, bytesReceived);
|
case PACKET_TYPE_ENVIRONMENT_DATA: {
|
||||||
break;
|
if (app->_renderVoxels->isChecked()) {
|
||||||
case PACKET_TYPE_ENVIRONMENT_DATA:
|
Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
|
||||||
|
if (voxelServer) {
|
||||||
|
voxelServer->lock();
|
||||||
|
|
||||||
|
if (app->_incomingPacket[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
|
||||||
app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
|
app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
|
||||||
|
} else {
|
||||||
|
app->_voxels.parseData(app->_incomingPacket, bytesReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
voxelServer->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case PACKET_TYPE_BULK_AVATAR_DATA:
|
case PACKET_TYPE_BULK_AVATAR_DATA:
|
||||||
NodeList::getInstance()->processBulkNodeData(&senderAddress,
|
NodeList::getInstance()->processBulkNodeData(&senderAddress,
|
||||||
app->_incomingPacket,
|
app->_incomingPacket,
|
||||||
|
|
|
@ -128,6 +128,7 @@ private slots:
|
||||||
void cycleFrustumRenderMode();
|
void cycleFrustumRenderMode();
|
||||||
|
|
||||||
void setRenderWarnings(bool renderWarnings);
|
void setRenderWarnings(bool renderWarnings);
|
||||||
|
void setRenderVoxels(bool renderVoxels);
|
||||||
void doKillLocalVoxels();
|
void doKillLocalVoxels();
|
||||||
void doRandomizeVoxelColors();
|
void doRandomizeVoxelColors();
|
||||||
void doFalseRandomizeVoxelColors();
|
void doFalseRandomizeVoxelColors();
|
||||||
|
@ -153,6 +154,7 @@ private slots:
|
||||||
void exportSettings();
|
void exportSettings();
|
||||||
void exportVoxels();
|
void exportVoxels();
|
||||||
void importVoxels();
|
void importVoxels();
|
||||||
|
void importVoxelsToClipboard();
|
||||||
void cutVoxels();
|
void cutVoxels();
|
||||||
void copyVoxels();
|
void copyVoxels();
|
||||||
void pasteVoxels();
|
void pasteVoxels();
|
||||||
|
|
|
@ -96,6 +96,10 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
||||||
Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
|
Node* audioMixer = nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
|
||||||
|
|
||||||
if (audioMixer) {
|
if (audioMixer) {
|
||||||
|
audioMixer->lock();
|
||||||
|
sockaddr_in audioSocket = *(sockaddr_in*) audioMixer->getActiveSocket();
|
||||||
|
audioMixer->unlock();
|
||||||
|
|
||||||
glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();
|
glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();
|
||||||
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
|
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
|
||||||
|
|
||||||
|
@ -122,12 +126,13 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
||||||
|
|
||||||
// copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet
|
// copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet
|
||||||
memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES_PER_CHANNEL);
|
memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES_PER_CHANNEL);
|
||||||
nodeList->getNodeSocket()->send(audioMixer->getActiveSocket(),
|
nodeList->getNodeSocket()->send((sockaddr*) &audioSocket,
|
||||||
dataPacket,
|
dataPacket,
|
||||||
BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
|
BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
|
||||||
|
|
||||||
interface->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO)
|
interface->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO).updateValue(BUFFER_LENGTH_BYTES_PER_CHANNEL
|
||||||
.updateValue(BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes);
|
+ leadingBytes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1331,6 +1331,10 @@ void Avatar::loadData(QSettings* settings) {
|
||||||
|
|
||||||
_leanScale = loadSetting(settings, "leanScale", 0.5f);
|
_leanScale = loadSetting(settings, "leanScale", 0.5f);
|
||||||
|
|
||||||
|
_scale = loadSetting(settings, "scale", 1.0f);
|
||||||
|
setScale(_scale);
|
||||||
|
Application::getInstance()->getCamera()->setScale(_scale);
|
||||||
|
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,6 +1357,7 @@ void Avatar::saveData(QSettings* set) {
|
||||||
set->setValue("voxelURL", _voxels.getVoxelURL());
|
set->setValue("voxelURL", _voxels.getVoxelURL());
|
||||||
|
|
||||||
set->setValue("leanScale", _leanScale);
|
set->setValue("leanScale", _leanScale);
|
||||||
|
set->setValue("scale", _scale);
|
||||||
|
|
||||||
set->endGroup();
|
set->endGroup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -509,6 +509,8 @@ namespace starfield {
|
||||||
_program.release();
|
_program.release();
|
||||||
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||||
glDisable(GL_POINT_SMOOTH);
|
glDisable(GL_POINT_SMOOTH);
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ Node::Node(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t no
|
||||||
} else {
|
} else {
|
||||||
_localSocket = NULL;
|
_localSocket = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_init(&_mutex, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::~Node() {
|
Node::~Node() {
|
||||||
|
@ -60,6 +62,8 @@ Node::~Node() {
|
||||||
delete _localSocket;
|
delete _localSocket;
|
||||||
delete _linkedData;
|
delete _linkedData;
|
||||||
delete _bytesReceivedMovingAverage;
|
delete _bytesReceivedMovingAverage;
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names of Node Types
|
// Names of Node Types
|
||||||
|
|
|
@ -66,6 +66,9 @@ public:
|
||||||
int getPingMs() const { return _pingMs; };
|
int getPingMs() const { return _pingMs; };
|
||||||
void setPingMs(int pingMs) { _pingMs = pingMs; };
|
void setPingMs(int pingMs) { _pingMs = pingMs; };
|
||||||
|
|
||||||
|
void lock() { pthread_mutex_lock(&_mutex); }
|
||||||
|
void unlock() { pthread_mutex_unlock(&_mutex); }
|
||||||
|
|
||||||
static void printLog(Node const&);
|
static void printLog(Node const&);
|
||||||
private:
|
private:
|
||||||
// privatize copy and assignment operator to disallow Node copying
|
// privatize copy and assignment operator to disallow Node copying
|
||||||
|
@ -83,6 +86,7 @@ private:
|
||||||
NodeData* _linkedData;
|
NodeData* _linkedData;
|
||||||
bool _isAlive;
|
bool _isAlive;
|
||||||
int _pingMs;
|
int _pingMs;
|
||||||
|
pthread_mutex_t _mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ const char SOLO_NODE_TYPES[3] = {
|
||||||
NODE_TYPE_VOXEL_SERVER
|
NODE_TYPE_VOXEL_SERVER
|
||||||
};
|
};
|
||||||
|
|
||||||
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
|
const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES] = "root.highfidelity.io";
|
||||||
char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup
|
const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN] = ""; // IP Address will be re-set by lookup on startup
|
||||||
const int DOMAINSERVER_PORT = 40102;
|
const int DEFAULT_DOMAINSERVER_PORT = 40102;
|
||||||
|
|
||||||
bool silentNodeThreadStopFlag = false;
|
bool silentNodeThreadStopFlag = false;
|
||||||
bool pingUnknownNodeThreadStopFlag = false;
|
bool pingUnknownNodeThreadStopFlag = false;
|
||||||
|
@ -63,17 +63,37 @@ NodeList::NodeList(char newOwnerType, unsigned int newSocketListenPort) :
|
||||||
_ownerType(newOwnerType),
|
_ownerType(newOwnerType),
|
||||||
_nodeTypesOfInterest(NULL),
|
_nodeTypesOfInterest(NULL),
|
||||||
_ownerID(UNKNOWN_NODE_ID),
|
_ownerID(UNKNOWN_NODE_ID),
|
||||||
_lastNodeID(0) {
|
_lastNodeID(0)
|
||||||
pthread_mutex_init(&mutex, 0);
|
{
|
||||||
|
memcpy(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, sizeof(DEFAULT_DOMAIN_HOSTNAME));
|
||||||
|
memcpy(_domainIP, DEFAULT_DOMAIN_IP, sizeof(DEFAULT_DOMAIN_IP));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeList::~NodeList() {
|
NodeList::~NodeList() {
|
||||||
delete _nodeTypesOfInterest;
|
delete _nodeTypesOfInterest;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
// stop the spawned threads, if they were started
|
// stop the spawned threads, if they were started
|
||||||
stopSilentNodeRemovalThread();
|
stopSilentNodeRemovalThread();
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_destroy(&mutex);
|
void NodeList::setDomainHostname(const char* domainHostname) {
|
||||||
|
memset(_domainHostname, 0, sizeof(_domainHostname));
|
||||||
|
memcpy(_domainHostname, domainHostname, strlen(domainHostname));
|
||||||
|
|
||||||
|
// reset the domain IP so the hostname is checked again
|
||||||
|
setDomainIP("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeList::setDomainIP(const char* domainIP) {
|
||||||
|
memset(_domainIP, 0, sizeof(_domainIP));
|
||||||
|
memcpy(_domainIP, domainIP, strlen(domainIP));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeList::setDomainIPToLocalhost() {
|
||||||
|
int ip = getLocalAddress();
|
||||||
|
sprintf(_domainIP, "%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
||||||
|
@ -92,7 +112,14 @@ void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
||||||
void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetData, size_t dataBytes) {
|
void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetData, size_t dataBytes) {
|
||||||
switch (packetData[0]) {
|
switch (packetData[0]) {
|
||||||
case PACKET_TYPE_DOMAIN: {
|
case PACKET_TYPE_DOMAIN: {
|
||||||
|
// only process the DS if this is our current domain server
|
||||||
|
sockaddr_in domainServerSocket = *(sockaddr_in*) senderAddress;
|
||||||
|
const char* domainSenderIP = inet_ntoa(domainServerSocket.sin_addr);
|
||||||
|
|
||||||
|
if (memcmp(domainSenderIP, _domainIP, strlen(domainSenderIP)) == 0) {
|
||||||
processDomainServerList(packetData, dataBytes);
|
processDomainServerList(packetData, dataBytes);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PACKET_TYPE_PING: {
|
case PACKET_TYPE_PING: {
|
||||||
|
@ -110,7 +137,6 @@ void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetDat
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
|
void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) {
|
||||||
lock();
|
|
||||||
|
|
||||||
// find the avatar mixer in our node list and update the lastRecvTime from it
|
// find the avatar mixer in our node list and update the lastRecvTime from it
|
||||||
Node* bulkSendNode = nodeWithAddress(senderAddress);
|
Node* bulkSendNode = nodeWithAddress(senderAddress);
|
||||||
|
@ -118,7 +144,6 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
|
||||||
if (bulkSendNode) {
|
if (bulkSendNode) {
|
||||||
bulkSendNode->setLastHeardMicrostamp(usecTimestampNow());
|
bulkSendNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
bulkSendNode->recordBytesReceived(numTotalBytes);
|
bulkSendNode->recordBytesReceived(numTotalBytes);
|
||||||
}
|
|
||||||
|
|
||||||
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||||
|
|
||||||
|
@ -147,9 +172,9 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
|
||||||
currentPosition += updateNodeWithData(matchingNode,
|
currentPosition += updateNodeWithData(matchingNode,
|
||||||
packetHolder,
|
packetHolder,
|
||||||
numTotalBytes - (currentPosition - startPosition));
|
numTotalBytes - (currentPosition - startPosition));
|
||||||
}
|
|
||||||
|
|
||||||
unlock();
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
|
int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
|
||||||
|
@ -164,6 +189,8 @@ int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetD
|
||||||
}
|
}
|
||||||
|
|
||||||
int NodeList::updateNodeWithData(Node *node, unsigned char *packetData, int dataBytes) {
|
int NodeList::updateNodeWithData(Node *node, unsigned char *packetData, int dataBytes) {
|
||||||
|
node->lock();
|
||||||
|
|
||||||
node->setLastHeardMicrostamp(usecTimestampNow());
|
node->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
|
|
||||||
if (node->getActiveSocket()) {
|
if (node->getActiveSocket()) {
|
||||||
|
@ -174,7 +201,11 @@ int NodeList::updateNodeWithData(Node *node, unsigned char *packetData, int data
|
||||||
linkedDataCreateCallback(node);
|
linkedDataCreateCallback(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node->getLinkedData()->parseData(packetData, dataBytes);
|
int numParsedBytes = node->getLinkedData()->parseData(packetData, dataBytes);
|
||||||
|
|
||||||
|
node->unlock();
|
||||||
|
|
||||||
|
return numParsedBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* NodeList::nodeWithAddress(sockaddr *senderAddress) {
|
Node* NodeList::nodeWithAddress(sockaddr *senderAddress) {
|
||||||
|
@ -209,6 +240,21 @@ int NodeList::getNumAliveNodes() const {
|
||||||
return numAliveNodes;
|
return numAliveNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeList::clear() {
|
||||||
|
// delete all of the nodes in the list, set the pointers back to NULL and the number of nodes to 0
|
||||||
|
for (int i = 0; i < _numNodes; i++) {
|
||||||
|
Node** nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET];
|
||||||
|
Node* node = nodeBucket[i % NODES_PER_BUCKET];
|
||||||
|
|
||||||
|
node->lock();
|
||||||
|
delete node;
|
||||||
|
|
||||||
|
node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_numNodes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) {
|
void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) {
|
||||||
delete _nodeTypesOfInterest;
|
delete _nodeTypesOfInterest;
|
||||||
|
|
||||||
|
@ -221,18 +267,19 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
static bool printedDomainServerIP = false;
|
static bool printedDomainServerIP = false;
|
||||||
|
|
||||||
// Lookup the IP address of the domain server if we need to
|
// Lookup the IP address of the domain server if we need to
|
||||||
if (atoi(DOMAIN_IP) == 0) {
|
if (atoi(_domainIP) == 0) {
|
||||||
|
printf("Looking up %s\n", _domainHostname);
|
||||||
struct hostent* pHostInfo;
|
struct hostent* pHostInfo;
|
||||||
if ((pHostInfo = gethostbyname(DOMAIN_HOSTNAME)) != NULL) {
|
if ((pHostInfo = gethostbyname(_domainHostname)) != NULL) {
|
||||||
sockaddr_in tempAddress;
|
sockaddr_in tempAddress;
|
||||||
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
||||||
strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
|
strcpy(_domainIP, inet_ntoa(tempAddress.sin_addr));
|
||||||
printLog("Domain Server: %s \n", DOMAIN_HOSTNAME);
|
printLog("Domain Server: %s \n", _domainHostname);
|
||||||
} else {
|
} else {
|
||||||
printLog("Failed domain server lookup\n");
|
printLog("Failed domain server lookup\n");
|
||||||
}
|
}
|
||||||
} else if (!printedDomainServerIP) {
|
} else if (!printedDomainServerIP) {
|
||||||
printLog("Domain Server IP: %s\n", DOMAIN_IP);
|
printLog("Domain Server IP: %s\n", _domainIP);
|
||||||
printedDomainServerIP = true;
|
printedDomainServerIP = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +326,7 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
checkInPacketSize = packetPosition - checkInPacket;
|
checkInPacketSize = packetPosition - checkInPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
_nodeSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
|
_nodeSocket.send(_domainIP, DEFAULT_DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) {
|
int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) {
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
#ifndef __hifi__NodeList__
|
#ifndef __hifi__NodeList__
|
||||||
#define __hifi__NodeList__
|
#define __hifi__NodeList__
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
#include "UDPSocket.h"
|
#include "UDPSocket.h"
|
||||||
|
@ -30,9 +32,11 @@ const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
||||||
|
|
||||||
extern const char SOLO_NODE_TYPES[3];
|
extern const char SOLO_NODE_TYPES[3];
|
||||||
|
|
||||||
extern char DOMAIN_HOSTNAME[];
|
const int MAX_HOSTNAME_BYTES = 255;
|
||||||
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup
|
|
||||||
extern const int DOMAINSERVER_PORT;
|
extern const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES];
|
||||||
|
extern const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN]; // IP Address will be re-set by lookup on startup
|
||||||
|
extern const int DEFAULT_DOMAINSERVER_PORT;
|
||||||
|
|
||||||
const int UNKNOWN_NODE_ID = -1;
|
const int UNKNOWN_NODE_ID = -1;
|
||||||
|
|
||||||
|
@ -48,6 +52,12 @@ public:
|
||||||
NodeListIterator begin() const;
|
NodeListIterator begin() const;
|
||||||
NodeListIterator end() const;
|
NodeListIterator end() const;
|
||||||
|
|
||||||
|
const char* getDomainHostname() const { return _domainHostname; };
|
||||||
|
void setDomainHostname(const char* domainHostname);
|
||||||
|
|
||||||
|
void setDomainIP(const char* domainIP);
|
||||||
|
void setDomainIPToLocalhost();
|
||||||
|
|
||||||
char getOwnerType() const { return _ownerType; }
|
char getOwnerType() const { return _ownerType; }
|
||||||
|
|
||||||
uint16_t getLastNodeID() const { return _lastNodeID; }
|
uint16_t getLastNodeID() const { return _lastNodeID; }
|
||||||
|
@ -65,8 +75,7 @@ public:
|
||||||
int size() { return _numNodes; }
|
int size() { return _numNodes; }
|
||||||
int getNumAliveNodes() const;
|
int getNumAliveNodes() const;
|
||||||
|
|
||||||
void lock() { pthread_mutex_lock(&mutex); }
|
void clear();
|
||||||
void unlock() { pthread_mutex_unlock(&mutex); }
|
|
||||||
|
|
||||||
void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
|
void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
|
||||||
void sendDomainServerCheckIn();
|
void sendDomainServerCheckIn();
|
||||||
|
@ -101,6 +110,8 @@ private:
|
||||||
|
|
||||||
void addNodeToList(Node* newNode);
|
void addNodeToList(Node* newNode);
|
||||||
|
|
||||||
|
char _domainHostname[MAX_HOSTNAME_BYTES];
|
||||||
|
char _domainIP[INET_ADDRSTRLEN];
|
||||||
Node** _nodeBuckets[MAX_NUM_NODES / NODES_PER_BUCKET];
|
Node** _nodeBuckets[MAX_NUM_NODES / NODES_PER_BUCKET];
|
||||||
int _numNodes;
|
int _numNodes;
|
||||||
UDPSocket _nodeSocket;
|
UDPSocket _nodeSocket;
|
||||||
|
@ -111,7 +122,6 @@ private:
|
||||||
uint16_t _lastNodeID;
|
uint16_t _lastNodeID;
|
||||||
pthread_t removeSilentNodesThread;
|
pthread_t removeSilentNodesThread;
|
||||||
pthread_t checkInWithDomainServerThread;
|
pthread_t checkInWithDomainServerThread;
|
||||||
pthread_mutex_t mutex;
|
|
||||||
|
|
||||||
void handlePingReply(sockaddr *nodeAddress);
|
void handlePingReply(sockaddr *nodeAddress);
|
||||||
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
||||||
|
|
|
@ -1251,7 +1251,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
} // wants occlusion culling & isLeaf()
|
} // wants occlusion culling & isLeaf()
|
||||||
|
|
||||||
|
|
||||||
bool shouldRender = childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust);
|
bool shouldRender = !params.viewFrustum ? true : childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust);
|
||||||
|
|
||||||
// track children with actual color, only if the child wasn't previously in view!
|
// track children with actual color, only if the child wasn't previously in view!
|
||||||
if (shouldRender && !childIsOccluded) {
|
if (shouldRender && !childIsOccluded) {
|
||||||
|
|
|
@ -313,6 +313,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
uint64_t lastPersistVoxels = 0;
|
uint64_t lastPersistVoxels = 0;
|
||||||
void persistVoxelsWhenDirty() {
|
void persistVoxelsWhenDirty() {
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
|
if (::lastPersistVoxels == 0) {
|
||||||
|
::lastPersistVoxels = now;
|
||||||
|
}
|
||||||
int sinceLastTime = (now - ::lastPersistVoxels) / 1000;
|
int sinceLastTime = (now - ::lastPersistVoxels) / 1000;
|
||||||
|
|
||||||
// check the dirty bit and persist here...
|
// check the dirty bit and persist here...
|
||||||
|
@ -383,8 +386,7 @@ int main(int argc, const char * argv[]) {
|
||||||
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
::wantLocalDomain = cmdOptionExists(argc, argv,local);
|
||||||
if (::wantLocalDomain) {
|
if (::wantLocalDomain) {
|
||||||
printf("Local Domain MODE!\n");
|
printf("Local Domain MODE!\n");
|
||||||
int ip = getLocalAddress();
|
nodeList->setDomainIPToLocalhost();
|
||||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode;
|
nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode;
|
||||||
|
|
Loading…
Reference in a new issue