first cut at getting voxel server based on octree server

This commit is contained in:
ZappoMan 2013-12-04 17:41:52 -08:00
parent 2119f0da7d
commit 5ff12ab8d1
17 changed files with 145 additions and 265 deletions

View file

@ -27,6 +27,7 @@ link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(voxel-server-library ${TARGET_NAME} ${ROOT_DIR})
include_directories(${ROOT_DIR}/externals/civetweb/include)

View file

@ -180,6 +180,10 @@ public:
virtual OctreeElement* createNewElement(unsigned char * octalCode = NULL) const = 0;
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const { return false; }
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength) { return 0; }
OctreeElement* getRoot() { return _rootNode; }
void eraseAllOctreeElements();

View file

@ -1,28 +0,0 @@
//
// NodeWatcher.h
// voxel-server
//
// Created by Brad Hefta-Gaub on 8/21/13
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
// Node List Hook that watches for Node's being killed in order to clean up node specific memory and threads
//
#include <NodeList.h>
#include "NodeWatcher.h"
#include "VoxelNodeData.h"
void NodeWatcher::nodeAdded(Node* node) {
// do nothing
}
void NodeWatcher::nodeKilled(Node* node) {
// Use this to cleanup our node
if (node->getType() == NODE_TYPE_AGENT) {
VoxelNodeData* nodeData = (VoxelNodeData*)node->getLinkedData();
if (nodeData) {
node->setLinkedData(NULL);
delete nodeData;
}
}
};

View file

@ -1,23 +0,0 @@
//
// NodeWatcher.h
// voxel-server
//
// Created by Brad Hefta-Gaub on 8/21/13
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
// Node List Hook that watches for Node's being killed in order to clean up node specific memory and threads
//
#ifndef __voxel_server__NodeWatcher__
#define __voxel_server__NodeWatcher__
#include <NodeList.h>
/// Voxel server's node watcher, which watches for nodes being killed and cleans up their data and threads
class NodeWatcher : public virtual NodeListHook {
public:
virtual void nodeAdded(Node* node);
virtual void nodeKilled(Node* node);
};
#endif // __voxel_server__NodeWatcher__

View file

@ -1,3 +1,6 @@
/***
//
// VoxelNodeData.cpp
// hifi
@ -274,3 +277,5 @@ void VoxelNodeData::dumpOutOfView() {
}
}
**/

View file

