mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #11210 from AndrewMeadows/mtwabp-OctreeSendThread-002
split packet construction from packet sending in OctreeSendThread
This commit is contained in:
commit
6a1fe81832
5 changed files with 133 additions and 138 deletions
|
@ -458,84 +458,80 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
||||||
return _truePacketsSent;
|
return _truePacketsSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OctreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) {
|
||||||
|
bool somethingToSend = false;
|
||||||
|
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(params.nodeData);
|
||||||
|
if (!nodeData->elementBag.isEmpty()) {
|
||||||
|
quint64 encodeStart = usecTimestampNow();
|
||||||
|
quint64 lockWaitStart = encodeStart;
|
||||||
|
|
||||||
|
_myServer->getOctree()->withReadLock([&]{
|
||||||
|
OctreeServer::trackTreeWaitTime((float)(usecTimestampNow() - lockWaitStart));
|
||||||
|
|
||||||
|
OctreeElementPointer subTree = nodeData->elementBag.extract();
|
||||||
|
if (subTree) {
|
||||||
|
// NOTE: this is where the tree "contents" are actually packed
|
||||||
|
nodeData->stats.encodeStarted();
|
||||||
|
_myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params);
|
||||||
|
nodeData->stats.encodeStopped();
|
||||||
|
|
||||||
|
somethingToSend = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
OctreeServer::trackEncodeTime((float)(usecTimestampNow() - encodeStart));
|
||||||
|
} else {
|
||||||
|
OctreeServer::trackTreeWaitTime(OctreeServer::SKIP_TIME);
|
||||||
|
OctreeServer::trackEncodeTime(OctreeServer::SKIP_TIME);
|
||||||
|
}
|
||||||
|
return somethingToSend;
|
||||||
|
}
|
||||||
|
|
||||||
void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene) {
|
void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene) {
|
||||||
// calculate max number of packets that can be sent during this interval
|
// calculate max number of packets that can be sent during this interval
|
||||||
int clientMaxPacketsPerInterval = std::max(1, (nodeData->getMaxQueryPacketsPerSecond() / INTERVALS_PER_SECOND));
|
int clientMaxPacketsPerInterval = std::max(1, (nodeData->getMaxQueryPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||||
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||||
|
|
||||||
int extraPackingAttempts = 0;
|
int extraPackingAttempts = 0;
|
||||||
bool completedScene = false;
|
|
||||||
|
// init params once outside the while loop
|
||||||
|
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
||||||
|
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
||||||
|
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||||
|
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||||
|
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
||||||
|
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
||||||
|
isFullScene, _myServer->getJurisdiction(), nodeData);
|
||||||
|
// Our trackSend() function is implemented by the server subclass, and will be called back
|
||||||
|
// during the encodeTreeBitstream() as new entities/data elements are sent
|
||||||
|
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
||||||
|
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
||||||
|
};
|
||||||
|
nodeData->copyCurrentViewFrustum(params.viewFrustum);
|
||||||
|
if (viewFrustumChanged) {
|
||||||
|
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
|
||||||
|
}
|
||||||
|
|
||||||
bool somethingToSend = true; // assume we have something
|
bool somethingToSend = true; // assume we have something
|
||||||
|
bool bagHadSomething = !nodeData->elementBag.isEmpty();
|
||||||
while (somethingToSend && _packetsSentThisInterval < maxPacketsPerInterval && !nodeData->isShuttingDown()) {
|
while (somethingToSend && _packetsSentThisInterval < maxPacketsPerInterval && !nodeData->isShuttingDown()) {
|
||||||
float lockWaitElapsedUsec = OctreeServer::SKIP_TIME;
|
|
||||||
float encodeElapsedUsec = OctreeServer::SKIP_TIME;
|
|
||||||
float compressAndWriteElapsedUsec = OctreeServer::SKIP_TIME;
|
float compressAndWriteElapsedUsec = OctreeServer::SKIP_TIME;
|
||||||
float packetSendingElapsedUsec = OctreeServer::SKIP_TIME;
|
float packetSendingElapsedUsec = OctreeServer::SKIP_TIME;
|
||||||
|
|
||||||
quint64 startInside = usecTimestampNow();
|
quint64 startInside = usecTimestampNow();
|
||||||
|
|
||||||
bool lastNodeDidntFit = false; // assume each node fits
|
bool lastNodeDidntFit = false; // assume each node fits
|
||||||
if (!nodeData->elementBag.isEmpty()) {
|
params.stopReason = EncodeBitstreamParams::UNKNOWN; // reset params.stopReason before traversal
|
||||||
|
|
||||||
quint64 lockWaitStart = usecTimestampNow();
|
somethingToSend = traverseTreeAndBuildNextPacketPayload(params);
|
||||||
_myServer->getOctree()->withReadLock([&]{
|
|
||||||
quint64 lockWaitEnd = usecTimestampNow();
|
|
||||||
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
|
||||||
quint64 encodeStart = usecTimestampNow();
|
|
||||||
|
|
||||||
OctreeElementPointer subTree = nodeData->elementBag.extract();
|
if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
|
||||||
if (!subTree) {
|
lastNodeDidntFit = true;
|
||||||
return;
|
extraPackingAttempts++;
|
||||||
}
|
|
||||||
|
|
||||||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
|
||||||
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
|
||||||
|
|
||||||
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
|
||||||
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
|
||||||
|
|
||||||
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
|
||||||
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
|
||||||
isFullScene, _myServer->getJurisdiction(), nodeData);
|
|
||||||
nodeData->copyCurrentViewFrustum(params.viewFrustum);
|
|
||||||
if (viewFrustumChanged) {
|
|
||||||
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Our trackSend() function is implemented by the server subclass, and will be called back
|
|
||||||
// during the encodeTreeBitstream() as new entities/data elements are sent
|
|
||||||
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
|
||||||
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: should this include the lock time or not? This stat is sent down to the client,
|
|
||||||
// it seems like it may be a good idea to include the lock time as part of the encode time
|
|
||||||
// are reported to client. Since you can encode without the lock
|
|
||||||
nodeData->stats.encodeStarted();
|
|
||||||
|
|
||||||
// NOTE: this is where the tree "contents" are actaully packed
|
|
||||||
_myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params);
|
|
||||||
|
|
||||||
quint64 encodeEnd = usecTimestampNow();
|
|
||||||
encodeElapsedUsec = (float)(encodeEnd - encodeStart);
|
|
||||||
|
|
||||||
// If after calling encodeTreeBitstream() there are no nodes left to send, then we know we've
|
|
||||||
// sent the entire scene. We want to know this below so we'll actually write this content into
|
|
||||||
// the packet and send it
|
|
||||||
completedScene = nodeData->elementBag.isEmpty();
|
|
||||||
|
|
||||||
if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
|
|
||||||
lastNodeDidntFit = true;
|
|
||||||
extraPackingAttempts++;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeData->stats.encodeStopped();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
somethingToSend = false; // this will cause us to drop out of the loop...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the bag had contents but is now empty then we know we've sent the entire scene.
|
||||||
|
bool completedScene = bagHadSomething && nodeData->elementBag.isEmpty();
|
||||||
if (completedScene || lastNodeDidntFit) {
|
if (completedScene || lastNodeDidntFit) {
|
||||||
// we probably want to flush what has accumulated in nodeData but:
|
// we probably want to flush what has accumulated in nodeData but:
|
||||||
// do we have more data to send? and is there room?
|
// do we have more data to send? and is there room?
|
||||||
|
@ -562,8 +558,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
||||||
if (sendNow) {
|
if (sendNow) {
|
||||||
quint64 packetSendingStart = usecTimestampNow();
|
quint64 packetSendingStart = usecTimestampNow();
|
||||||
_packetsSentThisInterval += handlePacketSend(node, nodeData);
|
_packetsSentThisInterval += handlePacketSend(node, nodeData);
|
||||||
quint64 packetSendingEnd = usecTimestampNow();
|
packetSendingElapsedUsec = (float)(usecTimestampNow() - packetSendingStart);
|
||||||
packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart);
|
|
||||||
|
|
||||||
targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
||||||
extraPackingAttempts = 0;
|
extraPackingAttempts = 0;
|
||||||
|
@ -576,14 +571,9 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
||||||
}
|
}
|
||||||
_packetData.changeSettings(true, targetSize); // will do reset - NOTE: Always compressed
|
_packetData.changeSettings(true, targetSize); // will do reset - NOTE: Always compressed
|
||||||
}
|
}
|
||||||
OctreeServer::trackTreeWaitTime(lockWaitElapsedUsec);
|
|
||||||
OctreeServer::trackEncodeTime(encodeElapsedUsec);
|
|
||||||
OctreeServer::trackCompressAndWriteTime(compressAndWriteElapsedUsec);
|
OctreeServer::trackCompressAndWriteTime(compressAndWriteElapsedUsec);
|
||||||
OctreeServer::trackPacketSendingTime(packetSendingElapsedUsec);
|
OctreeServer::trackPacketSendingTime(packetSendingElapsedUsec);
|
||||||
|
OctreeServer::trackInsideTime((float)(usecTimestampNow() - startInside));
|
||||||
quint64 endInside = usecTimestampNow();
|
|
||||||
quint64 elapsedInsideUsecs = endInside - startInside;
|
|
||||||
OctreeServer::trackInsideTime((float)elapsedInsideUsecs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
||||||
|
|
|
@ -53,7 +53,9 @@ protected:
|
||||||
|
|
||||||
/// Called before a packetDistributor pass to allow for pre-distribution processing
|
/// Called before a packetDistributor pass to allow for pre-distribution processing
|
||||||
virtual void preDistributionProcessing() {};
|
virtual void preDistributionProcessing() {};
|
||||||
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene);
|
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
|
||||||
|
bool viewFrustumChanged, bool isFullScene);
|
||||||
|
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params);
|
||||||
|
|
||||||
OctreeServer* _myServer { nullptr };
|
OctreeServer* _myServer { nullptr };
|
||||||
QWeakPointer<Node> _node;
|
QWeakPointer<Node> _node;
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
|
|
||||||
int OctreeServer::_clientCount = 0;
|
int OctreeServer::_clientCount = 0;
|
||||||
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000000;
|
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000;
|
||||||
|
|
||||||
float OctreeServer::SKIP_TIME = -1.0f; // use this for trackXXXTime() calls for non-times
|
float OctreeServer::SKIP_TIME = -1.0f; // use this for trackXXXTime() calls for non-times
|
||||||
|
|
||||||
|
@ -136,18 +136,19 @@ void OctreeServer::trackEncodeTime(float time) {
|
||||||
|
|
||||||
if (time == SKIP_TIME) {
|
if (time == SKIP_TIME) {
|
||||||
_noEncode++;
|
_noEncode++;
|
||||||
time = 0.0f;
|
|
||||||
} else if (time <= MAX_SHORT_TIME) {
|
|
||||||
_shortEncode++;
|
|
||||||
_averageShortEncodeTime.updateAverage(time);
|
|
||||||
} else if (time <= MAX_LONG_TIME) {
|
|
||||||
_longEncode++;
|
|
||||||
_averageLongEncodeTime.updateAverage(time);
|
|
||||||
} else {
|
} else {
|
||||||
_extraLongEncode++;
|
if (time <= MAX_SHORT_TIME) {
|
||||||
_averageExtraLongEncodeTime.updateAverage(time);
|
_shortEncode++;
|
||||||
|
_averageShortEncodeTime.updateAverage(time);
|
||||||
|
} else if (time <= MAX_LONG_TIME) {
|
||||||
|
_longEncode++;
|
||||||
|
_averageLongEncodeTime.updateAverage(time);
|
||||||
|
} else {
|
||||||
|
_extraLongEncode++;
|
||||||
|
_averageExtraLongEncodeTime.updateAverage(time);
|
||||||
|
}
|
||||||
|
_averageEncodeTime.updateAverage(time);
|
||||||
}
|
}
|
||||||
_averageEncodeTime.updateAverage(time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeServer::trackTreeWaitTime(float time) {
|
void OctreeServer::trackTreeWaitTime(float time) {
|
||||||
|
@ -155,18 +156,19 @@ void OctreeServer::trackTreeWaitTime(float time) {
|
||||||
const float MAX_LONG_TIME = 100.0f;
|
const float MAX_LONG_TIME = 100.0f;
|
||||||
if (time == SKIP_TIME) {
|
if (time == SKIP_TIME) {
|
||||||
_noTreeWait++;
|
_noTreeWait++;
|
||||||
time = 0.0f;
|
|
||||||
} else if (time <= MAX_SHORT_TIME) {
|
|
||||||
_shortTreeWait++;
|
|
||||||
_averageTreeShortWaitTime.updateAverage(time);
|
|
||||||
} else if (time <= MAX_LONG_TIME) {
|
|
||||||
_longTreeWait++;
|
|
||||||
_averageTreeLongWaitTime.updateAverage(time);
|
|
||||||
} else {
|
} else {
|
||||||
_extraLongTreeWait++;
|
if (time <= MAX_SHORT_TIME) {
|
||||||
_averageTreeExtraLongWaitTime.updateAverage(time);
|
_shortTreeWait++;
|
||||||
|
_averageTreeShortWaitTime.updateAverage(time);
|
||||||
|
} else if (time <= MAX_LONG_TIME) {
|
||||||
|
_longTreeWait++;
|
||||||
|
_averageTreeLongWaitTime.updateAverage(time);
|
||||||
|
} else {
|
||||||
|
_extraLongTreeWait++;
|
||||||
|
_averageTreeExtraLongWaitTime.updateAverage(time);
|
||||||
|
}
|
||||||
|
_averageTreeWaitTime.updateAverage(time);
|
||||||
}
|
}
|
||||||
_averageTreeWaitTime.updateAverage(time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeServer::trackCompressAndWriteTime(float time) {
|
void OctreeServer::trackCompressAndWriteTime(float time) {
|
||||||
|
@ -174,26 +176,27 @@ void OctreeServer::trackCompressAndWriteTime(float time) {
|
||||||
const float MAX_LONG_TIME = 100.0f;
|
const float MAX_LONG_TIME = 100.0f;
|
||||||
if (time == SKIP_TIME) {
|
if (time == SKIP_TIME) {
|
||||||
_noCompress++;
|
_noCompress++;
|
||||||
time = 0.0f;
|
|
||||||
} else if (time <= MAX_SHORT_TIME) {
|
|
||||||
_shortCompress++;
|
|
||||||
_averageShortCompressTime.updateAverage(time);
|
|
||||||
} else if (time <= MAX_LONG_TIME) {
|
|
||||||
_longCompress++;
|
|
||||||
_averageLongCompressTime.updateAverage(time);
|
|
||||||
} else {
|
} else {
|
||||||
_extraLongCompress++;
|
if (time <= MAX_SHORT_TIME) {
|
||||||
_averageExtraLongCompressTime.updateAverage(time);
|
_shortCompress++;
|
||||||
|
_averageShortCompressTime.updateAverage(time);
|
||||||
|
} else if (time <= MAX_LONG_TIME) {
|
||||||
|
_longCompress++;
|
||||||
|
_averageLongCompressTime.updateAverage(time);
|
||||||
|
} else {
|
||||||
|
_extraLongCompress++;
|
||||||
|
_averageExtraLongCompressTime.updateAverage(time);
|
||||||
|
}
|
||||||
|
_averageCompressAndWriteTime.updateAverage(time);
|
||||||
}
|
}
|
||||||
_averageCompressAndWriteTime.updateAverage(time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeServer::trackPacketSendingTime(float time) {
|
void OctreeServer::trackPacketSendingTime(float time) {
|
||||||
if (time == SKIP_TIME) {
|
if (time == SKIP_TIME) {
|
||||||
_noSend++;
|
_noSend++;
|
||||||
time = 0.0f;
|
} else {
|
||||||
|
_averagePacketSendingTime.updateAverage(time);
|
||||||
}
|
}
|
||||||
_averagePacketSendingTime.updateAverage(time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,18 +205,19 @@ void OctreeServer::trackProcessWaitTime(float time) {
|
||||||
const float MAX_LONG_TIME = 100.0f;
|
const float MAX_LONG_TIME = 100.0f;
|
||||||
if (time == SKIP_TIME) {
|
if (time == SKIP_TIME) {
|
||||||
_noProcessWait++;
|
_noProcessWait++;
|
||||||
time = 0.0f;
|
|
||||||
} else if (time <= MAX_SHORT_TIME) {
|
|
||||||
_shortProcessWait++;
|
|
||||||
_averageProcessShortWaitTime.updateAverage(time);
|
|
||||||
} else if (time <= MAX_LONG_TIME) {
|
|
||||||
_longProcessWait++;
|
|
||||||
_averageProcessLongWaitTime.updateAverage(time);
|
|
||||||
} else {
|
} else {
|
||||||
_extraLongProcessWait++;
|
if (time <= MAX_SHORT_TIME) {
|
||||||
_averageProcessExtraLongWaitTime.updateAverage(time);
|
_shortProcessWait++;
|
||||||
|
_averageProcessShortWaitTime.updateAverage(time);
|
||||||
|
} else if (time <= MAX_LONG_TIME) {
|
||||||
|
_longProcessWait++;
|
||||||
|
_averageProcessLongWaitTime.updateAverage(time);
|
||||||
|
} else {
|
||||||
|
_extraLongProcessWait++;
|
||||||
|
_averageProcessExtraLongWaitTime.updateAverage(time);
|
||||||
|
}
|
||||||
|
_averageProcessWaitTime.updateAverage(time);
|
||||||
}
|
}
|
||||||
_averageProcessWaitTime.updateAverage(time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OctreeServer::OctreeServer(ReceivedMessage& message) :
|
OctreeServer::OctreeServer(ReceivedMessage& message) :
|
||||||
|
|
|
@ -431,7 +431,7 @@ int Octree::readElementData(const OctreeElementPointer& destinationElement, cons
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long int bufferSizeBytes,
|
void Octree::readBitstreamToTree(const unsigned char * bitstream, uint64_t bufferSizeBytes,
|
||||||
ReadBitstreamToTreeParams& args) {
|
ReadBitstreamToTreeParams& args) {
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
const unsigned char* bitstreamAt = bitstream;
|
const unsigned char* bitstreamAt = bitstream;
|
||||||
|
@ -925,8 +925,8 @@ int Octree::encodeTreeBitstream(const OctreeElementPointer& element,
|
||||||
roomForOctalCode = packetData->startSubTree(newCode);
|
roomForOctalCode = packetData->startSubTree(newCode);
|
||||||
|
|
||||||
if (newCode) {
|
if (newCode) {
|
||||||
delete[] newCode;
|
|
||||||
codeLength = numberOfThreeBitSectionsInCode(newCode);
|
codeLength = numberOfThreeBitSectionsInCode(newCode);
|
||||||
|
delete[] newCode;
|
||||||
} else {
|
} else {
|
||||||
codeLength = 1;
|
codeLength = 1;
|
||||||
}
|
}
|
||||||
|
@ -1152,7 +1152,6 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
||||||
OctreeElementPointer sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
OctreeElementPointer sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||||
float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
int currentCount = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
OctreeElementPointer childElement = element->getChildAtIndex(i);
|
OctreeElementPointer childElement = element->getChildAtIndex(i);
|
||||||
|
@ -1174,7 +1173,6 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
||||||
sortedChildren[i] = childElement;
|
sortedChildren[i] = childElement;
|
||||||
indexOfChildren[i] = i;
|
indexOfChildren[i] = i;
|
||||||
distancesToChildren[i] = 0.0f;
|
distancesToChildren[i] = 0.0f;
|
||||||
currentCount++;
|
|
||||||
|
|
||||||
// track stats
|
// track stats
|
||||||
// must check childElement here, because it could be we got here with no childElement
|
// must check childElement here, because it could be we got here with no childElement
|
||||||
|
@ -1185,7 +1183,7 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
||||||
|
|
||||||
// for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
// for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
||||||
// add them to our distance ordered array of children
|
// add them to our distance ordered array of children
|
||||||
for (int i = 0; i < currentCount; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
OctreeElementPointer childElement = sortedChildren[i];
|
OctreeElementPointer childElement = sortedChildren[i];
|
||||||
int originalIndex = indexOfChildren[i];
|
int originalIndex = indexOfChildren[i];
|
||||||
|
|
||||||
|
@ -1276,7 +1274,7 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: the childrenDataBits indicates that there is an array of child element data included in this packet.
|
// NOTE: the childrenDataBits indicates that there is an array of child element data included in this packet.
|
||||||
// We wil write this bit mask but we may come back later and update the bits that are actually included
|
// We will write this bit mask but we may come back later and update the bits that are actually included
|
||||||
packetData->releaseReservedBytes(sizeof(childrenDataBits));
|
packetData->releaseReservedBytes(sizeof(childrenDataBits));
|
||||||
continueThisLevel = packetData->appendBitMask(childrenDataBits);
|
continueThisLevel = packetData->appendBitMask(childrenDataBits);
|
||||||
|
|
||||||
|
@ -1441,7 +1439,7 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
||||||
|
|
||||||
// for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
// for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
||||||
// add them to our distance ordered array of children
|
// add them to our distance ordered array of children
|
||||||
for (int indexByDistance = 0; indexByDistance < currentCount; indexByDistance++) {
|
for (int indexByDistance = 0; indexByDistance < NUMBER_OF_CHILDREN; indexByDistance++) {
|
||||||
OctreeElementPointer childElement = sortedChildren[indexByDistance];
|
OctreeElementPointer childElement = sortedChildren[indexByDistance];
|
||||||
int originalIndex = indexOfChildren[indexByDistance];
|
int originalIndex = indexOfChildren[indexByDistance];
|
||||||
|
|
||||||
|
@ -1638,7 +1636,7 @@ bool Octree::readFromFile(const char* fileName) {
|
||||||
|
|
||||||
QDataStream fileInputStream(&file);
|
QDataStream fileInputStream(&file);
|
||||||
QFileInfo fileInfo(qFileName);
|
QFileInfo fileInfo(qFileName);
|
||||||
unsigned long fileLength = fileInfo.size();
|
uint64_t fileLength = fileInfo.size();
|
||||||
|
|
||||||
emit importSize(1.0f, 1.0f, 1.0f);
|
emit importSize(1.0f, 1.0f, 1.0f);
|
||||||
emit importProgress(0);
|
emit importProgress(0);
|
||||||
|
@ -1715,7 +1713,7 @@ bool Octree::readFromURL(const QString& urlString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID) {
|
bool Octree::readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID) {
|
||||||
// decide if this is binary SVO or JSON-formatted SVO
|
// decide if this is binary SVO or JSON-formatted SVO
|
||||||
QIODevice *device = inputStream.device();
|
QIODevice *device = inputStream.device();
|
||||||
char firstChar;
|
char firstChar;
|
||||||
|
@ -1732,14 +1730,14 @@ bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStream) {
|
bool Octree::readSVOFromStream(uint64_t streamLength, QDataStream& inputStream) {
|
||||||
qWarning() << "SVO file format depricated. Support for reading SVO files is no longer support and will be removed soon.";
|
qWarning() << "SVO file format depricated. Support for reading SVO files is no longer support and will be removed soon.";
|
||||||
|
|
||||||
bool fileOk = false;
|
bool fileOk = false;
|
||||||
|
|
||||||
PacketVersion gotVersion = 0;
|
PacketVersion gotVersion = 0;
|
||||||
|
|
||||||
unsigned long headerLength = 0; // bytes in the header
|
uint64_t headerLength = 0; // bytes in the header
|
||||||
|
|
||||||
bool wantImportProgress = true;
|
bool wantImportProgress = true;
|
||||||
|
|
||||||
|
@ -1751,14 +1749,14 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
||||||
if (getWantSVOfileVersions()) {
|
if (getWantSVOfileVersions()) {
|
||||||
|
|
||||||
// read just enough of the file to parse the header...
|
// read just enough of the file to parse the header...
|
||||||
const unsigned long HEADER_LENGTH = sizeof(int) + sizeof(PacketVersion);
|
const uint64_t HEADER_LENGTH = sizeof(int) + sizeof(PacketVersion);
|
||||||
unsigned char fileHeader[HEADER_LENGTH];
|
unsigned char fileHeader[HEADER_LENGTH];
|
||||||
inputStream.readRawData((char*)&fileHeader, HEADER_LENGTH);
|
inputStream.readRawData((char*)&fileHeader, HEADER_LENGTH);
|
||||||
|
|
||||||
headerLength = HEADER_LENGTH; // we need this later to skip to the data
|
headerLength = HEADER_LENGTH; // we need this later to skip to the data
|
||||||
|
|
||||||
unsigned char* dataAt = (unsigned char*)&fileHeader;
|
unsigned char* dataAt = (unsigned char*)&fileHeader;
|
||||||
unsigned long dataLength = HEADER_LENGTH;
|
uint64_t dataLength = HEADER_LENGTH;
|
||||||
|
|
||||||
// if so, read the first byte of the file and see if it matches the expected version code
|
// if so, read the first byte of the file and see if it matches the expected version code
|
||||||
int intPacketType;
|
int intPacketType;
|
||||||
|
@ -1804,7 +1802,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
||||||
if (!hasBufferBreaks) {
|
if (!hasBufferBreaks) {
|
||||||
|
|
||||||
// read the entire file into a buffer, WHAT!? Why not.
|
// read the entire file into a buffer, WHAT!? Why not.
|
||||||
unsigned long dataLength = streamLength - headerLength;
|
uint64_t dataLength = streamLength - headerLength;
|
||||||
unsigned char* entireFileDataSection = new unsigned char[dataLength];
|
unsigned char* entireFileDataSection = new unsigned char[dataLength];
|
||||||
inputStream.readRawData((char*)entireFileDataSection, dataLength);
|
inputStream.readRawData((char*)entireFileDataSection, dataLength);
|
||||||
|
|
||||||
|
@ -1819,9 +1817,9 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
unsigned long dataLength = streamLength - headerLength;
|
uint64_t dataLength = streamLength - headerLength;
|
||||||
unsigned long remainingLength = dataLength;
|
uint64_t remainingLength = dataLength;
|
||||||
const unsigned long MAX_CHUNK_LENGTH = MAX_OCTREE_PACKET_SIZE * 2;
|
const uint64_t MAX_CHUNK_LENGTH = MAX_OCTREE_PACKET_SIZE * 2;
|
||||||
unsigned char* fileChunk = new unsigned char[MAX_CHUNK_LENGTH];
|
unsigned char* fileChunk = new unsigned char[MAX_CHUNK_LENGTH];
|
||||||
|
|
||||||
while (remainingLength > 0) {
|
while (remainingLength > 0) {
|
||||||
|
@ -1847,7 +1845,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
||||||
remainingLength -= chunkLength;
|
remainingLength -= chunkLength;
|
||||||
|
|
||||||
unsigned char* dataAt = fileChunk;
|
unsigned char* dataAt = fileChunk;
|
||||||
unsigned long dataLength = chunkLength;
|
uint64_t dataLength = chunkLength;
|
||||||
|
|
||||||
ReadBitstreamToTreeParams args(NO_EXISTS_BITS, NULL, 0,
|
ReadBitstreamToTreeParams args(NO_EXISTS_BITS, NULL, 0,
|
||||||
SharedNodePointer(), wantImportProgress, gotVersion);
|
SharedNodePointer(), wantImportProgress, gotVersion);
|
||||||
|
@ -1887,7 +1885,7 @@ QJsonDocument addMarketplaceIDToDocumentEntities(QJsonDocument& doc, const QStri
|
||||||
|
|
||||||
const int READ_JSON_BUFFER_SIZE = 2048;
|
const int READ_JSON_BUFFER_SIZE = 2048;
|
||||||
|
|
||||||
bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID /*=""*/) {
|
bool Octree::readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID /*=""*/) {
|
||||||
// if the data is gzipped we may not have a useful bytesAvailable() result, so just keep reading until
|
// if the data is gzipped we may not have a useful bytesAvailable() result, so just keep reading until
|
||||||
// we get an eof. Leave streamLength parameter for consistency.
|
// we get an eof. Leave streamLength parameter for consistency.
|
||||||
|
|
||||||
|
@ -1982,14 +1980,14 @@ bool Octree::writeToJSONFile(const char* fileName, const OctreeElementPointer& e
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long Octree::getOctreeElementsCount() {
|
uint64_t Octree::getOctreeElementsCount() {
|
||||||
unsigned long nodeCount = 0;
|
uint64_t nodeCount = 0;
|
||||||
recurseTreeWithOperation(countOctreeElementsOperation, &nodeCount);
|
recurseTreeWithOperation(countOctreeElementsOperation, &nodeCount);
|
||||||
return nodeCount;
|
return nodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::countOctreeElementsOperation(const OctreeElementPointer& element, void* extraData) {
|
bool Octree::countOctreeElementsOperation(const OctreeElementPointer& element, void* extraData) {
|
||||||
(*(unsigned long*)extraData)++;
|
(*(uint64_t*)extraData)++;
|
||||||
return true; // keep going
|
return true; // keep going
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
@ -231,7 +232,7 @@ public:
|
||||||
|
|
||||||
virtual void eraseAllOctreeElements(bool createNewRoot = true);
|
virtual void eraseAllOctreeElements(bool createNewRoot = true);
|
||||||
|
|
||||||
void readBitstreamToTree(const unsigned char* bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args);
|
void readBitstreamToTree(const unsigned char* bitstream, uint64_t bufferSizeBytes, ReadBitstreamToTreeParams& args);
|
||||||
void deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool collapseEmptyTrees = DONT_COLLAPSE);
|
void deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool collapseEmptyTrees = DONT_COLLAPSE);
|
||||||
void reaverageOctreeElements(OctreeElementPointer startElement = OctreeElementPointer());
|
void reaverageOctreeElements(OctreeElementPointer startElement = OctreeElementPointer());
|
||||||
|
|
||||||
|
@ -301,13 +302,13 @@ public:
|
||||||
// Octree importers
|
// Octree importers
|
||||||
bool readFromFile(const char* filename);
|
bool readFromFile(const char* filename);
|
||||||
bool readFromURL(const QString& url); // will support file urls as well...
|
bool readFromURL(const QString& url); // will support file urls as well...
|
||||||
bool readFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
bool readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||||
bool readSVOFromStream(unsigned long streamLength, QDataStream& inputStream);
|
bool readSVOFromStream(uint64_t streamLength, QDataStream& inputStream);
|
||||||
bool readJSONFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
bool readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||||
bool readJSONFromGzippedFile(QString qFileName);
|
bool readJSONFromGzippedFile(QString qFileName);
|
||||||
virtual bool readFromMap(QVariantMap& entityDescription) = 0;
|
virtual bool readFromMap(QVariantMap& entityDescription) = 0;
|
||||||
|
|
||||||
unsigned long getOctreeElementsCount();
|
uint64_t getOctreeElementsCount();
|
||||||
|
|
||||||
bool getShouldReaverage() const { return _shouldReaverage; }
|
bool getShouldReaverage() const { return _shouldReaverage; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue