mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:58:27 +02:00
fix issue where we sometimes don't completely fill a packet mid scene
This commit is contained in:
parent
0cd269632e
commit
ed80895eb3
4 changed files with 61 additions and 9 deletions
|
@ -350,6 +350,7 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lastNodeDidntFit = false; // assume each node fits
|
||||||
if (!nodeData->nodeBag.isEmpty()) {
|
if (!nodeData->nodeBag.isEmpty()) {
|
||||||
VoxelNode* subTree = nodeData->nodeBag.extract();
|
VoxelNode* subTree = nodeData->nodeBag.extract();
|
||||||
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
|
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
|
||||||
|
@ -375,11 +376,9 @@ int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nod
|
||||||
_myServer->getServerTree().lockForRead();
|
_myServer->getServerTree().lockForRead();
|
||||||
nodeData->stats.encodeStarted();
|
nodeData->stats.encodeStarted();
|
||||||
bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, &_tempPacket, nodeData->nodeBag, params);
|
bytesWritten = _myServer->getServerTree().encodeTreeBitstream(subTree, &_tempPacket, nodeData->nodeBag, params);
|
||||||
|
|
||||||
if (_tempPacket.hasContent() && bytesWritten == 0 && _tempPacket.getFinalizedSize() < 1450) {
|
if (_tempPacket.hasContent() && bytesWritten == 0 && params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
|
||||||
printf(">>>>>>>>>>>>>>> got bytesWritten==0 _tempPacket.getFinalizedSize()=%d <<<<<<<<<<<<<<<\n",
|
lastNodeDidntFit = true;
|
||||||
_tempPacket.getFinalizedSize());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesWritten > 0) {
|
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
|
// 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
|
// 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.
|
// mean we should send the previous packet contents and reset it.
|
||||||
bool sendNow = (bytesWritten == 0);
|
bool sendNow = lastNodeDidntFit;
|
||||||
if (_tempPacket.hasContent() && sendNow) {
|
if (_tempPacket.hasContent() && sendNow) {
|
||||||
if (_myServer->wantsDebugVoxelSending() && _myServer->wantsVerboseDebug()) {
|
if (_myServer->wantsDebugVoxelSending() && _myServer->wantsVerboseDebug()) {
|
||||||
printf("calling writeToPacket() compressedSize=%d uncompressedSize=%d\n",
|
printf("calling writeToPacket() compressedSize=%d uncompressedSize=%d\n",
|
||||||
|
|
|
@ -11,7 +11,12 @@
|
||||||
// * determine why we sometimes don't fill packets very well (rarely) mid-scene... sometimes it appears as if
|
// * 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
|
// 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
|
// 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
|
// * 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
|
// * improve semantics for "reshuffle" - current approach will work for now and with compression
|
||||||
|
|
|
@ -1031,6 +1031,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
|
||||||
// you can't call this without a valid node
|
// you can't call this without a valid node
|
||||||
if (!node) {
|
if (!node) {
|
||||||
qDebug("WARNING! encodeTreeBitstream() called with node=NULL\n");
|
qDebug("WARNING! encodeTreeBitstream() called with node=NULL\n");
|
||||||
|
params.stopReason = EncodeBitstreamParams::NULL_NODE;
|
||||||
return bytesWritten;
|
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 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)) {
|
if (params.viewFrustum && !node->isInView(*params.viewFrustum)) {
|
||||||
doneEncoding(node);
|
doneEncoding(node);
|
||||||
|
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1063,6 +1065,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
|
||||||
if (!roomForOctalCode) {
|
if (!roomForOctalCode) {
|
||||||
doneEncoding(node);
|
doneEncoding(node);
|
||||||
bag.insert(node); // add the node back to the bag so it will eventually get included
|
bag.insert(node); // add the node back to the bag so it will eventually get included
|
||||||
|
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||||
return bytesWritten;
|
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
|
// couldn't be written... so reset them here... This isn't true for the non-color included case
|
||||||
if (params.includeColor && childBytesWritten == 2) {
|
if (params.includeColor && childBytesWritten == 2) {
|
||||||
childBytesWritten = 0;
|
childBytesWritten = 0;
|
||||||
|
//params.stopReason = EncodeBitstreamParams::UNKNOWN; // possibly should be DIDNT_FIT...
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we wrote child bytes, then return our result of all bytes written
|
// if we wrote child bytes, then return our result of all bytes written
|
||||||
|
@ -1093,6 +1097,7 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node,
|
||||||
} else {
|
} else {
|
||||||
// otherwise... if we didn't write any child bytes, then pretend like we also didn't write our octal code
|
// otherwise... if we didn't write any child bytes, then pretend like we also didn't write our octal code
|
||||||
bytesWritten = 0;
|
bytesWritten = 0;
|
||||||
|
//params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesWritten == 0) {
|
if (bytesWritten == 0) {
|
||||||
|
@ -1115,6 +1120,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
// you can't call this without a valid node
|
// you can't call this without a valid node
|
||||||
if (!node) {
|
if (!node) {
|
||||||
qDebug("WARNING! encodeTreeBitstreamRecursion() called with node=NULL\n");
|
qDebug("WARNING! encodeTreeBitstreamRecursion() called with node=NULL\n");
|
||||||
|
params.stopReason = EncodeBitstreamParams::NULL_NODE;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,6 +1131,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
|
|
||||||
// If we've reached our max Search Level, then stop searching.
|
// If we've reached our max Search Level, then stop searching.
|
||||||
if (currentEncodeLevel >= params.maxEncodeLevel) {
|
if (currentEncodeLevel >= params.maxEncodeLevel) {
|
||||||
|
params.stopReason = EncodeBitstreamParams::TOO_DEEP;
|
||||||
return bytesAtThisLevel;
|
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.
|
// 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.
|
// 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)) {
|
if (JurisdictionMap::BELOW == params.jurisdictionMap->isMyJurisdiction(node->getOctalCode(), CHECK_NODE_ONLY)) {
|
||||||
|
params.stopReason = EncodeBitstreamParams::OUT_OF_JURISDICTION;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1148,6 +1156,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
if (params.stats) {
|
if (params.stats) {
|
||||||
params.stats->skippedDistance(node);
|
params.stats->skippedDistance(node);
|
||||||
}
|
}
|
||||||
|
params.stopReason = EncodeBitstreamParams::LOD_SKIP;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,6 +1167,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
if (params.stats) {
|
if (params.stats) {
|
||||||
params.stats->skippedOutOfView(node);
|
params.stats->skippedOutOfView(node);
|
||||||
}
|
}
|
||||||
|
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1197,6 +1207,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
if (params.stats) {
|
if (params.stats) {
|
||||||
params.stats->skippedWasInView(node);
|
params.stats->skippedWasInView(node);
|
||||||
}
|
}
|
||||||
|
params.stopReason = EncodeBitstreamParams::WAS_IN_VIEW;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1207,6 +1218,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
if (params.stats) {
|
if (params.stats) {
|
||||||
params.stats->skippedNoChange(node);
|
params.stats->skippedNoChange(node);
|
||||||
}
|
}
|
||||||
|
params.stopReason = EncodeBitstreamParams::NO_CHANGE;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,6 +1238,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
if (params.stats) {
|
if (params.stats) {
|
||||||
params.stats->skippedOccluded(node);
|
params.stats->skippedOccluded(node);
|
||||||
}
|
}
|
||||||
|
params.stopReason = EncodeBitstreamParams::OCCLUDED;
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1616,7 +1629,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node,
|
||||||
params.stats->didntFit(node);
|
params.stats->didntFit(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||||
|
bytesAtThisLevel = 0; // didn't fit
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
|
|
|
@ -66,6 +66,21 @@ public:
|
||||||
CoverageMap* map;
|
CoverageMap* map;
|
||||||
JurisdictionMap* jurisdictionMap;
|
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(
|
EncodeBitstreamParams(
|
||||||
int maxEncodeLevel = INT_MAX,
|
int maxEncodeLevel = INT_MAX,
|
||||||
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
|
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
|
||||||
|
@ -97,8 +112,27 @@ public:
|
||||||
forceSendScene(forceSendScene),
|
forceSendScene(forceSendScene),
|
||||||
stats(stats),
|
stats(stats),
|
||||||
map(map),
|
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 {
|
class ReadBitstreamToTreeParams {
|
||||||
|
|
Loading…
Reference in a new issue