@ -9,114 +9,13 @@
#ifndef __hifi__VoxelNodeData__
#define __hifi__VoxelNodeData__
#include <iostream>
#include <NodeData.h>
#include <VoxelPacketData.h>
#include <VoxelQuery.h>
#include <OctreeQueryNode.h>
#include <PacketHeaders.h>
#include <CoverageMap.h>
#include <VoxelConstants.h>
#include <OctreeElementBag.h>
#include <VoxelSceneStats.h>
class VoxelSendThread;
class VoxelServer;
class VoxelNodeData : public VoxelQuery {
class VoxelNodeData : public OctreeQueryNode {
public:
VoxelNodeData(Node* owningNode);
virtual ~VoxelNodeData();
void resetVoxelPacket(bool lastWasSurpressed = false); // resets voxel packet to after "V" header
void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet
const unsigned char* getPacket() const { return _voxelPacket; }
int getPacketLength() const { return (MAX_PACKET_SIZE - _voxelPacketAvailableBytes); }
bool isPacketWaiting() const { return _voxelPacketWaiting; }
bool packetIsDuplicate() const;
bool shouldSuppressDuplicatePacket();
int getAvailable() const { return _voxelPacketAvailableBytes; }
int getMaxSearchLevel() const { return _maxSearchLevel; }
void resetMaxSearchLevel() { _maxSearchLevel = 1; }
void incrementMaxSearchLevel() { _maxSearchLevel++; }
int getMaxLevelReached() const { return _maxLevelReachedInLastSearch; }
void setMaxLevelReached(int maxLevelReached) { _maxLevelReachedInLastSearch = maxLevelReached; }
OctreeElementBag nodeBag;
CoverageMap map;
ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; }
ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; }
// These are not classic setters because they are calculating and maintaining state
// which is set asynchronously through the network receive
bool updateCurrentViewFrustum();
void updateLastKnownViewFrustum();
bool getViewSent() const { return _viewSent; }
void setViewSent(bool viewSent);
bool getViewFrustumChanging() const { return _viewFrustumChanging; }
bool getViewFrustumJustStoppedChanging() const { return _viewFrustumJustStoppedChanging; }
bool moveShouldDump() const;
uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; }
void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; }
bool getCurrentPacketIsColor() const { return _currentPacketIsColor; }
bool getCurrentPacketIsCompressed() const { return _currentPacketIsCompressed; }
bool getCurrentPacketFormatMatches() {
return (getCurrentPacketIsColor() == getWantColor() && getCurrentPacketIsCompressed() == getWantCompression());
}
bool hasLodChanged() const { return _lodChanged; };
VoxelSceneStats stats;
void initializeVoxelSendThread(VoxelServer* voxelServer);
bool isVoxelSendThreadInitalized() { return _voxelSendThread; }
void dumpOutOfView();
private:
VoxelNodeData(const VoxelNodeData &);
VoxelNodeData& operator= (const VoxelNodeData&);
bool _viewSent;
unsigned char* _voxelPacket;
unsigned char* _voxelPacketAt;
int _voxelPacketAvailableBytes;
bool _voxelPacketWaiting;
unsigned char* _lastVoxelPacket;
int _lastVoxelPacketLength;
int _duplicatePacketCount;
uint64_t _firstSuppressedPacket;
int _maxSearchLevel;
int _maxLevelReachedInLastSearch;
ViewFrustum _currentViewFrustum;
ViewFrustum _lastKnownViewFrustum;
uint64_t _lastTimeBagEmpty;
bool _viewFrustumChanging;
bool _viewFrustumJustStoppedChanging;
bool _currentPacketIsColor;
bool _currentPacketIsCompressed;
VoxelSendThread* _voxelSendThread;
// watch for LOD changes
int _lastClientBoundaryLevelAdjust;
float _lastClientVoxelSizeScale;
bool _lodChanged;
bool _lodInitialized;
VOXEL_PACKET_SEQUENCE _sequenceNumber;
VoxelNodeData(Node* owningNode) : OctreeQueryNode(owningNode) { };
virtual PACKET_TYPE getMyPacketType() const { return PACKET_TYPE_VOXEL_DATA; }
};
#endif /* defined(__hifi__VoxelNodeData__) */

View file

@ -1,3 +1,6 @@
/*****
//
// VoxelPersistThread.cpp
// voxel-server
@ -84,3 +87,7 @@ bool VoxelPersistThread::process() {
}
return isStillRunning(); // keep running till they terminate us
}
****/

View file

@ -1,3 +1,5 @@
/****
//
// VoxelPersistThread.h
// voxel-server
@ -42,3 +44,6 @@ private:
};
#endif // __voxel_server__VoxelPersistThread__
***/

View file

@ -1,3 +1,5 @@
/*****
//
// VoxelSendThread.cpp
// voxel-server
@ -578,3 +580,4 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
return truePacketsSent;
}
****/

View file

@ -1,3 +1,5 @@
/****
//
// VoxelSendThread.h
// voxel-server
@ -46,3 +48,6 @@ private:
};
#endif // __voxel_server__VoxelSendThread__
****/

View file

