cleanup EncodeBitstreamParams to use nodeData when possible

This commit is contained in:
Stephen Birarda 2017-01-20 15:00:56 -08:00
parent 9b26e8ee95
commit 53e6a77fcc
23 changed files with 129 additions and 220 deletions

View file

@ -443,13 +443,8 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
viewFrustumChanged,
boundaryLevelAdjust, octreeSizeScale,
nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
&nodeData->extraEncodeData,
nodeData->getUsesFrustum(),
nodeData);
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
isFullScene, _myServer->getJurisdiction(), nodeData);
nodeData->copyCurrentViewFrustum(params.viewFrustum);
if (viewFrustumChanged) {
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);

View file

@ -125,7 +125,7 @@ public:
void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); }
quint64 getLastChangedOnServer() const { return _changedOnServer; }
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -51,7 +51,10 @@ void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) cons
qCDebug(entities) << "EntityTreeElement::debugExtraEncodeData()... ";
qCDebug(entities) << " element:" << _cube;
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
assert(entityNodeData);
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) {
@ -65,7 +68,11 @@ void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) cons
void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
assert(entityNodeData);
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
// Check to see if this element yet has encode data... if it doesn't create it
if (!extraEncodeData->contains(this)) {
@ -93,7 +100,11 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params)
}
bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
assert(entityNodeData);
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) {
@ -122,7 +133,10 @@ bool EntityTreeElement::shouldRecurseChildTree(int childIndex, EncodeBitstreamPa
}
bool EntityTreeElement::alreadyFullyEncoded(EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
assert(entityNodeData);
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) {
@ -137,8 +151,12 @@ bool EntityTreeElement::alreadyFullyEncoded(EncodeBitstreamParams& params) const
}
void EntityTreeElement::updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
assert(entityNodeData);
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) {
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData
= std::static_pointer_cast<EntityTreeElementExtraEncodeData>((*extraEncodeData)[this]);
@ -161,7 +179,10 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) con
qCDebug(entities) << "EntityTreeElement::elementEncodeComplete() element:" << _cube;
}
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
assert(entityNodeData);
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
assert(extraEncodeData->contains(this));
@ -236,8 +257,12 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best...
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
Q_ASSERT_X(entityNodeData, "EntityTreeElement::appendElementData", "expected params.nodeData not to be null");
// first, check the params.extraEncodeData to see if there's any partial re-encode data for this element
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
OctreeElementExtraEncodeData* extraEncodeData = &entityNodeData->extraEncodeData;
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData = NULL;
bool hadElementExtraData = false;
if (extraEncodeData && extraEncodeData->contains(this)) {
@ -285,20 +310,17 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// need to handle the case where our sibling elements need encoding but we don't.
if (!entityTreeElementExtraEncodeData->elementCompleted) {
QJsonObject jsonFilters;
auto entityNodeData = static_cast<EntityNodeData*>(params.nodeData);
if (entityNodeData) {
// we have an EntityNodeData instance
// so we should assume that means we might have JSON filters to check
jsonFilters = entityNodeData->getJSONParameters();
}
// we have an EntityNodeData instance
// so we should assume that means we might have JSON filters to check
auto jsonFilters = entityNodeData->getJSONParameters();
for (uint16_t i = 0; i < _entityItems.size(); i++) {
EntityItemPointer entity = _entityItems[i];
bool includeThisEntity = true;
if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastQuerySent) {
if (!params.forceSendScene && entity->getLastChangedOnServer() < entityNodeData->getLastTimeBagEmpty()) {
includeThisEntity = false;
}
@ -330,7 +352,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// we only check the bounds against our frustum and LOD if the query has asked us to check against the frustum
// which can sometimes not be the case when JSON filters are sent
if (params.usesFrustum && (includeThisEntity || params.recurseEverything)) {
if (entityNodeData->getUsesFrustum() && (includeThisEntity || params.recurseEverything)) {
// we want to use the maximum possible box for this, so that we don't have to worry about the nuance of
// simulation changing what's visible. consider the case where the entity contains an angular velocity

View file

@ -174,7 +174,7 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags LightEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_IS_SPOTLIGHT;

View file

@ -126,7 +126,7 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags LineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;

View file

@ -26,7 +26,7 @@ class LineEntityItem : public EntityItem {
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -160,7 +160,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
return bytesRead;
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);

View file

@ -29,7 +29,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -469,7 +469,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);

View file

@ -170,7 +170,7 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;

View file

@ -26,7 +26,7 @@ class PolyLineEntityItem : public EntityItem {
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -179,7 +179,7 @@ int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* dat
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_VOXEL_VOLUME_SIZE;

View file

@ -26,7 +26,7 @@ class PolyVoxEntityItem : public EntityItem {
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -137,7 +137,7 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_SHAPE;

View file

@ -99,7 +99,7 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_TEXT;

View file

@ -30,7 +30,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -84,7 +84,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_SOURCE_URL;

View file

@ -29,7 +29,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -137,7 +137,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);

View file

@ -30,7 +30,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastQuerySent time
// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -43,14 +43,15 @@
#include <PathUtils.h>
#include <ViewFrustum.h>
#include "Octree.h"
#include "OctreeConstants.h"
#include "OctreeElementBag.h"
#include "Octree.h"
#include "OctreeUtils.h"
#include "OctreeLogging.h"
#include "OctreeQueryNode.h"
#include "OctreeUtils.h"
QVector<QString> PERSIST_EXTENSIONS = {"svo", "json", "json.gz"};
QVector<QString> PERSIST_EXTENSIONS = {"json", "json.gz"};
Octree::Octree(bool shouldReaverage) :
_rootElement(NULL),
@ -898,8 +899,16 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element,
return bytesWritten;
}
// you can't call this without a valid nodeData
auto octreeQueryNode = static_cast<OctreeQueryNode*>(params.nodeData);
if (!octreeQueryNode) {
qCDebug(octree, "WARNING! encodeTreeBitstream() called with nodeData=NULL");
params.stopReason = EncodeBitstreamParams::NULL_NODE_DATA;
return bytesWritten;
}
// If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
if (params.usesFrustum && !params.recurseEverything && !element->isInView(params.viewFrustum)) {
if (octreeQueryNode->getUsesFrustum() && !params.recurseEverything && !element->isInView(params.viewFrustum)) {
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
return bytesWritten;
}
@ -935,9 +944,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element,
// record some stats, this is the one element that we won't record below in the recursion function, so we need to
// track it here
if (params.stats) {
params.stats->traversed(element);
}
octreeQueryNode->stats.traversed(element);
ViewFrustum::intersection parentLocationThisView = ViewFrustum::INTERSECT; // assume parent is in view, but not fully
@ -993,6 +1000,15 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
return bytesAtThisLevel;
}
// you can't call this without a valid nodeData
auto octreeQueryNode = static_cast<OctreeQueryNode*>(params.nodeData);
if (!octreeQueryNode) {
qCDebug(octree, "WARNING! encodeTreeBitstream() called with nodeData=NULL");
params.stopReason = EncodeBitstreamParams::NULL_NODE_DATA;
return bytesAtThisLevel;
}
// Keep track of how deep we've encoded.
currentEncodeLevel++;
@ -1015,15 +1031,13 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
}
ViewFrustum::intersection nodeLocationThisView = ViewFrustum::INSIDE; // assume we're inside
if (params.usesFrustum && !params.recurseEverything) {
if (octreeQueryNode->getUsesFrustum() && !params.recurseEverything) {
float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
// If we're too far away for our render level, then just return
if (element->distanceToCamera(params.viewFrustum) >= boundaryDistance) {
if (params.stats) {
params.stats->skippedDistance(element);
}
octreeQueryNode->stats.skippedDistance(element);
params.stopReason = EncodeBitstreamParams::LOD_SKIP;
return bytesAtThisLevel;
}
@ -1039,9 +1053,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
// we're out of view
if (nodeLocationThisView == ViewFrustum::OUTSIDE) {
if (params.stats) {
params.stats->skippedOutOfView(element);
}
octreeQueryNode->stats.skippedOutOfView(element);
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
return bytesAtThisLevel;
}
@ -1066,7 +1078,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// as "was in view"...
if (wasInView) {
float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
params.octreeElementSizeScale);
if (element->distanceToCamera(params.lastViewFrustum) >= boundaryDistance) {
// This would have been invisible... but now should be visible (we wouldn't be here otherwise)...
wasInView = false;
@ -1077,22 +1089,20 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// If we were previously in the view, then we normally will return out of here and stop recursing. But
// if we're in deltaView mode, and this element has changed since it was last sent, then we do
// need to send it.
if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE))) {
if (params.stats) {
params.stats->skippedWasInView(element);
}
if (wasInView && !(params.deltaView && element->hasChangedSince(octreeQueryNode->getLastTimeBagEmpty() - CHANGE_FUDGE))) {
octreeQueryNode->stats.skippedWasInView(element);
params.stopReason = EncodeBitstreamParams::WAS_IN_VIEW;
return bytesAtThisLevel;
}
}
// If we're not in delta sending mode, and we weren't asked to do a force send, and the octree element hasn't changed,
// If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed,
// then we can also bail early and save bits
if (!params.forceSendScene && !params.deltaView &&
!element->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE)) {
if (params.stats) {
params.stats->skippedNoChange(element);
}
!element->hasChangedSince(octreeQueryNode->getLastTimeBagEmpty() - CHANGE_FUDGE)) {
octreeQueryNode->stats.skippedNoChange(element);
params.stopReason = EncodeBitstreamParams::NO_CHANGE;
return bytesAtThisLevel;
}
@ -1164,8 +1174,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// track stats
// must check childElement here, because it could be we got here with no childElement
if (params.stats && childElement) {
params.stats->traversed(childElement);
if (childElement) {
octreeQueryNode->stats.traversed(childElement);
}
}
@ -1176,7 +1186,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
int originalIndex = indexOfChildren[i];
bool childIsInView = (childElement &&
(params.recurseEverything || !params.usesFrustum ||
(params.recurseEverything || !octreeQueryNode->getUsesFrustum() ||
(nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
(nodeLocationThisView == ViewFrustum::INTERSECT &&
childElement->isInView(params.viewFrustum)) // the parent intersects and the child is in view
@ -1184,20 +1194,18 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
if (!childIsInView) {
// must check childElement here, because it could be we got here because there was no childElement
if (params.stats && childElement) {
params.stats->skippedOutOfView(childElement);
if (childElement) {
octreeQueryNode->stats.skippedOutOfView(childElement);
}
} else {
// Before we consider this further, let's see if it's in our LOD scope...
float boundaryDistance = params.recurseEverything || !params.usesFrustum ? 1 :
float boundaryDistance = params.recurseEverything || !octreeQueryNode->getUsesFrustum() ? 1 :
boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
if (!(distancesToChildren[i] < boundaryDistance)) {
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats) {
params.stats->skippedDistance(childElement);
}
octreeQueryNode->stats.skippedDistance(childElement);
} else {
inViewCount++;
@ -1211,20 +1219,18 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bool childIsOccluded = false; // assume it's not occluded
bool shouldRender = params.recurseEverything || !params.usesFrustum ||
bool shouldRender = params.recurseEverything || !octreeQueryNode->getUsesFrustum() ||
childElement->calculateShouldRender(params.viewFrustum,
params.octreeElementSizeScale, params.boundaryLevelAdjust);
// track some stats
if (params.stats) {
// don't need to check childElement here, because we can't get here with no childElement
if (!shouldRender && childElement->isLeaf()) {
params.stats->skippedDistance(childElement);
}
// don't need to check childElement here, because we can't get here with no childElement
if (childIsOccluded) {
params.stats->skippedOccluded(childElement);
}
// don't need to check childElement here, because we can't get here with no childElement
if (!shouldRender && childElement->isLeaf()) {
octreeQueryNode->stats.skippedDistance(childElement);
}
// don't need to check childElement here, because we can't get here with no childElement
if (childIsOccluded) {
octreeQueryNode->stats.skippedOccluded(childElement);
}
// track children with actual color, only if the child wasn't previously in view!
@ -1247,19 +1253,17 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// need to send it.
if (!childWasInView ||
(params.deltaView &&
childElement->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE))){
childElement->hasChangedSince(octreeQueryNode->getLastTimeBagEmpty() - CHANGE_FUDGE))){
childrenDataBits += (1 << (7 - originalIndex));
inViewWithColorCount++;
} else {
// otherwise just track stats of the items we discarded
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats) {
if (childWasInView) {
params.stats->skippedWasInView(childElement);
} else {
params.stats->skippedNoChange(childElement);
}
if (childWasInView) {
octreeQueryNode->stats.skippedWasInView(childElement);
} else {
octreeQueryNode->stats.skippedNoChange(childElement);
}
}
}
@ -1277,9 +1281,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
assert(continueThisLevel); // since we used reserved bits, this really shouldn't fail
bytesAtThisLevel += sizeof(childrenDataBits); // keep track of byte count
if (params.stats) {
params.stats->colorBitsWritten(); // really data bits not just color bits
}
octreeQueryNode->stats.colorBitsWritten(); // really data bits not just color bits
// NOW might be a good time to give our tree subclass and this element a chance to set up and check any extra encode data
element->initializeExtraEncodeData(params);
@ -1349,8 +1352,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bytesAtThisLevel += (bytesAfterChild - bytesBeforeChild); // keep track of byte count for this child
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats && (childAppendState != OctreeElement::NONE)) {
params.stats->colorSent(childElement);
if (childAppendState != OctreeElement::NONE) {
octreeQueryNode->stats.colorSent(childElement);
}
}
}
@ -1377,9 +1380,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
continueThisLevel = packetData->appendBitMask(childrenExistInTreeBits);
if (continueThisLevel) {
bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count
if (params.stats) {
params.stats->existsBitsWritten();
}
octreeQueryNode->stats.existsBitsWritten();
} else {
qCDebug(octree) << "WARNING UNEXPECTED CASE: Failed to append childrenExistInTreeBits";
qCDebug(octree) << "This is not expected!!!! -- continueThisLevel=FALSE....";
@ -1392,9 +1394,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
continueThisLevel = packetData->appendBitMask(childrenExistInPacketBits);
if (continueThisLevel) {
bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count
if (params.stats) {
params.stats->existsInPacketBitsWritten();
}
octreeQueryNode->stats.existsInPacketBitsWritten();
} else {
qCDebug(octree) << "WARNING UNEXPECTED CASE: Failed to append childrenExistInPacketBits";
qCDebug(octree) << "This is not expected!!!! -- continueThisLevel=FALSE....";
@ -1451,7 +1452,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep
// recursing, by returning TRUE in recurseChildrenWithData().
if (params.recurseEverything || !params.usesFrustum
if (params.recurseEverything || !octreeQueryNode->getUsesFrustum()
|| recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) {
// Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this
@ -1502,8 +1503,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
}
// If this is the last of the child exists bits, then we're actually be rolling out the entire tree
if (params.stats && childrenExistInPacketBits == 0) {
params.stats->childBitsRemoved(params.includeExistsBits);
if (childrenExistInPacketBits == 0) {
octreeQueryNode->stats.childBitsRemoved(params.includeExistsBits);
}
if (!continueThisLevel) {
@ -1558,9 +1559,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
if (continueThisLevel) {
bytesAtThisLevel += (bytesAfterChild - bytesBeforeChild); // keep track of byte count for this child
if (params.stats) {
params.stats->colorSent(element);
}
octreeQueryNode->stats.colorSent(element);
}
if (!continueThisLevel) {
@ -1595,9 +1594,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bag.insert(element);
// don't need to check element here, because we can't get here with no element
if (params.stats) {
params.stats->didntFit(element);
}
octreeQueryNode->stats.didntFit(element);
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
bytesAtThisLevel = 0; // didn't fit
@ -1876,9 +1873,7 @@ bool Octree::writeToFile(const char* fileName, OctreeElementPointer element, QSt
const char* cFileName = byteArray.constData();
bool success = false;
if (persistAsFileType == "svo") {
success = writeToSVOFile(fileName, element);
} else if (persistAsFileType == "json") {
if (persistAsFileType == "json") {
success = writeToJSONFile(cFileName, element);
} else if (persistAsFileType == "json.gz") {
success = writeToJSONFile(cFileName, element, true);
@ -1936,95 +1931,6 @@ bool Octree::writeToJSONFile(const char* fileName, OctreeElementPointer element,
return success;
}
bool Octree::writeToSVOFile(const char* fileName, OctreeElementPointer element) {
qWarning() << "SVO file format deprecated. Support for reading SVO files is no longer support and will be removed soon.";
bool success = false;
std::ofstream file(fileName, std::ios::out|std::ios::binary);
if(file.is_open()) {
qCDebug(octree, "Saving binary SVO to file %s...", fileName);
PacketType expectedPacketType = expectedDataPacketType();
int expectedIntType = (int) expectedPacketType;
PacketVersion expectedVersion = versionForPacketType(expectedPacketType);
bool hasBufferBreaks = versionHasSVOfileBreaks(expectedVersion);
// before reading the file, check to see if this version of the Octree supports file versions
if (getWantSVOfileVersions()) {
// if so, read the first byte of the file and see if it matches the expected version code
file.write(reinterpret_cast<char*>(&expectedIntType), sizeof(expectedIntType));
file.write(&expectedVersion, sizeof(expectedVersion));
qCDebug(octree) << "SVO file type: " << expectedPacketType << " version: " << (int)expectedVersion;
hasBufferBreaks = versionHasSVOfileBreaks(expectedVersion);
}
if (hasBufferBreaks) {
qCDebug(octree) << " this version includes buffer breaks";
} else {
qCDebug(octree) << " this version does not include buffer breaks";
}
OctreeElementBag elementBag;
OctreeElementExtraEncodeData extraEncodeData;
// If we were given a specific element, start from there, otherwise start from root
if (element) {
elementBag.insert(element);
} else {
elementBag.insert(_rootElement);
}
OctreePacketData packetData;
int bytesWritten = 0;
bool lastPacketWritten = false;
while (OctreeElementPointer subTree = elementBag.extract()) {
EncodeBitstreamParams params(INT_MAX, NO_EXISTS_BITS);
params.recurseEverything = true;
withReadLock([&] {
params.extraEncodeData = &extraEncodeData;
bytesWritten = encodeTreeBitstream(subTree, &packetData, elementBag, params);
});
// if the subTree couldn't fit, and so we should reset the packet and reinsert the element in our bag and try again
if (bytesWritten == 0 && (params.stopReason == EncodeBitstreamParams::DIDNT_FIT)) {
if (packetData.hasContent()) {
// if this type of SVO file should have buffer breaks, then we will write a buffer size before each
// buffer to allow the reader to read this file in chunks.
if (hasBufferBreaks) {
quint16 bufferSize = packetData.getFinalizedSize();
file.write((const char*)&bufferSize, sizeof(bufferSize));
}
file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize());
lastPacketWritten = true;
}
packetData.reset(); // is there a better way to do this? could we fit more?
elementBag.insert(subTree);
} else {
lastPacketWritten = false;
}
}
if (!lastPacketWritten) {
// if this type of SVO file should have buffer breaks, then we will write a buffer size before each
// buffer to allow the reader to read this file in chunks.
if (hasBufferBreaks) {
quint16 bufferSize = packetData.getFinalizedSize();
file.write((const char*)&bufferSize, sizeof(bufferSize));
}
file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize());
}
releaseSceneEncodeData(&extraEncodeData);
success = true;
}
file.close();
return success;
}
unsigned long Octree::getOctreeElementsCount() {
unsigned long nodeCount = 0;
recurseTreeWithOperation(countOctreeElementsOperation, &nodeCount);

View file

@ -59,9 +59,7 @@ const bool DONT_COLLAPSE = false;
const int DONT_CHOP = 0;
const int NO_BOUNDARY_ADJUST = 0;
const int LOW_RES_MOVING_ADJUST = 1;
const quint64 IGNORE_LAST_SENT = 0;
#define IGNORE_SCENE_STATS NULL
#define IGNORE_COVERAGE_MAP NULL
#define IGNORE_JURISDICTION_MAP NULL
@ -69,7 +67,6 @@ class EncodeBitstreamParams {
public:
ViewFrustum viewFrustum;
ViewFrustum lastViewFrustum;
quint64 lastQuerySent;
int maxEncodeLevel;
int maxLevelReached;
bool includeExistsBits;
@ -79,10 +76,7 @@ public:
int boundaryLevelAdjust;
float octreeElementSizeScale;
bool forceSendScene;
OctreeSceneStats* stats;
JurisdictionMap* jurisdictionMap;
OctreeElementExtraEncodeData* extraEncodeData;
bool usesFrustum;
NodeData* nodeData;
// output hints from the encode process
@ -90,6 +84,7 @@ public:
UNKNOWN,
DIDNT_FIT,
NULL_NODE,
NULL_NODE_DATA,
TOO_DEEP,
OUT_OF_JURISDICTION,
LOD_SKIP,
@ -107,14 +102,9 @@ public:
bool useDeltaView = false,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
quint64 lastQuerySent = IGNORE_LAST_SENT,
bool forceSendScene = true,
OctreeSceneStats* stats = IGNORE_SCENE_STATS,
JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP,
OctreeElementExtraEncodeData* extraEncodeData = nullptr,
bool usesFrustum = true,
NodeData* nodeData = nullptr) :
lastQuerySent(lastQuerySent),
maxEncodeLevel(maxEncodeLevel),
maxLevelReached(0),
includeExistsBits(includeExistsBits),
@ -123,10 +113,7 @@ public:
boundaryLevelAdjust(boundaryLevelAdjust),
octreeElementSizeScale(octreeElementSizeScale),
forceSendScene(forceSendScene),
stats(stats),
jurisdictionMap(jurisdictionMap),
extraEncodeData(extraEncodeData),
usesFrustum(usesFrustum),
nodeData(nodeData),
stopReason(UNKNOWN)
{
@ -306,9 +293,8 @@ public:
void loadOctreeFile(const char* fileName);
// Octree exporters
bool writeToFile(const char* filename, OctreeElementPointer element = NULL, QString persistAsFileType = "svo");
bool writeToFile(const char* filename, OctreeElementPointer element = NULL, QString persistAsFileType = "json.gz");
bool writeToJSONFile(const char* filename, OctreeElementPointer element = NULL, bool doGzip = false);
bool writeToSVOFile(const char* filename, OctreeElementPointer element = NULL);
virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues,
bool skipThoseWithBadParents) = 0;

View file

@ -35,7 +35,7 @@ public:
OctreePersistThread(OctreePointer tree, const QString& filename, const QString& backupDirectory,
int persistInterval = DEFAULT_PERSIST_INTERVAL, bool wantBackup = false,
const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false, QString persistAsFileType="svo");
const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false, QString persistAsFileType="json.gz");
bool isInitialLoadComplete() const { return _initialLoadComplete; }
quint64 getLoadElapsedTime() const { return _loadTimeUSecs; }