Merge branch 'master' of https://github.com/worklist/hifi into glow

This commit is contained in:
Andrzej Kapolka 2013-08-13 09:49:18 -07:00
commit c1f6794295
7 changed files with 185 additions and 51 deletions

View file

@ -225,6 +225,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_audio(&_audioScope, STARTUP_JITTER_SAMPLES),
#endif
_stopNetworkReceiveThread(false),
_stopProcessVoxelsThread(false),
_packetCount(0),
_packetsPerSecond(0),
_bytesPerSecond(0),
@ -249,7 +250,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
NodeList::getInstance()->addHook(this);
_enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking");
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
_enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking");
if (!_enableNetworkThread) {
NodeList::getInstance()->getNodeSocket()->setBlocking(false);
}
@ -373,6 +375,12 @@ void Application::initializeGL() {
pthread_create(&_networkReceiveThread, NULL, networkReceive, NULL);
qDebug("Network receive thread created.\n");
}
// create thread for parsing of voxel data independent of the main network and rendering threads
if (_enableProcessVoxelsThread) {
pthread_create(&_processVoxelsThread, NULL, processVoxels, NULL);
qDebug("Voxel parsing thread created.\n");
}
// call terminate before exiting
connect(this, SIGNAL(aboutToQuit()), SLOT(terminate()));
@ -1178,6 +1186,11 @@ void Application::terminate() {
_stopNetworkReceiveThread = true;
pthread_join(_networkReceiveThread, NULL);
}
if (_enableProcessVoxelsThread) {
_stopProcessVoxelsThread = true;
pthread_join(_processVoxelsThread, NULL);
}
}
void Application::sendAvatarVoxelURLMessage(const QUrl& url) {
@ -1502,8 +1515,8 @@ void Application::doTreeStats() {
_voxels.collectStatsForTreesAndVBOs();
}
void Application::setWantsLowResMoving(bool wantsLowResMoving) {
_myAvatar.setWantLowResMoving(wantsLowResMoving);
void Application::disableLowResMoving(bool disableLowResMoving) {
_myAvatar.setWantLowResMoving(!disableLowResMoving);
}
void Application::setWantsMonochrome(bool wantsMonochrome) {
@ -2082,7 +2095,8 @@ void Application::initMenu() {
debugMenu->addAction("Calculate Tree Stats", this, SLOT(doTreeStats()), Qt::SHIFT | Qt::Key_S);
QMenu* renderDebugMenu = debugMenu->addMenu("Render Debugging Tools");
renderDebugMenu->addAction("Show Render Pipeline Warnings", this, SLOT(setRenderWarnings(bool)))->setCheckable(true);
(_renderPipelineWarnings = renderDebugMenu->addAction("Show Render Pipeline Warnings",
this, SLOT(setRenderWarnings(bool))))->setCheckable(true);
renderDebugMenu->addAction("Kill Local Voxels", this, SLOT(doKillLocalVoxels()), Qt::CTRL | Qt::Key_K);
renderDebugMenu->addAction("Randomize Voxel TRUE Colors", this, SLOT(doRandomizeVoxelColors()), Qt::CTRL | Qt::Key_R);
renderDebugMenu->addAction("FALSE Color Voxels Randomly", this, SLOT(doFalseRandomizeVoxelColors()));
@ -2097,7 +2111,7 @@ void Application::initMenu() {
(_shouldLowPassFilter = debugMenu->addAction("Test: LowPass filter"))->setCheckable(true);
debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true);
debugMenu->addAction("Use Lower Resolution While Moving", this, SLOT(setWantsLowResMoving(bool)))->setCheckable(true);
debugMenu->addAction("Disable Lower Resolution While Moving", this, SLOT(disableLowResMoving(bool)))->setCheckable(true);
debugMenu->addAction("Disable Delta Sending", this, SLOT(disableDeltaSending(bool)))->setCheckable(true);
(_occlusionCulling = debugMenu->addAction("Disable Occlusion Culling", this, SLOT(disableOcclusionCulling(bool)),
Qt::SHIFT | Qt::Key_C))->setCheckable(true);
@ -2574,6 +2588,11 @@ void Application::update(float deltaTime) {
if (!_enableNetworkThread) {
networkReceive(0);
}
// parse voxel packets
if (!_enableProcessVoxelsThread) {
processVoxels(0);
}
//loop through all the other avatars and simulate them...
NodeList* nodeList = NodeList::getInstance();
@ -4035,6 +4054,75 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng
return statsMessageLength;
}
// Receive packets from other nodes/servers and decide what to do with them!
void* Application::processVoxels(void* args) {
Application* app = Application::getInstance();
while (!app->_stopProcessVoxelsThread) {
// check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that
if (app->_wantToKillLocalVoxels) {
app->_voxels.killLocalVoxels();
app->_wantToKillLocalVoxels = false;
}
while (app->_voxelPackets.size() > 0) {
NetworkPacket& packet = app->_voxelPackets.front();
app->processVoxelPacket(packet.getSenderAddress(), packet.getData(), packet.getLength());
app->_voxelPackets.erase(app->_voxelPackets.begin());
}
if (!app->_enableProcessVoxelsThread) {
break;
}
}
if (app->_enableProcessVoxelsThread) {
pthread_exit(0);
}
return NULL;
}
void Application::queueVoxelPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength) {
_voxelPackets.push_back(NetworkPacket(senderAddress, packetData, packetLength));
}
void Application::processVoxelPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength) {
PerformanceWarning warn(_renderPipelineWarnings->isChecked(),"processVoxelPacket()");
ssize_t messageLength = packetLength;
// note: PACKET_TYPE_VOXEL_STATS can have PACKET_TYPE_VOXEL_DATA or PACKET_TYPE_VOXEL_DATA_MONOCHROME
// immediately following them inside the same packet. So, we process the PACKET_TYPE_VOXEL_STATS first
// then process any remaining bytes as if it was another packet
if (packetData[0] == PACKET_TYPE_VOXEL_STATS) {
int statsMessageLength = parseVoxelStats(packetData, messageLength, senderAddress);
if (messageLength > statsMessageLength) {
packetData += statsMessageLength;
messageLength -= statsMessageLength;
if (!packetVersionMatch(packetData)) {
return; // bail since piggyback data doesn't match our versioning
}
} else {
return; // bail since no piggyback data
}
} // fall through to piggyback message
if (_renderVoxels->isChecked()) {
Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress);
if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) {
voxelServer->lock();
if (packetData[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
_environment.parseData(&senderAddress, packetData, messageLength);
} else {
_voxels.setDataSourceID(voxelServer->getNodeID());
_voxels.parseData(packetData, messageLength);
_voxels.setDataSourceID(UNKNOWN_NODE_ID);
}
voxelServer->unlock();
}
}
}
// Receive packets from other nodes/servers and decide what to do with them!
void* Application::networkReceive(void* args) {
sockaddr senderAddress;
@ -4070,41 +4158,8 @@ void* Application::networkReceive(void* args) {
case PACKET_TYPE_ERASE_VOXEL:
case PACKET_TYPE_VOXEL_STATS:
case PACKET_TYPE_ENVIRONMENT_DATA: {
unsigned char* messageData = app->_incomingPacket;
ssize_t messageLength = bytesReceived;
// note: PACKET_TYPE_VOXEL_STATS can have PACKET_TYPE_VOXEL_DATA or PACKET_TYPE_VOXEL_DATA_MONOCHROME
// immediately following them inside the same packet. So, we process the PACKET_TYPE_VOXEL_STATS first
// then process any remaining bytes as if it was another packet
if (messageData[0] == PACKET_TYPE_VOXEL_STATS) {
int statsMessageLength = app->parseVoxelStats(messageData, messageLength, senderAddress);
if (messageLength > statsMessageLength) {
messageData += statsMessageLength;
messageLength -= statsMessageLength;
if (!packetVersionMatch(messageData)) {
break; // bail since piggyback data doesn't match our versioning
}
} else {
break; // bail since no piggyback data
}
} // fall through to piggyback message
if (app->_renderVoxels->isChecked()) {
Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress);
if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) {
voxelServer->lock();
if (messageData[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
app->_environment.parseData(&senderAddress, messageData, messageLength);
} else {
app->_voxels.setDataSourceID(voxelServer->getNodeID());
app->_voxels.parseData(messageData, messageLength);
app->_voxels.setDataSourceID(UNKNOWN_NODE_ID);
}
voxelServer->unlock();
}
}
// add this packet to our list of voxel packets and process them on the voxel processing
app->queueVoxelPacket(senderAddress, app->_incomingPacket, bytesReceived);
break;
}
case PACKET_TYPE_BULK_AVATAR_DATA:

View file

@ -19,6 +19,7 @@
#include <QTouchEvent>
#include <QList>
#include <NetworkPacket.h>
#include <NodeList.h>
#include <PacketHeaders.h>
@ -69,8 +70,6 @@ static const float NODE_KILLED_RED = 1.0f;
static const float NODE_KILLED_GREEN = 0.0f;
static const float NODE_KILLED_BLUE = 0.0f;
class Application : public QApplication, public NodeListHook {
Q_OBJECT
@ -175,7 +174,7 @@ private slots:
void doTrueVoxelColors();
void doTreeStats();
void setWantsMonochrome(bool wantsMonochrome);
void setWantsLowResMoving(bool wantsLowResMoving);
void disableLowResMoving(bool disableLowResMoving);
void disableDeltaSending(bool disableDeltaSending);
void disableOcclusionCulling(bool disableOcclusionCulling);
void updateVoxelModeActions();
@ -264,7 +263,11 @@ private:
QAction* checkedVoxelModeAction() const;
static void attachNewHeadToNode(Node *newNode);
static void* networkReceive(void* args);
static void* networkReceive(void* args); // network receive thread
static void* processVoxels(void* args); // voxel parsing thread
void processVoxelPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength);
void queueVoxelPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength);
// methodes handling menu settings
typedef void(*settingsAction)(QSettings*, QAction*);
@ -317,6 +320,7 @@ private:
QAction* _noise;
QAction* _occlusionCulling;
QAction* _wantCollisionsOn;
QAction* _renderPipelineWarnings;
QAction* _renderCoverageMapV2;
QAction* _renderCoverageMap;
@ -455,6 +459,12 @@ private:
pthread_t _networkReceiveThread;
bool _stopNetworkReceiveThread;
bool _enableProcessVoxelsThread;
pthread_t _processVoxelsThread;
bool _stopProcessVoxelsThread;
std::vector<NetworkPacket> _voxelPackets;
unsigned char _incomingPacket[MAX_PACKET_SIZE];
int _packetCount;
int _packetsPerSecond;

View file

@ -13,11 +13,11 @@
#include "VoxelFade.h"
const float VoxelFade::FADE_OUT_START = 0.5f;
const float VoxelFade::FADE_OUT_END = 0.0f;
const float VoxelFade::FADE_OUT_STEP = -0.005f;
const float VoxelFade::FADE_IN_START = 0.0f;
const float VoxelFade::FADE_OUT_END = 0.05f;
const float VoxelFade::FADE_OUT_STEP = 0.9f;
const float VoxelFade::FADE_IN_START = 0.05f;
const float VoxelFade::FADE_IN_END = 0.5f;
const float VoxelFade::FADE_IN_STEP = 0.005f;
const float VoxelFade::FADE_IN_STEP = 1.1f;
const float VoxelFade::DEFAULT_RED = 0.5f;
const float VoxelFade::DEFAULT_GREEN = 0.5f;
const float VoxelFade::DEFAULT_BLUE = 0.5f;
@ -45,7 +45,7 @@ void VoxelFade::render() {
glPopMatrix();
glEnable(GL_LIGHTING);
opacity += (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP;
opacity *= (direction == FADE_OUT) ? FADE_OUT_STEP : FADE_IN_STEP;
}
bool VoxelFade::isDone() const {

View file

@ -39,7 +39,7 @@ AvatarData::AvatarData(Node* owningNode) :
_keyState(NO_KEY_DOWN),
_wantColor(true),
_wantDelta(true),
_wantLowResMoving(false),
_wantLowResMoving(true),
_wantOcclusionCulling(true),
_headData(NULL),
_handData(NULL)

View file

@ -0,0 +1,29 @@
//
// NetworkPacket.cpp
// shared
//
// Created by Brad Hefta-Gaub on 8/9/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
// A really simple class that stores a network packet between being received and being processed
//
#include <cstring>
#include <QtDebug>
#include "NetworkPacket.h"
NetworkPacket::NetworkPacket() : _packetLength(0) {
}
NetworkPacket::NetworkPacket(const NetworkPacket& packet) {
memcpy(&_senderAddress, &packet.getSenderAddress(), sizeof(_senderAddress));
_packetLength = packet.getLength();
memcpy(&_packetData[0], packet.getData(), _packetLength);
}
NetworkPacket::NetworkPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength) {
memcpy(&_senderAddress, &senderAddress, sizeof(_senderAddress));
_packetLength = packetLength;
memcpy(&_packetData[0], packetData, packetLength);
};

View file

@ -0,0 +1,40 @@
//
// NetworkPacket.h
// shared
//
// Created by Brad Hefta-Gaub on 8/9/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
// A really simple class that stores a network packet between being received and being processed
//
#ifndef __shared_NetworkPacket__
#define __shared_NetworkPacket__
#include <stdlib.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include "NodeList.h" // for MAX_PACKET_SIZE
class NetworkPacket {
public:
NetworkPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength);
NetworkPacket(const NetworkPacket& packet);
NetworkPacket();
//~NetworkPacket();
sockaddr& getSenderAddress() { return _senderAddress; };
ssize_t getLength() const { return _packetLength; };
unsigned char* getData() { return &_packetData[0]; };
const sockaddr& getSenderAddress() const { return _senderAddress; };
const unsigned char* getData() const { return &_packetData[0]; };
private:
sockaddr _senderAddress;
ssize_t _packetLength;
unsigned char _packetData[MAX_PACKET_SIZE];
};
#endif /* defined(__shared_NetworkPacket__) */

View file

@ -101,7 +101,7 @@ int main(int argc, const char * argv[])
// jurisdiction of the server
// This hack assumes the end nodes for demo dinner since it only guarantees
// nodes in the 8 child voxels of the main root voxel
const float verySmall = verySmall;
const float verySmall = 0.015625;
endNodeTree.createVoxel(0.0, 0.0, 0.0, verySmall, 1, 1, 1, true);
endNodeTree.createVoxel(1.0, 0.0, 0.0, verySmall, 1, 1, 1, true);
endNodeTree.createVoxel(0.0, 1.0, 0.0, verySmall, 1, 1, 1, true);