@ -6,44 +6,45 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <time.h>
#include <QtCore/QDebug>
#include <QtCore/QString>
#include <QtCore/QTimer>
#include <QtCore/QUuid>
#include <Logging.h>
#include <OctalCode.h>
#include <NodeList.h>
#include <NodeTypes.h>
#include <VoxelTree.h>
#include "VoxelNodeData.h"
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <SceneUtils.h>
#include <PerfStat.h>
#include <JurisdictionSender.h>
#include <UUID.h>
#ifdef _WIN32
#include "Syssocket.h"
#include "Systime.h"
#else
#include <sys/time.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#endif
#include "VoxelServer.h"
#include "VoxelServerConsts.h"
#include "VoxelNodeData.h"
VoxelServer::VoxelServer(const unsigned char* dataBuffer, int numBytes) : OctreeServer(dataBuffer, numBytes) {
// nothing special to do here...
}
VoxelServer::~VoxelServer() {
// nothing special to do here...
}
OctreeQueryNode* VoxelServer::createOctreeQueryNode(Node* newNode) {
return new VoxelNodeData(newNode);
}
Octree* VoxelServer::createTree() {
return new VoxelTree(true);
}
unsigned char VoxelServer::getMyNodeType() {
return NODE_TYPE_VOXEL_SERVER;
}
const char* VOXEL_SERVER_LOGGING_TARGET_NAME = "voxel-server";
const char* VoxelServer::getMyLoggingServerTargetName() {
return VOXEL_SERVER_LOGGING_TARGET_NAME;
}
const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo";
const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.svo";
const char* VoxelServer::getMyDefaultPersistFilename() {
return LOCAL_VOXELS_PERSIST_FILE;
}
/*****
void attachVoxelNodeDataToNode(Node* newNode) {
if (newNode->getLinkedData() == NULL) {
@ -785,4 +786,5 @@ void VoxelServer::run() {
qDebug() << "VoxelServer::run()... DONE\n";
}
**/

View file

@ -17,87 +17,37 @@
#include <ThreadedAssignment.h>
#include <EnvironmentData.h>
#include <OctreeServer.h>
#include "civetweb.h"
#include "NodeWatcher.h"
#include "VoxelPersistThread.h"
#include "VoxelSendThread.h"
#include "VoxelServerConsts.h"
#include "VoxelServerPacketProcessor.h"
/// Handles assignments of type VoxelServer - sending voxels to various clients.
class VoxelServer : public ThreadedAssignment {
class VoxelServer : public OctreeServer {
public:
VoxelServer(const unsigned char* dataBuffer, int numBytes);
~VoxelServer();
/// allows setting of run arguments
void setArguments(int argc, char** argv);
bool wantsDebugVoxelSending() const { return _debugVoxelSending; }
bool wantsDebugVoxelReceiving() const { return _debugVoxelReceiving; }
bool wantsVerboseDebug() const { return _verboseDebug; }
bool wantShowAnimationDebug() const { return _shouldShowAnimationDebug; }
bool wantSendEnvironments() const { return _sendEnvironments; }
bool wantDumpVoxelsOnMove() const { return _dumpVoxelsOnMove; }
bool wantDisplayVoxelStats() const { return _displayVoxelStats; }
VoxelTree& getServerTree() { return _serverTree; }
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
int getPacketsPerClientPerInterval() const { return _packetsPerClientPerInterval; }
bool getSendMinimalEnvironment() const { return _sendMinimalEnvironment; }
EnvironmentData* getEnvironmentData(int i) { return &_environmentData[i]; }
int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); }
static VoxelServer* GetInstance() { return _theInstance; }
bool isInitialLoadComplete() const { return (_voxelPersistThread) ? _voxelPersistThread->isInitialLoadComplete() : true; }
time_t* getLoadCompleted() { return (_voxelPersistThread) ? _voxelPersistThread->getLoadCompleted() : NULL; }
uint64_t getLoadElapsedTime() const { return (_voxelPersistThread) ? _voxelPersistThread->getLoadElapsedTime() : 0; }
public slots:
/// runs the voxel server assignment
void run();
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
private:
int _argc;
const char** _argv;
char** _parsedArgV;
char _voxelPersistFilename[MAX_FILENAME_LENGTH];
int _packetsPerClientPerInterval;
VoxelTree _serverTree; // this IS a reaveraging tree
bool _wantVoxelPersist;
bool _wantLocalDomain;
bool _debugVoxelSending;
bool _shouldShowAnimationDebug;
bool _displayVoxelStats;
bool _debugVoxelReceiving;
// Subclasses must implement these methods
virtual OctreeQueryNode* createOctreeQueryNode(Node* newNode);
virtual Octree* createTree();
virtual unsigned char getMyNodeType();
virtual const char* getMyLoggingServerTargetName();
virtual const char* getMyDefaultPersistFilename();
private:
bool _sendEnvironments;
bool _sendMinimalEnvironment;
bool _dumpVoxelsOnMove;
bool _verboseDebug;
JurisdictionMap* _jurisdiction;
JurisdictionSender* _jurisdictionSender;
VoxelServerPacketProcessor* _voxelServerPacketProcessor;
VoxelPersistThread* _voxelPersistThread;
EnvironmentData _environmentData[3];
NodeWatcher _nodeWatcher; // used to cleanup AGENT data when agents are killed
void parsePayload();
void initMongoose(int port);
static int civetwebRequestHandler(struct mg_connection *connection);
static VoxelServer* _theInstance;
time_t _started;
uint64_t _startedUSecs;
};
#endif // __voxel_server__VoxelServer__

