mirror of
https://github.com/overte-org/overte.git
synced 2025-07-26 09:18:26 +02:00
Merge pull request #2120 from ZappoMan/seeing_voxels
Voxel Scale Testing: Seeing voxels & particles in JS & OctreeServer improvements
This commit is contained in:
commit
cdda220c83
33 changed files with 795 additions and 197 deletions
|
@ -39,6 +39,7 @@ void Agent::readPendingDatagrams() {
|
||||||
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
|
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
|
||||||
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
||||||
PacketType datagramPacketType = packetTypeForPacket(receivedPacket);
|
PacketType datagramPacketType = packetTypeForPacket(receivedPacket);
|
||||||
|
|
||||||
if (datagramPacketType == PacketTypeJurisdiction) {
|
if (datagramPacketType == PacketTypeJurisdiction) {
|
||||||
int headerBytes = numBytesForPacketHeader(receivedPacket);
|
int headerBytes = numBytesForPacketHeader(receivedPacket);
|
||||||
|
|
||||||
|
@ -48,12 +49,12 @@ void Agent::readPendingDatagrams() {
|
||||||
// PacketType_JURISDICTION, first byte is the node type...
|
// PacketType_JURISDICTION, first byte is the node type...
|
||||||
switch (receivedPacket[headerBytes]) {
|
switch (receivedPacket[headerBytes]) {
|
||||||
case NodeType::VoxelServer:
|
case NodeType::VoxelServer:
|
||||||
_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
|
_scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->
|
||||||
receivedPacket);
|
queueReceivedPacket(matchedNode,receivedPacket);
|
||||||
break;
|
break;
|
||||||
case NodeType::ParticleServer:
|
case NodeType::ParticleServer:
|
||||||
_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(matchedNode,
|
_scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->
|
||||||
receivedPacket);
|
queueReceivedPacket(matchedNode, receivedPacket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,44 @@ void Agent::readPendingDatagrams() {
|
||||||
Particle::handleAddParticleResponse(receivedPacket);
|
Particle::handleAddParticleResponse(receivedPacket);
|
||||||
|
|
||||||
// also give our local particle tree a chance to remap any internal locally created particles
|
// also give our local particle tree a chance to remap any internal locally created particles
|
||||||
_particleTree.handleAddParticleResponse(receivedPacket);
|
_particleViewer.getTree()->handleAddParticleResponse(receivedPacket);
|
||||||
|
|
||||||
|
} else if (datagramPacketType == PacketTypeParticleData
|
||||||
|
|| datagramPacketType == PacketTypeParticleErase
|
||||||
|
|| datagramPacketType == PacketTypeOctreeStats
|
||||||
|
|| datagramPacketType == PacketTypeVoxelData
|
||||||
|
) {
|
||||||
|
SharedNodePointer sourceNode = nodeList->sendingNodeForPacket(receivedPacket);
|
||||||
|
QByteArray mutablePacket = receivedPacket;
|
||||||
|
ssize_t messageLength = mutablePacket.size();
|
||||||
|
|
||||||
|
if (datagramPacketType == PacketTypeOctreeStats) {
|
||||||
|
|
||||||
|
int statsMessageLength = OctreeHeadlessViewer::parseOctreeStats(mutablePacket, sourceNode);
|
||||||
|
if (messageLength > statsMessageLength) {
|
||||||
|
mutablePacket = mutablePacket.mid(statsMessageLength);
|
||||||
|
|
||||||
|
// TODO: this needs to be fixed, the goal is to test the packet version for the piggyback, but
|
||||||
|
// this is testing the version and hash of the original packet
|
||||||
|
// need to use numBytesArithmeticCodingFromBuffer()...
|
||||||
|
if (!NodeList::getInstance()->packetVersionAndHashMatch(receivedPacket)) {
|
||||||
|
return; // bail since piggyback data doesn't match our versioning
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return; // bail since no piggyback data
|
||||||
|
}
|
||||||
|
|
||||||
|
datagramPacketType = packetTypeForPacket(mutablePacket);
|
||||||
|
} // fall through to piggyback message
|
||||||
|
|
||||||
|
if (datagramPacketType == PacketTypeParticleData || datagramPacketType == PacketTypeParticleErase) {
|
||||||
|
_particleViewer.processDatagram(mutablePacket, sourceNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datagramPacketType == PacketTypeVoxelData) {
|
||||||
|
_voxelViewer.processDatagram(mutablePacket, sourceNode);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
|
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
|
||||||
}
|
}
|
||||||
|
@ -110,9 +148,6 @@ void Agent::run() {
|
||||||
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
||||||
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
|
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
|
||||||
|
|
||||||
// tell our script engine about our local particle tree
|
|
||||||
_scriptEngine.getParticlesScriptingInterface()->setParticleTree(&_particleTree);
|
|
||||||
|
|
||||||
// setup an Avatar for the script to use
|
// setup an Avatar for the script to use
|
||||||
AvatarData scriptedAvatar;
|
AvatarData scriptedAvatar;
|
||||||
|
|
||||||
|
@ -126,6 +161,21 @@ void Agent::run() {
|
||||||
// register ourselves to the script engine
|
// register ourselves to the script engine
|
||||||
_scriptEngine.registerGlobalObject("Agent", this);
|
_scriptEngine.registerGlobalObject("Agent", this);
|
||||||
|
|
||||||
|
_scriptEngine.init(); // must be done before we set up the viewers
|
||||||
|
|
||||||
|
_scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer);
|
||||||
|
// connect the VoxelViewer and the VoxelScriptingInterface to each other
|
||||||
|
JurisdictionListener* voxelJL = _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener();
|
||||||
|
_voxelViewer.setJurisdictionListener(voxelJL);
|
||||||
|
_voxelViewer.init();
|
||||||
|
_scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree());
|
||||||
|
|
||||||
|
_scriptEngine.registerGlobalObject("ParticleViewer", &_particleViewer);
|
||||||
|
JurisdictionListener* particleJL = _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener();
|
||||||
|
_particleViewer.setJurisdictionListener(particleJL);
|
||||||
|
_particleViewer.init();
|
||||||
|
_scriptEngine.getParticlesScriptingInterface()->setParticleTree(_particleViewer.getTree());
|
||||||
|
|
||||||
_scriptEngine.setScriptContents(scriptContents);
|
_scriptEngine.setScriptContents(scriptContents);
|
||||||
_scriptEngine.run();
|
_scriptEngine.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,11 @@
|
||||||
|
|
||||||
#include <ParticleEditPacketSender.h>
|
#include <ParticleEditPacketSender.h>
|
||||||
#include <ParticleTree.h>
|
#include <ParticleTree.h>
|
||||||
|
#include <ParticleTreeHeadlessViewer.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
#include <ThreadedAssignment.h>
|
#include <ThreadedAssignment.h>
|
||||||
#include <VoxelEditPacketSender.h>
|
#include <VoxelEditPacketSender.h>
|
||||||
|
#include <VoxelTreeHeadlessViewer.h>
|
||||||
|
|
||||||
|
|
||||||
class Agent : public ThreadedAssignment {
|
class Agent : public ThreadedAssignment {
|
||||||
|
@ -41,9 +43,11 @@ signals:
|
||||||
void willSendVisualDataCallback();
|
void willSendVisualDataCallback();
|
||||||
private:
|
private:
|
||||||
ScriptEngine _scriptEngine;
|
ScriptEngine _scriptEngine;
|
||||||
ParticleTree _particleTree;
|
|
||||||
VoxelEditPacketSender _voxelEditSender;
|
VoxelEditPacketSender _voxelEditSender;
|
||||||
ParticleEditPacketSender _particleEditSender;
|
ParticleEditPacketSender _particleEditSender;
|
||||||
|
|
||||||
|
ParticleTreeHeadlessViewer _particleViewer;
|
||||||
|
VoxelTreeHeadlessViewer _voxelViewer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__Agent__) */
|
#endif /* defined(__hifi__Agent__) */
|
||||||
|
|
|
@ -161,7 +161,7 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, int bytes) {
|
||||||
OctreeQueryNode::~OctreeQueryNode() {
|
OctreeQueryNode::~OctreeQueryNode() {
|
||||||
if (_octreeSendThread) {
|
if (_octreeSendThread) {
|
||||||
_octreeSendThread->terminate();
|
_octreeSendThread->terminate();
|
||||||
_octreeSendThread->deleteLater();
|
delete _octreeSendThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] _octreePacket;
|
delete[] _octreePacket;
|
||||||
|
|
|
@ -22,8 +22,16 @@ OctreeSendThread::OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer
|
||||||
_myServer(myServer),
|
_myServer(myServer),
|
||||||
_packetData()
|
_packetData()
|
||||||
{
|
{
|
||||||
|
qDebug() << "client connected";
|
||||||
|
_myServer->clientConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OctreeSendThread::~OctreeSendThread() {
|
||||||
|
qDebug() << "client disconnected";
|
||||||
|
_myServer->clientDisconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool OctreeSendThread::process() {
|
bool OctreeSendThread::process() {
|
||||||
quint64 start = usecTimestampNow();
|
quint64 start = usecTimestampNow();
|
||||||
bool gotLock = false;
|
bool gotLock = false;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
class OctreeSendThread : public GenericThread {
|
class OctreeSendThread : public GenericThread {
|
||||||
public:
|
public:
|
||||||
OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer);
|
OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer);
|
||||||
|
virtual ~OctreeSendThread();
|
||||||
|
|
||||||
static quint64 _totalBytes;
|
static quint64 _totalBytes;
|
||||||
static quint64 _totalWastedBytes;
|
static quint64 _totalWastedBytes;
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include "OctreeServerConsts.h"
|
#include "OctreeServerConsts.h"
|
||||||
|
|
||||||
OctreeServer* OctreeServer::_instance = NULL;
|
OctreeServer* OctreeServer::_instance = NULL;
|
||||||
|
int OctreeServer::_clientCount = 0;
|
||||||
|
|
||||||
|
|
||||||
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
|
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
|
||||||
if (newNode->getLinkedData() == NULL) {
|
if (newNode->getLinkedData() == NULL) {
|
||||||
|
@ -35,6 +37,7 @@ OctreeServer::OctreeServer(const QByteArray& packet) :
|
||||||
_parsedArgV(NULL),
|
_parsedArgV(NULL),
|
||||||
_httpManager(NULL),
|
_httpManager(NULL),
|
||||||
_packetsPerClientPerInterval(10),
|
_packetsPerClientPerInterval(10),
|
||||||
|
_packetsTotalPerInterval(DEFAULT_PACKETS_PER_INTERVAL),
|
||||||
_tree(NULL),
|
_tree(NULL),
|
||||||
_wantPersist(true),
|
_wantPersist(true),
|
||||||
_debugSending(false),
|
_debugSending(false),
|
||||||
|
@ -75,8 +78,7 @@ OctreeServer::~OctreeServer() {
|
||||||
|
|
||||||
delete _jurisdiction;
|
delete _jurisdiction;
|
||||||
_jurisdiction = NULL;
|
_jurisdiction = NULL;
|
||||||
|
qDebug() << "OctreeServer::~OctreeServer()... DONE";
|
||||||
qDebug() << "OctreeServer::run()... DONE";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeServer::initHTTPManager(int port) {
|
void OctreeServer::initHTTPManager(int port) {
|
||||||
|
@ -155,12 +157,24 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
statsString += "Uptime: ";
|
statsString += "Uptime: ";
|
||||||
|
|
||||||
if (hours > 0) {
|
if (hours > 0) {
|
||||||
statsString += QString("%1 hour%2").arg(hours).arg((hours > 1) ? "s" : "");
|
statsString += QString("%1 hour").arg(hours);
|
||||||
|
if (hours > 1) {
|
||||||
|
statsString += QString("s");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (minutes > 0) {
|
if (minutes > 0) {
|
||||||
statsString += QString("%1 minute%s").arg(minutes).arg((minutes > 1) ? "s" : "");
|
if (hours > 0) {
|
||||||
|
statsString += QString(" ");
|
||||||
|
}
|
||||||
|
statsString += QString("%1 minute").arg(minutes);
|
||||||
|
if (minutes > 1) {
|
||||||
|
statsString += QString("s");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (seconds > 0) {
|
if (seconds > 0) {
|
||||||
|
if (hours > 0 || minutes > 0) {
|
||||||
|
statsString += QString(" ");
|
||||||
|
}
|
||||||
statsString += QString().sprintf("%.3f seconds", seconds);
|
statsString += QString().sprintf("%.3f seconds", seconds);
|
||||||
}
|
}
|
||||||
statsString += "\r\n\r\n";
|
statsString += "\r\n\r\n";
|
||||||
|
@ -180,14 +194,26 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
int minutes = (msecsElapsed/(MSECS_PER_MIN)) % MIN_PER_HOUR;
|
int minutes = (msecsElapsed/(MSECS_PER_MIN)) % MIN_PER_HOUR;
|
||||||
int hours = (msecsElapsed/(MSECS_PER_MIN * MIN_PER_HOUR));
|
int hours = (msecsElapsed/(MSECS_PER_MIN * MIN_PER_HOUR));
|
||||||
|
|
||||||
statsString += QString("%1 File Load Took").arg(getMyServerName());
|
statsString += QString("%1 File Load Took ").arg(getMyServerName());
|
||||||
if (hours > 0) {
|
if (hours > 0) {
|
||||||
statsString += QString("%1 hour%2").arg(hours).arg((hours > 1) ? "s" : "");
|
statsString += QString("%1 hour").arg(hours);
|
||||||
|
if (hours > 1) {
|
||||||
|
statsString += QString("s");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (minutes > 0) {
|
if (minutes > 0) {
|
||||||
statsString += QString("%1 minute%2").arg(minutes).arg((minutes > 1) ? "s" : "");
|
if (hours > 0) {
|
||||||
|
statsString += QString(" ");
|
||||||
|
}
|
||||||
|
statsString += QString("%1 minute").arg(minutes);
|
||||||
|
if (minutes > 1) {
|
||||||
|
statsString += QString("s");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (seconds >= 0) {
|
if (seconds >= 0) {
|
||||||
|
if (hours > 0 || minutes > 0) {
|
||||||
|
statsString += QString(" ");
|
||||||
|
}
|
||||||
statsString += QString().sprintf("%.3f seconds", seconds);
|
statsString += QString().sprintf("%.3f seconds", seconds);
|
||||||
}
|
}
|
||||||
statsString += "\r\n";
|
statsString += "\r\n";
|
||||||
|
@ -234,6 +260,13 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
quint64 totalBytesOfColor = OctreePacketData::getTotalBytesOfColor();
|
quint64 totalBytesOfColor = OctreePacketData::getTotalBytesOfColor();
|
||||||
|
|
||||||
const int COLUMN_WIDTH = 10;
|
const int COLUMN_WIDTH = 10;
|
||||||
|
statsString += QString(" Configured Max PPS/Client: %1 pps/client\r\n")
|
||||||
|
.arg(locale.toString((uint)getPacketsPerClientPerSecond()).rightJustified(COLUMN_WIDTH, ' '));
|
||||||
|
statsString += QString(" Configured Max PPS/Server: %1 pps/server\r\n\r\n")
|
||||||
|
.arg(locale.toString((uint)getPacketsTotalPerSecond()).rightJustified(COLUMN_WIDTH, ' '));
|
||||||
|
statsString += QString(" Total Clients Connected: %1 clients\r\n\r\n")
|
||||||
|
.arg(locale.toString((uint)getCurrentClientCount()).rightJustified(COLUMN_WIDTH, ' '));
|
||||||
|
|
||||||
statsString += QString(" Total Outbound Packets: %1 packets\r\n")
|
statsString += QString(" Total Outbound Packets: %1 packets\r\n")
|
||||||
.arg(locale.toString((uint)totalOutboundPackets).rightJustified(COLUMN_WIDTH, ' '));
|
.arg(locale.toString((uint)totalOutboundPackets).rightJustified(COLUMN_WIDTH, ' '));
|
||||||
statsString += QString(" Total Outbound Bytes: %1 bytes\r\n")
|
statsString += QString(" Total Outbound Bytes: %1 bytes\r\n")
|
||||||
|
@ -612,15 +645,28 @@ void OctreeServer::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the user passed in a command line option for setting packet send rate
|
// Check to see if the user passed in a command line option for setting packet send rate
|
||||||
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
const char* PACKETS_PER_SECOND_PER_CLIENT_MAX = "--packetsPerSecondPerClientMax";
|
||||||
const char* packetsPerSecond = getCmdOption(_argc, _argv, PACKETS_PER_SECOND);
|
const char* packetsPerSecondPerClientMax = getCmdOption(_argc, _argv, PACKETS_PER_SECOND_PER_CLIENT_MAX);
|
||||||
if (packetsPerSecond) {
|
if (packetsPerSecondPerClientMax) {
|
||||||
_packetsPerClientPerInterval = atoi(packetsPerSecond) / INTERVALS_PER_SECOND;
|
_packetsPerClientPerInterval = atoi(packetsPerSecondPerClientMax) / INTERVALS_PER_SECOND;
|
||||||
if (_packetsPerClientPerInterval < 1) {
|
if (_packetsPerClientPerInterval < 1) {
|
||||||
_packetsPerClientPerInterval = 1;
|
_packetsPerClientPerInterval = 1;
|
||||||
}
|
}
|
||||||
qDebug("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d", packetsPerSecond, _packetsPerClientPerInterval);
|
|
||||||
}
|
}
|
||||||
|
qDebug("packetsPerSecondPerClientMax=%s _packetsPerClientPerInterval=%d",
|
||||||
|
packetsPerSecondPerClientMax, _packetsPerClientPerInterval);
|
||||||
|
|
||||||
|
// Check to see if the user passed in a command line option for setting packet send rate
|
||||||
|
const char* PACKETS_PER_SECOND_TOTAL_MAX = "--packetsPerSecondTotalMax";
|
||||||
|
const char* packetsPerSecondTotalMax = getCmdOption(_argc, _argv, PACKETS_PER_SECOND_TOTAL_MAX);
|
||||||
|
if (packetsPerSecondTotalMax) {
|
||||||
|
_packetsTotalPerInterval = atoi(packetsPerSecondTotalMax) / INTERVALS_PER_SECOND;
|
||||||
|
if (_packetsTotalPerInterval < 1) {
|
||||||
|
_packetsTotalPerInterval = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug("packetsPerSecondTotalMax=%s _packetsTotalPerInterval=%d",
|
||||||
|
packetsPerSecondTotalMax, _packetsTotalPerInterval);
|
||||||
|
|
||||||
HifiSockAddr senderSockAddr;
|
HifiSockAddr senderSockAddr;
|
||||||
|
|
||||||
|
@ -656,3 +702,4 @@ void OctreeServer::run() {
|
||||||
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
||||||
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
|
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "OctreeServerConsts.h"
|
#include "OctreeServerConsts.h"
|
||||||
#include "OctreeInboundPacketProcessor.h"
|
#include "OctreeInboundPacketProcessor.h"
|
||||||
|
|
||||||
|
const int DEFAULT_PACKETS_PER_INTERVAL = 2000; // some 120,000 packets per second total
|
||||||
|
|
||||||
/// Handles assignments of type OctreeServer - sending octrees to various clients.
|
/// Handles assignments of type OctreeServer - sending octrees to various clients.
|
||||||
class OctreeServer : public ThreadedAssignment, public HTTPRequestHandler {
|
class OctreeServer : public ThreadedAssignment, public HTTPRequestHandler {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -41,7 +43,16 @@ public:
|
||||||
Octree* getOctree() { return _tree; }
|
Octree* getOctree() { return _tree; }
|
||||||
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
|
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
|
||||||
|
|
||||||
int getPacketsPerClientPerInterval() const { return _packetsPerClientPerInterval; }
|
int getPacketsPerClientPerInterval() const { return std::min(_packetsPerClientPerInterval,
|
||||||
|
std::max(1, getPacketsTotalPerInterval() / std::max(1, getCurrentClientCount()))); }
|
||||||
|
|
||||||
|
int getPacketsPerClientPerSecond() const { return getPacketsPerClientPerInterval() * INTERVALS_PER_SECOND; }
|
||||||
|
int getPacketsTotalPerInterval() const { return _packetsTotalPerInterval; }
|
||||||
|
int getPacketsTotalPerSecond() const { return getPacketsTotalPerInterval() * INTERVALS_PER_SECOND; }
|
||||||
|
|
||||||
|
static int getCurrentClientCount() { return _clientCount; }
|
||||||
|
static void clientConnected() { _clientCount++; }
|
||||||
|
static void clientDisconnected() { _clientCount--; }
|
||||||
|
|
||||||
bool isInitialLoadComplete() const { return (_persistThread) ? _persistThread->isInitialLoadComplete() : true; }
|
bool isInitialLoadComplete() const { return (_persistThread) ? _persistThread->isInitialLoadComplete() : true; }
|
||||||
bool isPersistEnabled() const { return (_persistThread) ? true : false; }
|
bool isPersistEnabled() const { return (_persistThread) ? true : false; }
|
||||||
|
@ -81,6 +92,7 @@ protected:
|
||||||
|
|
||||||
char _persistFilename[MAX_FILENAME_LENGTH];
|
char _persistFilename[MAX_FILENAME_LENGTH];
|
||||||
int _packetsPerClientPerInterval;
|
int _packetsPerClientPerInterval;
|
||||||
|
int _packetsTotalPerInterval;
|
||||||
Octree* _tree; // this IS a reaveraging tree
|
Octree* _tree; // this IS a reaveraging tree
|
||||||
bool _wantPersist;
|
bool _wantPersist;
|
||||||
bool _debugSending;
|
bool _debugSending;
|
||||||
|
@ -95,6 +107,8 @@ protected:
|
||||||
|
|
||||||
time_t _started;
|
time_t _started;
|
||||||
quint64 _startedUSecs;
|
quint64 _startedUSecs;
|
||||||
|
|
||||||
|
static int _clientCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __octree_server__OctreeServer__
|
#endif // __octree_server__OctreeServer__
|
||||||
|
|
74
examples/seeingVoxelsExample.js
Normal file
74
examples/seeingVoxelsExample.js
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// seeingVoxelsExample.js
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// This is an example script
|
||||||
|
//
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
var yawDirection = -1;
|
||||||
|
var yaw = 45;
|
||||||
|
var yawMax = 70;
|
||||||
|
var yawMin = 20;
|
||||||
|
|
||||||
|
var isLocal = false;
|
||||||
|
|
||||||
|
// set up our VoxelViewer with a position and orientation
|
||||||
|
var orientation = Quat.fromPitchYawRoll(0, yaw, 0);
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (isLocal) {
|
||||||
|
MyAvatar.position = {x: 5000, y: 500, z: 5000};
|
||||||
|
MyAvatar.orientation = orientation;
|
||||||
|
} else {
|
||||||
|
VoxelViewer.setPosition({x: 5000, y: 500, z: 5000});
|
||||||
|
VoxelViewer.setOrientation(orientation);
|
||||||
|
VoxelViewer.queryOctree();
|
||||||
|
Agent.isAvatar = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keepLooking() {
|
||||||
|
//print("count =" + count);
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
if (count % 10 == 0) {
|
||||||
|
yaw += yawDirection;
|
||||||
|
orientation = Quat.fromPitchYawRoll(0, yaw, 0);
|
||||||
|
if (yaw > yawMax || yaw < yawMin) {
|
||||||
|
yawDirection = yawDirection * -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("calling VoxelViewer.queryOctree()... count=" + count + " yaw=" + yaw);
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
MyAvatar.orientation = orientation;
|
||||||
|
} else {
|
||||||
|
VoxelViewer.setOrientation(orientation);
|
||||||
|
VoxelViewer.queryOctree();
|
||||||
|
print("VoxelViewer.getOctreeElementsCount()=" + VoxelViewer.getOctreeElementsCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
print("SCRIPT ENDNG!!!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the call back so it fires before each data send
|
||||||
|
Script.willSendVisualDataCallback.connect(keepLooking);
|
||||||
|
|
||||||
|
// register our scriptEnding callback
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
||||||
|
|
||||||
|
// test for local...
|
||||||
|
Menu.isOptionChecked("Voxels");
|
||||||
|
isLocal = true; // will only get here on local client
|
|
@ -1379,6 +1379,26 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) {
|
||||||
_window->activateWindow();
|
_window->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::importVoxels() {
|
||||||
|
if (!_voxelImporter) {
|
||||||
|
_voxelImporter = new VoxelImporter(_window);
|
||||||
|
_voxelImporter->loadSettings(_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_voxelImporter->exec()) {
|
||||||
|
qDebug() << "[DEBUG] Import succeeded." << endl;
|
||||||
|
} else {
|
||||||
|
qDebug() << "[DEBUG] Import failed." << endl;
|
||||||
|
if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) {
|
||||||
|
_sharedVoxelSystem.killLocalVoxels();
|
||||||
|
_sharedVoxelSystem.changeTree(&_clipboard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore the main window's active state
|
||||||
|
_window->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
void Application::cutVoxels(const VoxelDetail& sourceVoxel) {
|
void Application::cutVoxels(const VoxelDetail& sourceVoxel) {
|
||||||
copyVoxels(sourceVoxel);
|
copyVoxels(sourceVoxel);
|
||||||
deleteVoxelAt(sourceVoxel);
|
deleteVoxelAt(sourceVoxel);
|
||||||
|
@ -1517,8 +1537,8 @@ void Application::init() {
|
||||||
|
|
||||||
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
|
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
|
||||||
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
|
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
|
||||||
_voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader));
|
_voxels.setUseVoxelShader(false);
|
||||||
_voxels.setVoxelsAsPoints(Menu::getInstance()->isOptionChecked(MenuOption::VoxelsAsPoints));
|
_voxels.setVoxelsAsPoints(false);
|
||||||
_voxels.setDisableFastVoxelPipeline(false);
|
_voxels.setDisableFastVoxelPipeline(false);
|
||||||
_voxels.init();
|
_voxels.init();
|
||||||
|
|
||||||
|
@ -1914,7 +1934,7 @@ void Application::updateMyAvatar(float deltaTime) {
|
||||||
// actually need to calculate the view frustum planes to send these details
|
// actually need to calculate the view frustum planes to send these details
|
||||||
// to the server.
|
// to the server.
|
||||||
loadViewFrustum(_myCamera, _viewFrustum);
|
loadViewFrustum(_myCamera, _viewFrustum);
|
||||||
|
|
||||||
// Update my voxel servers with my current voxel query...
|
// Update my voxel servers with my current voxel query...
|
||||||
queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
|
queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions);
|
||||||
queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
|
queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions);
|
||||||
|
@ -1927,26 +1947,28 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//qDebug() << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
|
||||||
|
|
||||||
bool wantExtraDebugging = getLogger()->extraDebugging();
|
bool wantExtraDebugging = getLogger()->extraDebugging();
|
||||||
|
|
||||||
// These will be the same for all servers, so we can set them up once and then reuse for each server we send to.
|
// These will be the same for all servers, so we can set them up once and then reuse for each server we send to.
|
||||||
_voxelQuery.setWantLowResMoving(!Menu::getInstance()->isOptionChecked(MenuOption::DisableLowRes));
|
_octreeQuery.setWantLowResMoving(true);
|
||||||
_voxelQuery.setWantColor(!Menu::getInstance()->isOptionChecked(MenuOption::DisableColorVoxels));
|
_octreeQuery.setWantColor(true);
|
||||||
_voxelQuery.setWantDelta(!Menu::getInstance()->isOptionChecked(MenuOption::DisableDeltaSending));
|
_octreeQuery.setWantDelta(true);
|
||||||
_voxelQuery.setWantOcclusionCulling(Menu::getInstance()->isOptionChecked(MenuOption::EnableOcclusionCulling));
|
_octreeQuery.setWantOcclusionCulling(false);
|
||||||
_voxelQuery.setWantCompression(Menu::getInstance()->isOptionChecked(MenuOption::EnableVoxelPacketCompression));
|
_octreeQuery.setWantCompression(true);
|
||||||
|
|
||||||
_voxelQuery.setCameraPosition(_viewFrustum.getPosition());
|
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());
|
||||||
_voxelQuery.setCameraOrientation(_viewFrustum.getOrientation());
|
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
|
||||||
_voxelQuery.setCameraFov(_viewFrustum.getFieldOfView());
|
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
|
||||||
_voxelQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
|
_octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
|
||||||
_voxelQuery.setCameraNearClip(_viewFrustum.getNearClip());
|
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
|
||||||
_voxelQuery.setCameraFarClip(_viewFrustum.getFarClip());
|
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
|
||||||
_voxelQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
|
_octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
|
||||||
_voxelQuery.setOctreeSizeScale(Menu::getInstance()->getVoxelSizeScale());
|
_octreeQuery.setOctreeSizeScale(Menu::getInstance()->getVoxelSizeScale());
|
||||||
_voxelQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust());
|
_octreeQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust());
|
||||||
|
|
||||||
unsigned char voxelQueryPacket[MAX_PACKET_SIZE];
|
unsigned char queryPacket[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
// Iterate all of the nodes, and get a count of how many voxel servers we have...
|
// Iterate all of the nodes, and get a count of how many voxel servers we have...
|
||||||
int totalServers = 0;
|
int totalServers = 0;
|
||||||
|
@ -1986,7 +2008,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wantExtraDebugging && unknownJurisdictionServers > 0) {
|
if (wantExtraDebugging) {
|
||||||
qDebug("Servers: total %d, in view %d, unknown jurisdiction %d",
|
qDebug("Servers: total %d, in view %d, unknown jurisdiction %d",
|
||||||
totalServers, inViewServers, unknownJurisdictionServers);
|
totalServers, inViewServers, unknownJurisdictionServers);
|
||||||
}
|
}
|
||||||
|
@ -2007,7 +2029,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wantExtraDebugging && unknownJurisdictionServers > 0) {
|
if (wantExtraDebugging) {
|
||||||
qDebug("perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer);
|
qDebug("perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2056,7 +2078,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inView) {
|
if (inView) {
|
||||||
_voxelQuery.setMaxOctreePacketsPerSecond(perServerPPS);
|
_octreeQuery.setMaxOctreePacketsPerSecond(perServerPPS);
|
||||||
} else if (unknownView) {
|
} else if (unknownView) {
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "no known jurisdiction for node " << *node << ", give it budget of "
|
qDebug() << "no known jurisdiction for node " << *node << ", give it budget of "
|
||||||
|
@ -2067,11 +2089,11 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
// If there's only one server, then don't do this, and just let the normal voxel query pass through
|
// If there's only one server, then don't do this, and just let the normal voxel query pass through
|
||||||
// as expected... this way, we will actually get a valid scene if there is one to be seen
|
// as expected... this way, we will actually get a valid scene if there is one to be seen
|
||||||
if (totalServers > 1) {
|
if (totalServers > 1) {
|
||||||
_voxelQuery.setCameraPosition(glm::vec3(-0.1,-0.1,-0.1));
|
_octreeQuery.setCameraPosition(glm::vec3(-0.1,-0.1,-0.1));
|
||||||
const glm::quat OFF_IN_NEGATIVE_SPACE = glm::quat(-0.5, 0, -0.5, 1.0);
|
const glm::quat OFF_IN_NEGATIVE_SPACE = glm::quat(-0.5, 0, -0.5, 1.0);
|
||||||
_voxelQuery.setCameraOrientation(OFF_IN_NEGATIVE_SPACE);
|
_octreeQuery.setCameraOrientation(OFF_IN_NEGATIVE_SPACE);
|
||||||
_voxelQuery.setCameraNearClip(0.1f);
|
_octreeQuery.setCameraNearClip(0.1f);
|
||||||
_voxelQuery.setCameraFarClip(0.1f);
|
_octreeQuery.setCameraFarClip(0.1f);
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "Using 'minimal' camera position for node" << *node;
|
qDebug() << "Using 'minimal' camera position for node" << *node;
|
||||||
}
|
}
|
||||||
|
@ -2080,23 +2102,23 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
qDebug() << "Using regular camera position for node" << *node;
|
qDebug() << "Using regular camera position for node" << *node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_voxelQuery.setMaxOctreePacketsPerSecond(perUnknownServer);
|
_octreeQuery.setMaxOctreePacketsPerSecond(perUnknownServer);
|
||||||
} else {
|
} else {
|
||||||
_voxelQuery.setMaxOctreePacketsPerSecond(0);
|
_octreeQuery.setMaxOctreePacketsPerSecond(0);
|
||||||
}
|
}
|
||||||
// set up the packet for sending...
|
// set up the packet for sending...
|
||||||
unsigned char* endOfVoxelQueryPacket = voxelQueryPacket;
|
unsigned char* endOfQueryPacket = queryPacket;
|
||||||
|
|
||||||
// insert packet type/version and node UUID
|
// insert packet type/version and node UUID
|
||||||
endOfVoxelQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfVoxelQueryPacket), packetType);
|
endOfQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType);
|
||||||
|
|
||||||
// encode the query data...
|
// encode the query data...
|
||||||
endOfVoxelQueryPacket += _voxelQuery.getBroadcastData(endOfVoxelQueryPacket);
|
endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket);
|
||||||
|
|
||||||
int packetLength = endOfVoxelQueryPacket - voxelQueryPacket;
|
int packetLength = endOfQueryPacket - queryPacket;
|
||||||
|
|
||||||
// make sure we still have an active socket
|
// make sure we still have an active socket
|
||||||
nodeList->writeDatagram(reinterpret_cast<const char*>(voxelQueryPacket), packetLength, node);
|
nodeList->writeDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||||
|
|
||||||
// Feed number of bytes to corresponding channel of the bandwidth meter
|
// Feed number of bytes to corresponding channel of the bandwidth meter
|
||||||
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength);
|
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength);
|
||||||
|
@ -2338,14 +2360,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... voxels...");
|
"Application::displaySide() ... voxels...");
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DontRenderVoxels)) {
|
|
||||||
_voxels.render();
|
_voxels.render();
|
||||||
|
|
||||||
// double check that our LOD doesn't need to be auto-adjusted
|
// double check that our LOD doesn't need to be auto-adjusted
|
||||||
// only adjust if our option is set
|
// adjust it unless we were asked to disable this feature
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AutoAdjustLOD)) {
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
|
||||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3403,7 +3424,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
// If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
||||||
_voxelServerJurisdictions.erase(nodeUUID);
|
_voxelServerJurisdictions.erase(_voxelServerJurisdictions.find(nodeUUID));
|
||||||
}
|
}
|
||||||
|
|
||||||
// also clean up scene stats for that server
|
// also clean up scene stats for that server
|
||||||
|
@ -3434,7 +3455,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
// If the voxel server is going away, remove it from our jurisdiction map so we don't send voxels to a dead server
|
||||||
_particleServerJurisdictions.erase(nodeUUID);
|
_particleServerJurisdictions.erase(_particleServerJurisdictions.find(nodeUUID));
|
||||||
}
|
}
|
||||||
|
|
||||||
// also clean up scene stats for that server
|
// also clean up scene stats for that server
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <ParticleCollisionSystem.h>
|
#include <ParticleCollisionSystem.h>
|
||||||
#include <ParticleEditPacketSender.h>
|
#include <ParticleEditPacketSender.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
#include <VoxelQuery.h>
|
#include <OctreeQuery.h>
|
||||||
|
|
||||||
#include "Audio.h"
|
#include "Audio.h"
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ public slots:
|
||||||
void nodeKilled(SharedNodePointer node);
|
void nodeKilled(SharedNodePointer node);
|
||||||
void packetSent(quint64 length);
|
void packetSent(quint64 length);
|
||||||
|
|
||||||
|
void importVoxels(); // doesn't include source voxel because it goes to clipboard
|
||||||
void cutVoxels(const VoxelDetail& sourceVoxel);
|
void cutVoxels(const VoxelDetail& sourceVoxel);
|
||||||
void copyVoxels(const VoxelDetail& sourceVoxel);
|
void copyVoxels(const VoxelDetail& sourceVoxel);
|
||||||
void pasteVoxels(const VoxelDetail& sourceVoxel);
|
void pasteVoxels(const VoxelDetail& sourceVoxel);
|
||||||
|
@ -387,7 +388,7 @@ private:
|
||||||
|
|
||||||
Oscilloscope _audioScope;
|
Oscilloscope _audioScope;
|
||||||
|
|
||||||
VoxelQuery _voxelQuery; // NodeData derived class for querying voxels from voxel server
|
OctreeQuery _octreeQuery; // NodeData derived class for querying voxels from voxel server
|
||||||
|
|
||||||
AvatarManager _avatarManager;
|
AvatarManager _avatarManager;
|
||||||
MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be)
|
MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be)
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 90.0f;
|
|
||||||
|
|
||||||
enum CameraMode
|
enum CameraMode
|
||||||
{
|
{
|
||||||
CAMERA_MODE_NULL = -1,
|
CAMERA_MODE_NULL = -1,
|
||||||
|
|
|
@ -238,29 +238,12 @@ Menu::Menu() :
|
||||||
true,
|
true,
|
||||||
appInstance,
|
appInstance,
|
||||||
SLOT(setRenderVoxels(bool)));
|
SLOT(setRenderVoxels(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontRenderVoxels);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontCallOpenGLForVoxels);
|
|
||||||
|
|
||||||
_useVoxelShader = addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0,
|
|
||||||
false, appInstance->getVoxels(), SLOT(setUseVoxelShader(bool)));
|
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelsAsPoints, 0,
|
|
||||||
false, appInstance->getVoxels(), SLOT(setVoxelsAsPoints(bool)));
|
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AutoAdjustLOD);
|
|
||||||
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
|
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
|
||||||
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges);
|
||||||
QMenu* voxelProtoOptionsMenu = voxelOptionsMenu->addMenu("Voxel Server Protocol Options");
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DisableAutoAdjustLOD);
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DisableColorVoxels);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DisableLowRes);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DisableDeltaSending);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::EnableVoxelPacketCompression);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::EnableOcclusionCulling);
|
|
||||||
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::DestructiveAddVoxel);
|
|
||||||
|
|
||||||
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ namespace MenuOption {
|
||||||
const QString AmbientOcclusion = "Ambient Occlusion";
|
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||||
const QString Avatars = "Avatars";
|
const QString Avatars = "Avatars";
|
||||||
const QString Atmosphere = "Atmosphere";
|
const QString Atmosphere = "Atmosphere";
|
||||||
const QString AutoAdjustLOD = "Automatically Adjust LOD";
|
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
|
||||||
const QString AutomaticallyAuditTree = "Automatically Audit Tree Stats";
|
const QString AutomaticallyAuditTree = "Automatically Audit Tree Stats";
|
||||||
const QString Bandwidth = "Bandwidth Display";
|
const QString Bandwidth = "Bandwidth Display";
|
||||||
const QString BandwidthDetails = "Bandwidth Details";
|
const QString BandwidthDetails = "Bandwidth Details";
|
||||||
|
@ -217,19 +217,11 @@ namespace MenuOption {
|
||||||
const QString CullSharedFaces = "Cull Shared Voxel Faces";
|
const QString CullSharedFaces = "Cull Shared Voxel Faces";
|
||||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||||
const QString DecreaseVoxelSize = "Decrease Voxel Size";
|
const QString DecreaseVoxelSize = "Decrease Voxel Size";
|
||||||
const QString DestructiveAddVoxel = "Create Voxel is Destructive";
|
|
||||||
const QString DisableColorVoxels = "Disable Colored Voxels";
|
|
||||||
const QString DisableDeltaSending = "Disable Delta Sending";
|
|
||||||
const QString DisableLowRes = "Disable Lower Resolution While Moving";
|
|
||||||
const QString DisplayFrustum = "Display Frustum";
|
const QString DisplayFrustum = "Display Frustum";
|
||||||
const QString DisplayHands = "Display Hands";
|
const QString DisplayHands = "Display Hands";
|
||||||
const QString DisplayHandTargets = "Display Hand Targets";
|
const QString DisplayHandTargets = "Display Hand Targets";
|
||||||
const QString FilterSixense = "Smooth Sixense Movement";
|
const QString FilterSixense = "Smooth Sixense Movement";
|
||||||
const QString DontRenderVoxels = "Don't call _voxels.render()";
|
|
||||||
const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels";
|
|
||||||
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
||||||
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
|
|
||||||
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
|
|
||||||
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
||||||
const QString EchoServerAudio = "Echo Server Audio";
|
const QString EchoServerAudio = "Echo Server Audio";
|
||||||
const QString EchoLocalAudio = "Echo Local Audio";
|
const QString EchoLocalAudio = "Echo Local Audio";
|
||||||
|
@ -301,8 +293,6 @@ namespace MenuOption {
|
||||||
const QString TreeStats = "Calculate Tree Stats";
|
const QString TreeStats = "Calculate Tree Stats";
|
||||||
const QString TransmitterDrive = "Transmitter Drive";
|
const QString TransmitterDrive = "Transmitter Drive";
|
||||||
const QString Quit = "Quit";
|
const QString Quit = "Quit";
|
||||||
const QString UseVoxelShader = "Use Voxel Shader";
|
|
||||||
const QString VoxelsAsPoints = "Draw Voxels as Points";
|
|
||||||
const QString Voxels = "Voxels";
|
const QString Voxels = "Voxels";
|
||||||
const QString VoxelDrumming = "Voxel Drumming";
|
const QString VoxelDrumming = "Voxel Drumming";
|
||||||
const QString VoxelMode = "Cycle Voxel Mode";
|
const QString VoxelMode = "Cycle Voxel Mode";
|
||||||
|
|
|
@ -48,6 +48,9 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c
|
||||||
wasStatsPacket = true;
|
wasStatsPacket = true;
|
||||||
if (messageLength > statsMessageLength) {
|
if (messageLength > statsMessageLength) {
|
||||||
mutablePacket = mutablePacket.mid(statsMessageLength);
|
mutablePacket = mutablePacket.mid(statsMessageLength);
|
||||||
|
|
||||||
|
// TODO: this does not look correct, the goal is to test the packet version for the piggyback, but
|
||||||
|
// this is testing the version and hash of the original packet
|
||||||
if (!NodeList::getInstance()->packetVersionAndHashMatch(packet)) {
|
if (!NodeList::getInstance()->packetVersionAndHashMatch(packet)) {
|
||||||
return; // bail since piggyback data doesn't match our versioning
|
return; // bail since piggyback data doesn't match our versioning
|
||||||
}
|
}
|
||||||
|
|
|
@ -867,7 +867,6 @@ void VoxelSystem::checkForCulling() {
|
||||||
bool fullRedraw = (_lastKnownVoxelSizeScale != Menu::getInstance()->getVoxelSizeScale() ||
|
bool fullRedraw = (_lastKnownVoxelSizeScale != Menu::getInstance()->getVoxelSizeScale() ||
|
||||||
_lastKnownBoundaryLevelAdjust != Menu::getInstance()->getBoundaryLevelAdjust());
|
_lastKnownBoundaryLevelAdjust != Menu::getInstance()->getBoundaryLevelAdjust());
|
||||||
|
|
||||||
// track that these values
|
|
||||||
_lastKnownVoxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
|
_lastKnownVoxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
|
||||||
_lastKnownBoundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
|
_lastKnownBoundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
|
||||||
|
|
||||||
|
@ -1386,7 +1385,6 @@ void VoxelSystem::render() {
|
||||||
|
|
||||||
updateVBOs();
|
updateVBOs();
|
||||||
|
|
||||||
bool dontCallOpenGLDraw = Menu::getInstance()->isOptionChecked(MenuOption::DontCallOpenGLForVoxels);
|
|
||||||
// if not don't... then do...
|
// if not don't... then do...
|
||||||
if (_useVoxelShader) {
|
if (_useVoxelShader) {
|
||||||
PerformanceWarning warn(showWarnings,"render().. _useVoxelShader openGL..");
|
PerformanceWarning warn(showWarnings,"render().. _useVoxelShader openGL..");
|
||||||
|
@ -1432,9 +1430,7 @@ void VoxelSystem::render() {
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID);
|
||||||
|
|
||||||
if (!dontCallOpenGLDraw) {
|
glDrawElements(GL_POINTS, _voxelsInReadArrays, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); //The starting point of the IBO
|
||||||
glDrawElements(GL_POINTS, _voxelsInReadArrays, GL_UNSIGNED_INT, BUFFER_OFFSET(0)); //The starting point of the IBO
|
|
||||||
}
|
|
||||||
|
|
||||||
// deactivate vertex and color arrays after drawing
|
// deactivate vertex and color arrays after drawing
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
@ -1477,7 +1473,7 @@ void VoxelSystem::render() {
|
||||||
|
|
||||||
// draw voxels in 6 passes
|
// draw voxels in 6 passes
|
||||||
|
|
||||||
if (!dontCallOpenGLDraw) {
|
{
|
||||||
PerformanceWarning warn(showWarnings, "render().. glDrawRangeElementsEXT()...");
|
PerformanceWarning warn(showWarnings, "render().. glDrawRangeElementsEXT()...");
|
||||||
|
|
||||||
glNormal3f(0,1.0f,0);
|
glNormal3f(0,1.0f,0);
|
||||||
|
@ -1510,7 +1506,6 @@ void VoxelSystem::render() {
|
||||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
|
glDrawRangeElementsEXT(GL_TRIANGLES, 0, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
|
||||||
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
|
INDICES_PER_FACE * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceWarning warn(showWarnings, "render().. cleanup after glDrawRangeElementsEXT()...");
|
PerformanceWarning warn(showWarnings, "render().. cleanup after glDrawRangeElementsEXT()...");
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,7 @@ bool JurisdictionListener::queueJurisdictionRequest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void JurisdictionListener::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) {
|
void JurisdictionListener::processPacket(const SharedNodePointer& sendingNode, const QByteArray& packet) {
|
||||||
//qDebug() << "JurisdictionListener::processPacket()";
|
if (packetTypeForPacket(packet) == PacketTypeJurisdiction && sendingNode) {
|
||||||
if (packetTypeForPacket(packet) == PacketTypeJurisdictionRequest && sendingNode) {
|
|
||||||
QUuid nodeUUID = sendingNode->getUUID();
|
QUuid nodeUUID = sendingNode->getUUID();
|
||||||
JurisdictionMap map;
|
JurisdictionMap map;
|
||||||
map.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size());
|
map.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size());
|
||||||
|
|
|
@ -79,7 +79,8 @@ private:
|
||||||
|
|
||||||
/// Map between node IDs and their reported JurisdictionMap. Typically used by classes that need to know which nodes are
|
/// Map between node IDs and their reported JurisdictionMap. Typically used by classes that need to know which nodes are
|
||||||
/// managing which jurisdictions.
|
/// managing which jurisdictions.
|
||||||
typedef std::map<QUuid, JurisdictionMap> NodeToJurisdictionMap;
|
typedef QMap<QUuid, JurisdictionMap> NodeToJurisdictionMap;
|
||||||
|
typedef QMap<QUuid, JurisdictionMap>::iterator NodeToJurisdictionMapIterator;
|
||||||
|
|
||||||
|
|
||||||
#endif /* defined(__hifi__JurisdictionMap__) */
|
#endif /* defined(__hifi__JurisdictionMap__) */
|
||||||
|
|
241
libraries/octree/src/OctreeHeadlessViewer.cpp
Normal file
241
libraries/octree/src/OctreeHeadlessViewer.cpp
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
//
|
||||||
|
// OctreeHeadlessViewer.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <NodeList.h>
|
||||||
|
|
||||||
|
#include "OctreeHeadlessViewer.h"
|
||||||
|
|
||||||
|
OctreeHeadlessViewer::OctreeHeadlessViewer() :
|
||||||
|
OctreeRenderer(),
|
||||||
|
_voxelSizeScale(DEFAULT_OCTREE_SIZE_SCALE),
|
||||||
|
_boundaryLevelAdjust(0),
|
||||||
|
_maxPacketsPerSecond(DEFAULT_MAX_OCTREE_PPS)
|
||||||
|
{
|
||||||
|
_viewFrustum.setFieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES);
|
||||||
|
_viewFrustum.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||||
|
_viewFrustum.setNearClip(DEFAULT_NEAR_CLIP);
|
||||||
|
_viewFrustum.setFarClip(TREE_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
OctreeHeadlessViewer::~OctreeHeadlessViewer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeHeadlessViewer::init() {
|
||||||
|
OctreeRenderer::init();
|
||||||
|
setViewFrustum(&_viewFrustum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeHeadlessViewer::queryOctree() {
|
||||||
|
NodeType_t serverType = getMyNodeType();
|
||||||
|
PacketType packetType = getMyQueryMessageType();
|
||||||
|
NodeToJurisdictionMap& jurisdictions = *_jurisdictionListener->getJurisdictions();
|
||||||
|
|
||||||
|
bool wantExtraDebugging = false;
|
||||||
|
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "OctreeHeadlessViewer::queryOctree() _jurisdictionListener=" << _jurisdictionListener;
|
||||||
|
qDebug() << "---------------";
|
||||||
|
qDebug() << "_jurisdictionListener=" << _jurisdictionListener;
|
||||||
|
qDebug() << "Jurisdictions...";
|
||||||
|
for (NodeToJurisdictionMapIterator i = jurisdictions.begin(); i != jurisdictions.end(); ++i) {
|
||||||
|
qDebug() << i.key() << ": " << &i.value();
|
||||||
|
}
|
||||||
|
qDebug() << "---------------";
|
||||||
|
}
|
||||||
|
|
||||||
|
// These will be the same for all servers, so we can set them up once and then reuse for each server we send to.
|
||||||
|
_octreeQuery.setWantLowResMoving(true);
|
||||||
|
_octreeQuery.setWantColor(true);
|
||||||
|
_octreeQuery.setWantDelta(true);
|
||||||
|
_octreeQuery.setWantOcclusionCulling(false);
|
||||||
|
_octreeQuery.setWantCompression(true); // TODO: should be on by default
|
||||||
|
|
||||||
|
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());
|
||||||
|
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
|
||||||
|
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
|
||||||
|
_octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
|
||||||
|
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
|
||||||
|
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
|
||||||
|
_octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
|
||||||
|
_octreeQuery.setOctreeSizeScale(getVoxelSizeScale());
|
||||||
|
_octreeQuery.setBoundaryLevelAdjust(getBoundaryLevelAdjust());
|
||||||
|
|
||||||
|
unsigned char queryPacket[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
|
// Iterate all of the nodes, and get a count of how many voxel servers we have...
|
||||||
|
int totalServers = 0;
|
||||||
|
int inViewServers = 0;
|
||||||
|
int unknownJurisdictionServers = 0;
|
||||||
|
|
||||||
|
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||||
|
// only send to the NodeTypes that are serverType
|
||||||
|
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
|
||||||
|
totalServers++;
|
||||||
|
|
||||||
|
// get the server bounds for this server
|
||||||
|
QUuid nodeUUID = node->getUUID();
|
||||||
|
|
||||||
|
// if we haven't heard from this voxel server, go ahead and send it a query, so we
|
||||||
|
// can get the jurisdiction...
|
||||||
|
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
|
||||||
|
unknownJurisdictionServers++;
|
||||||
|
} else {
|
||||||
|
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
||||||
|
|
||||||
|
unsigned char* rootCode = map.getRootOctalCode();
|
||||||
|
|
||||||
|
if (rootCode) {
|
||||||
|
VoxelPositionSize rootDetails;
|
||||||
|
voxelDetailsForCode(rootCode, rootDetails);
|
||||||
|
AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
||||||
|
serverBounds.scale(TREE_SCALE);
|
||||||
|
|
||||||
|
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);
|
||||||
|
|
||||||
|
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
|
||||||
|
inViewServers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug("Servers: total %d, in view %d, unknown jurisdiction %d",
|
||||||
|
totalServers, inViewServers, unknownJurisdictionServers);
|
||||||
|
}
|
||||||
|
|
||||||
|
int perServerPPS = 0;
|
||||||
|
const int SMALL_BUDGET = 10;
|
||||||
|
int perUnknownServer = SMALL_BUDGET;
|
||||||
|
int totalPPS = getMaxPacketsPerSecond();
|
||||||
|
|
||||||
|
// determine PPS based on number of servers
|
||||||
|
if (inViewServers >= 1) {
|
||||||
|
// set our preferred PPS to be exactly evenly divided among all of the voxel servers... and allocate 1 PPS
|
||||||
|
// for each unknown jurisdiction server
|
||||||
|
perServerPPS = (totalPPS / inViewServers) - (unknownJurisdictionServers * perUnknownServer);
|
||||||
|
} else {
|
||||||
|
if (unknownJurisdictionServers > 0) {
|
||||||
|
perUnknownServer = (totalPPS / unknownJurisdictionServers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug("perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
|
||||||
|
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||||
|
// only send to the NodeTypes that are serverType
|
||||||
|
if (node->getActiveSocket() != NULL && node->getType() == serverType) {
|
||||||
|
|
||||||
|
|
||||||
|
// get the server bounds for this server
|
||||||
|
QUuid nodeUUID = node->getUUID();
|
||||||
|
|
||||||
|
bool inView = false;
|
||||||
|
bool unknownView = false;
|
||||||
|
|
||||||
|
// if we haven't heard from this voxel server, go ahead and send it a query, so we
|
||||||
|
// can get the jurisdiction...
|
||||||
|
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
|
||||||
|
unknownView = true; // assume it's in view
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "no known jurisdiction for node " << *node << ", assume it's visible.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
||||||
|
|
||||||
|
unsigned char* rootCode = map.getRootOctalCode();
|
||||||
|
|
||||||
|
if (rootCode) {
|
||||||
|
VoxelPositionSize rootDetails;
|
||||||
|
voxelDetailsForCode(rootCode, rootDetails);
|
||||||
|
AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
||||||
|
serverBounds.scale(TREE_SCALE);
|
||||||
|
|
||||||
|
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds);
|
||||||
|
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
|
||||||
|
inView = true;
|
||||||
|
} else {
|
||||||
|
inView = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inView) {
|
||||||
|
_octreeQuery.setMaxOctreePacketsPerSecond(perServerPPS);
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "inView for node " << *node << ", give it budget of " << perServerPPS;
|
||||||
|
}
|
||||||
|
} else if (unknownView) {
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "no known jurisdiction for node " << *node << ", give it budget of "
|
||||||
|
<< perUnknownServer << " to send us jurisdiction.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the query's position/orientation to be degenerate in a manner that will get the scene quickly
|
||||||
|
// If there's only one server, then don't do this, and just let the normal voxel query pass through
|
||||||
|
// as expected... this way, we will actually get a valid scene if there is one to be seen
|
||||||
|
if (totalServers > 1) {
|
||||||
|
_octreeQuery.setCameraPosition(glm::vec3(-0.1,-0.1,-0.1));
|
||||||
|
const glm::quat OFF_IN_NEGATIVE_SPACE = glm::quat(-0.5, 0, -0.5, 1.0);
|
||||||
|
_octreeQuery.setCameraOrientation(OFF_IN_NEGATIVE_SPACE);
|
||||||
|
_octreeQuery.setCameraNearClip(0.1f);
|
||||||
|
_octreeQuery.setCameraFarClip(0.1f);
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "Using 'minimal' camera position for node" << *node;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (wantExtraDebugging) {
|
||||||
|
qDebug() << "Using regular camera position for node" << *node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_octreeQuery.setMaxOctreePacketsPerSecond(perUnknownServer);
|
||||||
|
} else {
|
||||||
|
_octreeQuery.setMaxOctreePacketsPerSecond(0);
|
||||||
|
}
|
||||||
|
// set up the packet for sending...
|
||||||
|
unsigned char* endOfQueryPacket = queryPacket;
|
||||||
|
|
||||||
|
// insert packet type/version and node UUID
|
||||||
|
endOfQueryPacket += populatePacketHeader(reinterpret_cast<char*>(endOfQueryPacket), packetType);
|
||||||
|
|
||||||
|
// encode the query data...
|
||||||
|
endOfQueryPacket += _octreeQuery.getBroadcastData(endOfQueryPacket);
|
||||||
|
|
||||||
|
int packetLength = endOfQueryPacket - queryPacket;
|
||||||
|
|
||||||
|
// make sure we still have an active socket
|
||||||
|
nodeList->writeDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int OctreeHeadlessViewer::parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sourceNode) {
|
||||||
|
|
||||||
|
OctreeSceneStats temp;
|
||||||
|
int statsMessageLength = temp.unpackFromMessage(reinterpret_cast<const unsigned char*>(packet.data()), packet.size());
|
||||||
|
|
||||||
|
// TODO: actually do something with these stats, like expose them to JS...
|
||||||
|
|
||||||
|
return statsMessageLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeHeadlessViewer::trackIncomingOctreePacket(const QByteArray& packet,
|
||||||
|
const SharedNodePointer& sendingNode, bool wasStatsPacket) {
|
||||||
|
|
||||||
|
}
|
73
libraries/octree/src/OctreeHeadlessViewer.h
Normal file
73
libraries/octree/src/OctreeHeadlessViewer.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
//
|
||||||
|
// OctreeHeadlessViewer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__OctreeHeadlessViewer__
|
||||||
|
#define __hifi__OctreeHeadlessViewer__
|
||||||
|
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include "JurisdictionListener.h"
|
||||||
|
#include "Octree.h"
|
||||||
|
#include "OctreeConstants.h"
|
||||||
|
#include "OctreeQuery.h"
|
||||||
|
#include "OctreeRenderer.h"
|
||||||
|
#include "OctreeSceneStats.h"
|
||||||
|
#include "Octree.h"
|
||||||
|
#include "ViewFrustum.h"
|
||||||
|
|
||||||
|
// Generic client side Octree renderer class.
|
||||||
|
class OctreeHeadlessViewer : public OctreeRenderer {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
OctreeHeadlessViewer();
|
||||||
|
virtual ~OctreeHeadlessViewer();
|
||||||
|
virtual void renderElement(OctreeElement* element, RenderArgs* args) { /* swallow these */ };
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
virtual void render() { /* swallow these */ };
|
||||||
|
|
||||||
|
void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; }
|
||||||
|
|
||||||
|
static int parseOctreeStats(const QByteArray& packet, const SharedNodePointer& sourceNode);
|
||||||
|
static void trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void queryOctree();
|
||||||
|
|
||||||
|
// setters for camera attributes
|
||||||
|
void setPosition(const glm::vec3& position) { _viewFrustum.setPosition(position); }
|
||||||
|
void setOrientation(const glm::quat& orientation) { _viewFrustum.setOrientation(orientation); }
|
||||||
|
|
||||||
|
// setters for LOD and PPS
|
||||||
|
void setVoxelSizeScale(float sizeScale) { _voxelSizeScale = sizeScale; }
|
||||||
|
void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; }
|
||||||
|
void setMaxPacketsPerSecond(int maxPacketsPerSecond) { _maxPacketsPerSecond = maxPacketsPerSecond; }
|
||||||
|
|
||||||
|
// getters for camera attributes
|
||||||
|
const glm::vec3& getPosition() const { return _viewFrustum.getPosition(); }
|
||||||
|
const glm::quat& getOrientation() const { return _viewFrustum.getOrientation(); }
|
||||||
|
|
||||||
|
// getters for LOD and PPS
|
||||||
|
float getVoxelSizeScale() const { return _voxelSizeScale; }
|
||||||
|
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||||
|
int getMaxPacketsPerSecond() const { return _maxPacketsPerSecond; }
|
||||||
|
|
||||||
|
unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ViewFrustum _viewFrustum;
|
||||||
|
JurisdictionListener* _jurisdictionListener;
|
||||||
|
OctreeQuery _octreeQuery;
|
||||||
|
float _voxelSizeScale;
|
||||||
|
int _boundaryLevelAdjust;
|
||||||
|
int _maxPacketsPerSecond;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__OctreeHeadlessViewer__) */
|
|
@ -6,22 +6,11 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <NodeList.h>
|
|
||||||
#include <PacketHeaders.h>
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <UUID.h>
|
|
||||||
#include "OctreeConstants.h"
|
#include "OctreeConstants.h"
|
||||||
|
|
||||||
#include "OctreeQuery.h"
|
#include "OctreeQuery.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
|
||||||
|
|
||||||
OctreeQuery::OctreeQuery() :
|
OctreeQuery::OctreeQuery() :
|
||||||
NodeData(),
|
NodeData(),
|
||||||
_cameraPosition(0,0,0),
|
_cameraPosition(0,0,0),
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
#ifndef __hifi__OctreeQuery__
|
#ifndef __hifi__OctreeQuery__
|
||||||
#define __hifi__OctreeQuery__
|
#define __hifi__OctreeQuery__
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/* VS2010 defines stdint.h, but not inttypes.h */
|
/* VS2010 defines stdint.h, but not inttypes.h */
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
typedef signed char int8_t;
|
typedef signed char int8_t;
|
||||||
|
@ -27,17 +25,9 @@ typedef unsigned long long quint64;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
#include <QtCore/QUuid>
|
|
||||||
#include <QtCore/QVariantMap>
|
|
||||||
|
|
||||||
#include <RegisteredMetaTypes.h>
|
|
||||||
|
|
||||||
#include <NodeData.h>
|
#include <NodeData.h>
|
||||||
|
|
||||||
// First bitset
|
// First bitset
|
||||||
|
|
|
@ -27,42 +27,48 @@ OctreeRenderer::~OctreeRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
||||||
|
bool extraDebugging = false;
|
||||||
|
|
||||||
|
if (extraDebugging) {
|
||||||
|
qDebug() << "OctreeRenderer::processDatagram()";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_tree) {
|
||||||
|
qDebug() << "OctreeRenderer::processDatagram() called before init, calling init()...";
|
||||||
|
this->init();
|
||||||
|
}
|
||||||
|
|
||||||
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
bool extraDebugging = false; // Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)
|
|
||||||
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
|
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
|
||||||
|
|
||||||
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
|
|
||||||
int packetLength = dataByteArray.size();
|
int packetLength = dataByteArray.size();
|
||||||
|
PacketType command = packetTypeForPacket(dataByteArray);
|
||||||
unsigned char command = *packetData;
|
|
||||||
|
|
||||||
int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray);
|
int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray);
|
||||||
|
QUuid sourceUUID = uuidFromPacketHeader(dataByteArray);
|
||||||
PacketType expectedType = getExpectedPacketType();
|
PacketType expectedType = getExpectedPacketType();
|
||||||
|
|
||||||
if(command == expectedType) {
|
if(command == expectedType) {
|
||||||
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram expected PacketType", showTimingDetails);
|
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram expected PacketType", showTimingDetails);
|
||||||
|
|
||||||
// if we are getting inbound packets, then our tree is also viewing, and we should remember that fact.
|
// if we are getting inbound packets, then our tree is also viewing, and we should remember that fact.
|
||||||
_tree->setIsViewing(true);
|
_tree->setIsViewing(true);
|
||||||
|
|
||||||
const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(dataByteArray.data()) + numBytesPacketHeader;
|
const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(dataByteArray.data()) + numBytesPacketHeader;
|
||||||
|
|
||||||
OCTREE_PACKET_FLAGS flags = (*(OCTREE_PACKET_FLAGS*)(dataAt));
|
OCTREE_PACKET_FLAGS flags = (*(OCTREE_PACKET_FLAGS*)(dataAt));
|
||||||
dataAt += sizeof(OCTREE_PACKET_FLAGS);
|
dataAt += sizeof(OCTREE_PACKET_FLAGS);
|
||||||
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
|
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
|
||||||
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
||||||
|
|
||||||
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
|
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
|
||||||
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
|
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
|
||||||
|
|
||||||
bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
|
bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
|
||||||
bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
|
bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
|
||||||
|
|
||||||
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
||||||
int clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0;
|
int clockSkew = sourceNode ? sourceNode->getClockSkewUsec() : 0;
|
||||||
int flightTime = arrivedAt - sentAt + clockSkew;
|
int flightTime = arrivedAt - sentAt + clockSkew;
|
||||||
|
|
||||||
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
||||||
int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
||||||
|
|
||||||
|
@ -91,7 +97,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
|
||||||
if (sectionLength) {
|
if (sectionLength) {
|
||||||
// ask the VoxelTree to read the bitstream into the tree
|
// ask the VoxelTree to read the bitstream into the tree
|
||||||
ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL,
|
ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL,
|
||||||
getDataSourceUUID(), sourceNode);
|
sourceUUID, sourceNode);
|
||||||
_tree->lockForWrite();
|
_tree->lockForWrite();
|
||||||
OctreePacketData packetData(packetIsCompressed);
|
OctreePacketData packetData(packetIsCompressed);
|
||||||
packetData.loadFinalizedContent(dataAt, sectionLength);
|
packetData.loadFinalizedContent(dataAt, sectionLength);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
@ -31,7 +33,8 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// Generic client side Octree renderer class.
|
// Generic client side Octree renderer class.
|
||||||
class OctreeRenderer {
|
class OctreeRenderer : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
OctreeRenderer();
|
OctreeRenderer();
|
||||||
virtual ~OctreeRenderer();
|
virtual ~OctreeRenderer();
|
||||||
|
@ -51,8 +54,6 @@ public:
|
||||||
/// render the content of the octree
|
/// render the content of the octree
|
||||||
virtual void render();
|
virtual void render();
|
||||||
|
|
||||||
void setDataSourceUUID(const QUuid& dataSourceUUID) { _dataSourceUUID = dataSourceUUID; }
|
|
||||||
const QUuid& getDataSourceUUID() const { return _dataSourceUUID; }
|
|
||||||
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
||||||
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
||||||
|
|
||||||
|
@ -62,7 +63,6 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
protected:
|
protected:
|
||||||
Octree* _tree;
|
Octree* _tree;
|
||||||
QUuid _dataSourceUUID;
|
|
||||||
ViewFrustum* _viewFrustum;
|
ViewFrustum* _viewFrustum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,9 @@ public:
|
||||||
virtual NodeType_t getServerNodeType() const = 0;
|
virtual NodeType_t getServerNodeType() const = 0;
|
||||||
virtual OctreeEditPacketSender* createPacketSender() = 0;
|
virtual OctreeEditPacketSender* createPacketSender() = 0;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void cleanupManagedObjects();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// Set the desired max packet size in bytes that should be created
|
/// Set the desired max packet size in bytes that should be created
|
||||||
void setMaxPacketSize(int maxPacketSize) { return _packetSender->setMaxPacketSize(maxPacketSize); }
|
void setMaxPacketSize(int maxPacketSize) { return _packetSender->setMaxPacketSize(maxPacketSize); }
|
||||||
|
@ -84,9 +87,6 @@ public slots:
|
||||||
/// returns the total bytes queued by this object over its lifetime
|
/// returns the total bytes queued by this object over its lifetime
|
||||||
long long unsigned int getLifetimeBytesQueued() const { return _packetSender->getLifetimeBytesQueued(); }
|
long long unsigned int getLifetimeBytesQueued() const { return _packetSender->getLifetimeBytesQueued(); }
|
||||||
|
|
||||||
// TODO: hmmm... we don't want this called from JS, how to handle that?
|
|
||||||
void cleanupManagedObjects();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// attached OctreeEditPacketSender that handles queuing and sending of packets to VS
|
/// attached OctreeEditPacketSender that handles queuing and sending of packets to VS
|
||||||
OctreeEditPacketSender* _packetSender;
|
OctreeEditPacketSender* _packetSender;
|
||||||
|
|
|
@ -54,11 +54,9 @@ void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
||||||
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
|
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ViewFrustum::calculateViewFrustum()
|
// ViewFrustum::calculateViewFrustum()
|
||||||
//
|
//
|
||||||
// Description: this will calculate the view frustum bounds for a given position
|
// Description: this will calculate the view frustum bounds for a given position and direction
|
||||||
// and direction
|
|
||||||
//
|
//
|
||||||
// Notes on how/why this works:
|
// Notes on how/why this works:
|
||||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
|
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
|
||||||
|
|
|
@ -17,9 +17,14 @@
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
#include "Plane.h"
|
#include "Plane.h"
|
||||||
|
|
||||||
|
#include "OctreeConstants.h"
|
||||||
#include "OctreeProjectedPolygon.h"
|
#include "OctreeProjectedPolygon.h"
|
||||||
|
|
||||||
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
|
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
|
||||||
|
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 90.0f;
|
||||||
|
const float DEFAULT_ASPECT_RATIO = 16.f/9.f;
|
||||||
|
const float DEFAULT_NEAR_CLIP = 0.08f;
|
||||||
|
const float DEFAULT_FAR_CLIP = 50.0f * TREE_SCALE;
|
||||||
|
|
||||||
class ViewFrustum {
|
class ViewFrustum {
|
||||||
public:
|
public:
|
||||||
|
|
36
libraries/particles/src/ParticleTreeHeadlessViewer.cpp
Normal file
36
libraries/particles/src/ParticleTreeHeadlessViewer.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// ParticleTreeHeadlessViewer.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ParticleTreeHeadlessViewer.h"
|
||||||
|
|
||||||
|
ParticleTreeHeadlessViewer::ParticleTreeHeadlessViewer() :
|
||||||
|
OctreeHeadlessViewer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleTreeHeadlessViewer::~ParticleTreeHeadlessViewer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleTreeHeadlessViewer::init() {
|
||||||
|
OctreeHeadlessViewer::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParticleTreeHeadlessViewer::update() {
|
||||||
|
if (_tree) {
|
||||||
|
ParticleTree* tree = static_cast<ParticleTree*>(_tree);
|
||||||
|
if (tree->tryLockForWrite()) {
|
||||||
|
tree->update();
|
||||||
|
tree->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleTreeHeadlessViewer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
||||||
|
static_cast<ParticleTree*>(_tree)->processEraseMessage(dataByteArray, sourceNode);
|
||||||
|
}
|
42
libraries/particles/src/ParticleTreeHeadlessViewer.h
Normal file
42
libraries/particles/src/ParticleTreeHeadlessViewer.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// ParticleTreeHeadlessViewer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__ParticleTreeHeadlessViewer__
|
||||||
|
#define __hifi__ParticleTreeHeadlessViewer__
|
||||||
|
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <Octree.h>
|
||||||
|
#include <OctreePacketData.h>
|
||||||
|
#include <OctreeHeadlessViewer.h>
|
||||||
|
#include "ParticleTree.h"
|
||||||
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
|
// Generic client side Octree renderer class.
|
||||||
|
class ParticleTreeHeadlessViewer : public OctreeHeadlessViewer {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ParticleTreeHeadlessViewer();
|
||||||
|
virtual ~ParticleTreeHeadlessViewer();
|
||||||
|
|
||||||
|
virtual Octree* createTree() { return new ParticleTree(true); }
|
||||||
|
virtual NodeType_t getMyNodeType() const { return NodeType::ParticleServer; }
|
||||||
|
virtual PacketType getMyQueryMessageType() const { return PacketTypeParticleQuery; }
|
||||||
|
virtual PacketType getExpectedPacketType() const { return PacketTypeParticleData; }
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
ParticleTree* getTree() { return (ParticleTree*)_tree; }
|
||||||
|
|
||||||
|
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__ParticleTreeHeadlessViewer__) */
|
|
@ -26,7 +26,19 @@ public:
|
||||||
|
|
||||||
void setParticleTree(ParticleTree* particleTree) { _particleTree = particleTree; }
|
void setParticleTree(ParticleTree* particleTree) { _particleTree = particleTree; }
|
||||||
ParticleTree* getParticleTree(ParticleTree*) { return _particleTree; }
|
ParticleTree* getParticleTree(ParticleTree*) { return _particleTree; }
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
/// inbound slots for external collision systems
|
||||||
|
void forwardParticleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel) {
|
||||||
|
qDebug() << "forwardParticleCollisionWithVoxel()";
|
||||||
|
emit particleCollisionWithVoxel(particleID, voxel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB) {
|
||||||
|
qDebug() << "forwardParticleCollisionWithParticle()";
|
||||||
|
emit particleCollisionWithParticle(idA, idB);
|
||||||
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// adds a particle with the specific properties
|
/// adds a particle with the specific properties
|
||||||
ParticleID addParticle(const ParticleProperties& properties);
|
ParticleID addParticle(const ParticleProperties& properties);
|
||||||
|
@ -54,15 +66,6 @@ public slots:
|
||||||
/// this function will not find any particles in script engine contexts which don't have access to particles
|
/// this function will not find any particles in script engine contexts which don't have access to particles
|
||||||
QVector<ParticleID> findParticles(const glm::vec3& center, float radius) const;
|
QVector<ParticleID> findParticles(const glm::vec3& center, float radius) const;
|
||||||
|
|
||||||
/// inbound slots for external collision systems
|
|
||||||
void forwardParticleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel) {
|
|
||||||
emit particleCollisionWithVoxel(particleID, voxel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB) {
|
|
||||||
emit particleCollisionWithParticle(idA, idB);
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel);
|
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel);
|
||||||
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB);
|
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB);
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
//
|
|
||||||
// VoxelQuery.cpp
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Brad Hefta-Gaub on 10/24/13.
|
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "VoxelQuery.h"
|
|
|
@ -1,25 +0,0 @@
|
||||||
//
|
|
||||||
// VoxelQuery.h
|
|
||||||
// hifi
|
|
||||||
//
|
|
||||||
// Created by Stephen Birarda on 4/9/13.
|
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __hifi__VoxelQuery__
|
|
||||||
#define __hifi__VoxelQuery__
|
|
||||||
|
|
||||||
#include <OctreeQuery.h>
|
|
||||||
|
|
||||||
class VoxelQuery : public OctreeQuery {
|
|
||||||
|
|
||||||
public:
|
|
||||||
// currently just an alias
|
|
||||||
VoxelQuery() : OctreeQuery() {};
|
|
||||||
private:
|
|
||||||
// privatize the copy constructor and assignment operator so they cannot be called
|
|
||||||
VoxelQuery(const VoxelQuery&);
|
|
||||||
VoxelQuery& operator= (const VoxelQuery&);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(__hifi__VoxelQuery__) */
|
|
22
libraries/voxels/src/VoxelTreeHeadlessViewer.cpp
Normal file
22
libraries/voxels/src/VoxelTreeHeadlessViewer.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// VoxelTreeHeadlessViewer.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "VoxelTreeHeadlessViewer.h"
|
||||||
|
|
||||||
|
VoxelTreeHeadlessViewer::VoxelTreeHeadlessViewer() :
|
||||||
|
OctreeHeadlessViewer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelTreeHeadlessViewer::~VoxelTreeHeadlessViewer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelTreeHeadlessViewer::init() {
|
||||||
|
OctreeHeadlessViewer::init();
|
||||||
|
}
|
||||||
|
|
38
libraries/voxels/src/VoxelTreeHeadlessViewer.h
Normal file
38
libraries/voxels/src/VoxelTreeHeadlessViewer.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// VoxelTreeHeadlessViewer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/26/14
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__VoxelTreeHeadlessViewer__
|
||||||
|
#define __hifi__VoxelTreeHeadlessViewer__
|
||||||
|
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <Octree.h>
|
||||||
|
#include <OctreePacketData.h>
|
||||||
|
#include <OctreeHeadlessViewer.h>
|
||||||
|
#include "VoxelTree.h"
|
||||||
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
|
// Generic client side Octree renderer class.
|
||||||
|
class VoxelTreeHeadlessViewer : public OctreeHeadlessViewer {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
VoxelTreeHeadlessViewer();
|
||||||
|
virtual ~VoxelTreeHeadlessViewer();
|
||||||
|
|
||||||
|
virtual Octree* createTree() { return new VoxelTree(true); }
|
||||||
|
virtual NodeType_t getMyNodeType() const { return NodeType::VoxelServer; }
|
||||||
|
virtual PacketType getMyQueryMessageType() const { return PacketTypeVoxelQuery; }
|
||||||
|
virtual PacketType getExpectedPacketType() const { return PacketTypeVoxelData; }
|
||||||
|
|
||||||
|
VoxelTree* getTree() { return (VoxelTree*)_tree; }
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__VoxelTreeHeadlessViewer__) */
|
Loading…
Reference in a new issue