fix issue where we sometimes don't completely fill a packet mid scene

This commit is contained in:
ZappoMan 2013-11-24 20:29:54 -08:00
parent 0cd269632e
commit ed80895eb3
4 changed files with 61 additions and 9 deletions

View file

@ -350,6 +350,7 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
break;
}
bool lastNodeDidntFit = false; // assume each node fits
if (!nodeData->nodeBag.isEmpty()) {
VoxelNode* subTree = nodeData->nodeBag.extract();
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
@ -375,11 +376,9 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
_myServer->getServerTree().lockForRead();
nodeData->stats.encodeStarted();
bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, &_tempPacket, nodeData->nodeBag, params);
if (_tempPacket.hasContent() && bytesWritten == 0 && _tempPacket.getFinalizedSize() < 1450) {
printf(">>>>>>>>>>>>>>> got bytesWritten==0 _tempPacket.getFinalizedSize()=%d <<<<<<<<<<<<<<<\n",
_tempPacket.getFinalizedSize());
if (_tempPacket.hasContent() && bytesWritten == 0 && params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
lastNodeDidntFit = true;
}
if (bytesWritten > 0) {
@ -396,7 +395,7 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
// We only consider sending anything if there is something in the _tempPacket to send... But
// if bytesWritten == 0 it means either the subTree couldn't fit or we had an empty bag... Both cases
// mean we should send the previous packet contents and reset it.
bool sendNow = (bytesWritten == 0);
bool sendNow = lastNodeDidntFit;
if (_tempPacket.hasContent() && sendNow) {
if (_myServer->wantsDebugVoxelSending() && _myServer->wantsVerboseDebug()) {
printf("calling writeToPacket() compressedSize=%d uncompressedSize=%d\n",

View file

@ -11,7 +11,12 @@
// * determine why we sometimes don't fill packets very well (rarely) mid-scene... sometimes it appears as if
// the "next node" would encode with more bytes than can fit in the remainder of the packet. this might be
// several tens or hundreds of bytes, but theoretically other voxels would have fit. This happens in the 0100
// scene a couple times.
// scene a couple times.
// this is happening because of nodes that are not recursed for good reason like:
// - being occluded
// - being previously in view
// - being out of view, etc.
// in these cases, the node is not re-added to the bag... so, we can probably just keep going...
//
// * further testing of compression to determine optimal configuration for performance and compression
// * improve semantics for "reshuffle" - current approach will work for now and with compression

View file

@ -1031,6 +1031,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
// you can't call this without a valid node
if (!node) {
qDebug("WARNING! encodeTreeBitstream() called with node=NULL\n");
params.stopReason = EncodeBitstreamParams::NULL_NODE;
return bytesWritten;
}
@ -1039,6 +1040,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
if (params.viewFrustum && !node->isInView(*params.viewFrustum)) {
doneEncoding(node);
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
return bytesWritten;
}
@ -1063,6 +1065,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
if (!roomForOctalCode) {
doneEncoding(node);
bag.insert(node); // add the node back to the bag so it will eventually get included
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
return bytesWritten;
}
@ -1085,6 +1088,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
// couldn't be written... so reset them here... This isn't true for the non-color included case
if (params.includeColor && childBytesWritten == 2) {
childBytesWritten = 0;
//params.stopReason = EncodeBitstreamParams::UNKNOWN; // possibly should be DIDNT_FIT...
}
// if we wrote child bytes, then return our result of all bytes written
@ -1093,6 +1097,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
} else {
// otherwise... if we didn't write any child bytes, then pretend like we also didn't write our octal code
bytesWritten = 0;
//params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
}
if (bytesWritten == 0) {
@ -1115,6 +1120,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
// you can't call this without a valid node
if (!node) {
qDebug("WARNING! encodeTreeBitstreamRecursion() called with node=NULL\n");
params.stopReason = EncodeBitstreamParams::NULL_NODE;
return bytesAtThisLevel;
}
@ -1125,6 +1131,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
// If we've reached our max Search Level, then stop searching.
if (currentEncodeLevel >= params.maxEncodeLevel) {
params.stopReason = EncodeBitstreamParams::TOO_DEEP;
return bytesAtThisLevel;
}
@ -1133,6 +1140,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
// here's how it works... if we're currently above our root jurisdiction, then we proceed normally.
// but once we're in our own jurisdiction, then we need to make sure we're not below it.
if (JurisdictionMap::BELOW == params.jurisdictionMap->isMyJurisdiction(node->getOctalCode(), CHECK_NODE_ONLY)) {
params.stopReason = EncodeBitstreamParams::OUT_OF_JURISDICTION;
return bytesAtThisLevel;
}
}
@ -1148,6 +1156,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
if (params.stats) {
params.stats->skippedDistance(node);
}
params.stopReason = EncodeBitstreamParams::LOD_SKIP;
return bytesAtThisLevel;
}
@ -1158,6 +1167,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
if (params.stats) {
params.stats->skippedOutOfView(node);
}
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
return bytesAtThisLevel;
}
@ -1197,6 +1207,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
if (params.stats) {
params.stats->skippedWasInView(node);
}
params.stopReason = EncodeBitstreamParams::WAS_IN_VIEW;
return bytesAtThisLevel;
}
@ -1207,6 +1218,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
if (params.stats) {
params.stats->skippedNoChange(node);
}
params.stopReason = EncodeBitstreamParams::NO_CHANGE;
return bytesAtThisLevel;
}
@ -1226,6 +1238,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
if (params.stats) {
params.stats->skippedOccluded(node);
}
params.stopReason = EncodeBitstreamParams::OCCLUDED;
return bytesAtThisLevel;
}
} else {
@ -1616,7 +1629,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
params.stats->didntFit(node);
}
return 0;
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
bytesAtThisLevel = 0; // didn't fit
}
return bytesAtThisLevel;

View file

@ -66,6 +66,21 @@ public:
CoverageMap* map;
JurisdictionMap* jurisdictionMap;
// output hints from the encode process
typedef enum {
UNKNOWN,
DIDNT_FIT,
NULL_NODE,
TOO_DEEP,
OUT_OF_JURISDICTION,
LOD_SKIP,
OUT_OF_VIEW,
WAS_IN_VIEW,
NO_CHANGE,
OCCLUDED
} reason;
reason stopReason;
EncodeBitstreamParams(
int maxEncodeLevel = INT_MAX,
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
@ -97,8 +112,27 @@ public:
forceSendScene(forceSendScene),
stats(stats),
map(map),
jurisdictionMap(jurisdictionMap)
jurisdictionMap(jurisdictionMap),
stopReason(UNKNOWN)
{}
void displayStopReason() {
printf("StopReason: ");
switch (stopReason) {
default:
case UNKNOWN: printf("UNKNOWN\n"); break;
case DIDNT_FIT: printf("DIDNT_FIT\n"); break;
case NULL_NODE: printf("NULL_NODE\n"); break;
case TOO_DEEP: printf("TOO_DEEP\n"); break;
case OUT_OF_JURISDICTION: printf("OUT_OF_JURISDICTION\n"); break;
case LOD_SKIP: printf("LOD_SKIP\n"); break;
case OUT_OF_VIEW: printf("OUT_OF_VIEW\n"); break;
case WAS_IN_VIEW: printf("WAS_IN_VIEW\n"); break;
case NO_CHANGE: printf("NO_CHANGE\n"); break;
case OCCLUDED: printf("OCCLUDED\n"); break;
}
}
};
class ReadBitstreamToTreeParams {