View file

@ -9,21 +9,6 @@
#ifndef __voxel_server__VoxelServerConsts__
#define __voxel_server__VoxelServerConsts__
#include <SharedUtil.h>
#include <NodeList.h> // for MAX_PACKET_SIZE
#include <JurisdictionSender.h>
#include <VoxelTree.h>
#include "VoxelServerPacketProcessor.h"
const int MAX_FILENAME_LENGTH = 1024;
const int INTERVALS_PER_SECOND = 60;
const int VOXEL_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND;
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000;
extern const char* LOCAL_VOXELS_PERSIST_FILE;
extern const char* VOXELS_PERSIST_FILE;
#endif // __voxel_server__VoxelServerConsts__

View file

@ -1,3 +1,5 @@
/******
//
// VoxelServerPacketProcessor.cpp
// voxel-server
@ -221,3 +223,4 @@ SingleSenderStats::SingleSenderStats() {
}
****/

View file

@ -1,3 +1,6 @@
/******
//
// VoxelServerPacketProcessor.h
// voxel-server
@ -81,3 +84,6 @@ private:
NodeToSenderStatsMap _singleSenderStats;
};
#endif // __voxel_server__VoxelServerPacketProcessor__
***/

View file

@ -638,3 +638,54 @@ void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelTreeElement* node, ReadC
node->handleSubtreeChanged(this);
}
}
bool VoxelTree::handlesEditPacketType(PACKET_TYPE packetType) const {
// we handle these types of "edit" packets
switch (packetType) {
case PACKET_TYPE_SET_VOXEL:
case PACKET_TYPE_SET_VOXEL_DESTRUCTIVE:
case PACKET_TYPE_ERASE_VOXEL:
return true;
}
return false;
}
int VoxelTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength) {
int processedBytes = 0;
// we handle these types of "edit" packets
switch (packetType) {
case PACKET_TYPE_SET_VOXEL:
case PACKET_TYPE_SET_VOXEL_DESTRUCTIVE: {
bool destructive = (packetType == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
int octets = numberOfThreeBitSectionsInCode(editData, maxLength);
if (octets == OVERFLOWED_OCTCODE_BUFFER) {
printf("WARNING! Got voxel edit record that would overflow buffer in numberOfThreeBitSectionsInCode(), ");
printf("bailing processing of packet!\n");
return processedBytes;
}
const int COLOR_SIZE_IN_BYTES = 3;
int voxelCodeSize = bytesRequiredForCodeLength(octets);
int voxelDataSize = voxelCodeSize + COLOR_SIZE_IN_BYTES;
if (voxelDataSize > maxLength) {
printf("WARNING! Got voxel edit record that would overflow buffer, bailing processing of packet!\n");
printf("bailing processing of packet!\n");
return processedBytes;
}
readCodeColorBufferToTree(editData, destructive);
return voxelDataSize;
} break;
case PACKET_TYPE_ERASE_VOXEL:
processRemoveOctreeElementsBitstream((unsigned char*)packetData, packetLength);
return maxLength;
}
return processedBytes;
}

View file

@ -53,6 +53,11 @@ public:
void readCodeColorBufferToTree(const unsigned char* codeColorBuffer, bool destructive = false);
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const;
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength);
void processSetVoxelsBitstream(const unsigned char* bitstream, int bufferSizeBytes);
/**
signals:
void importSize(float x, float y, float z);