mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 04:37:48 +02:00
more voxel scene stats
This commit is contained in:
parent
65f550e68e
commit
3aa6af21b1
5 changed files with 312 additions and 77 deletions
|
@ -8,70 +8,179 @@
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include "VoxelNode.h"
|
||||||
#include "VoxelSceneStats.h"
|
#include "VoxelSceneStats.h"
|
||||||
|
|
||||||
VoxelSceneStats::VoxelSceneStats() :
|
VoxelSceneStats::VoxelSceneStats() {
|
||||||
start(0),
|
reset();
|
||||||
end(0),
|
|
||||||
elapsed(0),
|
|
||||||
total(0),
|
|
||||||
traversed(0),
|
|
||||||
internal(0),
|
|
||||||
internalOutOfView(0),
|
|
||||||
internalOccluded(0),
|
|
||||||
internalDirty(0),
|
|
||||||
leaves(0),
|
|
||||||
leavesOutOfView(0),
|
|
||||||
leavesOccluded(0),
|
|
||||||
leavesDirty(0),
|
|
||||||
packets(0),
|
|
||||||
bytes(0),
|
|
||||||
passes(0),
|
|
||||||
wasFinished(false),
|
|
||||||
wasMoving(false),
|
|
||||||
hadDeltaView(false),
|
|
||||||
hadOcclusionCulling(false)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelSceneStats::~VoxelSceneStats() {
|
VoxelSceneStats::~VoxelSceneStats() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSceneStats::sceneStarted() {
|
void VoxelSceneStats::sceneStarted(bool fullScene, bool moving) {
|
||||||
start = usecTimestampNow();
|
_start = usecTimestampNow();
|
||||||
|
reset(); // resets packet and voxel stats
|
||||||
|
_fullSceneDraw = fullScene;
|
||||||
|
_moving = moving;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSceneStats::sceneCompleted() {
|
void VoxelSceneStats::sceneCompleted() {
|
||||||
end = usecTimestampNow();
|
_end = usecTimestampNow();
|
||||||
elapsed = end - start;
|
_elapsed = _end - _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSceneStats::reset() {
|
void VoxelSceneStats::reset() {
|
||||||
start = 0;
|
_packets = 0;
|
||||||
end= 0;
|
_bytes = 0;
|
||||||
elapsed= 0;
|
_passes = 0;
|
||||||
|
|
||||||
|
_traversed = 0;
|
||||||
|
_internal = 0;
|
||||||
|
_leaves = 0;
|
||||||
|
|
||||||
|
_skippedDistance = 0;
|
||||||
|
_internalSkippedDistance = 0;
|
||||||
|
_leavesSkippedDistance = 0;
|
||||||
|
|
||||||
|
_skippedOutOfView = 0;
|
||||||
|
_internalSkippedOutOfView = 0;
|
||||||
|
_leavesSkippedOutOfView = 0;
|
||||||
|
|
||||||
|
_skippedWasInView = 0;
|
||||||
|
_internalSkippedWasInView = 0;
|
||||||
|
_leavesSkippedWasInView = 0;
|
||||||
|
|
||||||
|
_skippedNoChange = 0;
|
||||||
|
_internalSkippedNoChange = 0;
|
||||||
|
_leavesSkippedNoChange = 0;
|
||||||
|
|
||||||
|
_skippedOccluded = 0;
|
||||||
|
_internalSkippedOccluded = 0;
|
||||||
|
_leavesSkippedOccluded = 0;
|
||||||
|
|
||||||
|
_colorSent = 0;
|
||||||
|
_internalColorSent = 0;
|
||||||
|
_leavesColorSent = 0;
|
||||||
|
|
||||||
|
_didntFit = 0;
|
||||||
|
_internalDidntFit = 0;
|
||||||
|
_leavesDidntFit = 0;
|
||||||
|
|
||||||
total = 0;
|
|
||||||
traversed = 0;
|
|
||||||
internal = 0;
|
|
||||||
internalOutOfView = 0;
|
|
||||||
internalOccluded = 0;
|
|
||||||
internalDirty = 0;
|
|
||||||
leaves = 0;
|
|
||||||
leavesOutOfView = 0;
|
|
||||||
leavesOccluded = 0;
|
|
||||||
leavesDirty = 0;
|
|
||||||
packets = 0;
|
|
||||||
bytes = 0;
|
|
||||||
passes = 0;
|
|
||||||
wasFinished = false;
|
|
||||||
wasMoving = false;
|
|
||||||
hadDeltaView = false;
|
|
||||||
hadOcclusionCulling = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::packetSent(int bytes) {
|
||||||
|
_packets++;
|
||||||
|
_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::traversed(const VoxelNode* node) {
|
||||||
|
_traversed++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leaves++;
|
||||||
|
} else {
|
||||||
|
_internal++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::skippedDistance(const VoxelNode* node) {
|
||||||
|
_skippedDistance++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesSkippedDistance++;
|
||||||
|
} else {
|
||||||
|
_internalSkippedDistance++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::skippedOutOfView(const VoxelNode* node) {
|
||||||
|
_skippedOutOfView++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesSkippedOutOfView++;
|
||||||
|
} else {
|
||||||
|
_internalSkippedOutOfView++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::skippedWasInView(const VoxelNode* node) {
|
||||||
|
_skippedWasInView++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesSkippedWasInView++;
|
||||||
|
} else {
|
||||||
|
_internalSkippedWasInView++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::skippedNoChange(const VoxelNode* node) {
|
||||||
|
_skippedNoChange++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesSkippedNoChange++;
|
||||||
|
} else {
|
||||||
|
_internalSkippedNoChange++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::skippedOccluded(const VoxelNode* node) {
|
||||||
|
_skippedOccluded++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesSkippedOccluded++;
|
||||||
|
} else {
|
||||||
|
_internalSkippedOccluded++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::colorSent(const VoxelNode* node) {
|
||||||
|
_colorSent++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesColorSent++;
|
||||||
|
} else {
|
||||||
|
_internalColorSent++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSceneStats::didntFit(const VoxelNode* node) {
|
||||||
|
_didntFit++;
|
||||||
|
if (node->isLeaf()) {
|
||||||
|
_leavesDidntFit++;
|
||||||
|
} else {
|
||||||
|
_internalDidntFit++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelSceneStats::printDebugDetails() {
|
void VoxelSceneStats::printDebugDetails() {
|
||||||
qDebug("VoxelSceneStats: start: %llu, end: %llu, elapsed: %llu \n", start, end, elapsed);
|
qDebug("\n------------------------------\n");
|
||||||
|
qDebug("VoxelSceneStats:\n");
|
||||||
|
qDebug(" start : %llu \n", _start);
|
||||||
|
qDebug(" end : %llu \n", _end);
|
||||||
|
qDebug(" elapsed: %llu \n", _elapsed);
|
||||||
|
qDebug("\n");
|
||||||
|
qDebug(" full scene: %s\n", debug::valueOf(_fullSceneDraw));
|
||||||
|
qDebug(" moving: %s\n", debug::valueOf(_moving));
|
||||||
|
qDebug("\n");
|
||||||
|
qDebug(" packets: %d\n", _packets);
|
||||||
|
qDebug(" bytes : %d\n", _bytes);
|
||||||
|
qDebug("\n");
|
||||||
|
qDebug(" traversed : %lu\n", _traversed );
|
||||||
|
qDebug(" internal : %lu\n", _internal );
|
||||||
|
qDebug(" leaves : %lu\n", _leaves );
|
||||||
|
qDebug(" skipped distance : %lu\n", _skippedDistance );
|
||||||
|
qDebug(" internal : %lu\n", _internalSkippedDistance );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesSkippedDistance );
|
||||||
|
qDebug(" skipped out of view : %lu\n", _skippedOutOfView );
|
||||||
|
qDebug(" internal : %lu\n", _internalSkippedOutOfView );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesSkippedOutOfView );
|
||||||
|
qDebug(" skipped was in view : %lu\n", _skippedWasInView );
|
||||||
|
qDebug(" internal : %lu\n", _internalSkippedWasInView );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesSkippedWasInView );
|
||||||
|
qDebug(" skipped no change : %lu\n", _skippedNoChange );
|
||||||
|
qDebug(" internal : %lu\n", _internalSkippedNoChange );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesSkippedNoChange );
|
||||||
|
qDebug(" skipped occluded : %lu\n", _skippedOccluded );
|
||||||
|
qDebug(" internal : %lu\n", _internalSkippedOccluded );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesSkippedOccluded );
|
||||||
|
qDebug(" color sent : %lu\n", _colorSent );
|
||||||
|
qDebug(" internal : %lu\n", _internalColorSent );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesColorSent );
|
||||||
|
qDebug(" Didn't Fit : %lu\n", _didntFit );
|
||||||
|
qDebug(" internal : %lu\n", _internalDidntFit );
|
||||||
|
qDebug(" leaves : %lu\n", _leavesDidntFit );
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,43 +11,85 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class VoxelNode;
|
||||||
|
|
||||||
class VoxelSceneStats {
|
class VoxelSceneStats {
|
||||||
public:
|
public:
|
||||||
VoxelSceneStats();
|
VoxelSceneStats();
|
||||||
~VoxelSceneStats();
|
~VoxelSceneStats();
|
||||||
void reset();
|
void reset();
|
||||||
void sceneStarted();
|
void sceneStarted(bool fullScene, bool moving);
|
||||||
void sceneCompleted();
|
void sceneCompleted();
|
||||||
void printDebugDetails();
|
void printDebugDetails();
|
||||||
|
void packetSent(int bytes);
|
||||||
|
|
||||||
|
void traversed(const VoxelNode* node);
|
||||||
|
void skippedDistance(const VoxelNode* node);
|
||||||
|
void skippedOutOfView(const VoxelNode* node);
|
||||||
|
void skippedWasInView(const VoxelNode* node);
|
||||||
|
void skippedNoChange(const VoxelNode* node);
|
||||||
|
void skippedOccluded(const VoxelNode* node);
|
||||||
|
void colorSent(const VoxelNode* node);
|
||||||
|
void didntFit(const VoxelNode* node);
|
||||||
|
void colorBitsWritten(const VoxelNode* node);
|
||||||
|
void existsBitsWritten(const VoxelNode* node);
|
||||||
|
void existsInPacketBitsWritten(const VoxelNode* node);
|
||||||
|
|
||||||
|
private:
|
||||||
// scene timing data in usecs
|
// scene timing data in usecs
|
||||||
uint64_t start;
|
uint64_t _start;
|
||||||
uint64_t end;
|
uint64_t _end;
|
||||||
uint64_t elapsed;
|
uint64_t _elapsed;
|
||||||
|
|
||||||
// scene voxel related data
|
// scene voxel related data
|
||||||
|
unsigned long _traversed;
|
||||||
|
unsigned long _internal;
|
||||||
|
unsigned long _leaves;
|
||||||
|
|
||||||
|
unsigned long _skippedDistance;
|
||||||
|
unsigned long _internalSkippedDistance;
|
||||||
|
unsigned long _leavesSkippedDistance;
|
||||||
|
|
||||||
|
unsigned long _skippedOutOfView;
|
||||||
|
unsigned long _internalSkippedOutOfView;
|
||||||
|
unsigned long _leavesSkippedOutOfView;
|
||||||
|
|
||||||
|
unsigned long _skippedWasInView;
|
||||||
|
unsigned long _internalSkippedWasInView;
|
||||||
|
unsigned long _leavesSkippedWasInView;
|
||||||
|
|
||||||
|
unsigned long _skippedNoChange;
|
||||||
|
unsigned long _internalSkippedNoChange;
|
||||||
|
unsigned long _leavesSkippedNoChange;
|
||||||
|
|
||||||
|
unsigned long _skippedOccluded;
|
||||||
|
unsigned long _internalSkippedOccluded;
|
||||||
|
unsigned long _leavesSkippedOccluded;
|
||||||
|
|
||||||
|
unsigned long _colorSent;
|
||||||
|
unsigned long _internalColorSent;
|
||||||
|
unsigned long _leavesColorSent;
|
||||||
|
|
||||||
|
unsigned long _didntFit;
|
||||||
|
unsigned long _internalDidntFit;
|
||||||
|
unsigned long _leavesDidntFit;
|
||||||
|
|
||||||
unsigned long total;
|
unsigned long total;
|
||||||
unsigned long traversed;
|
|
||||||
unsigned long internal;
|
|
||||||
unsigned long internalOutOfView;
|
unsigned long internalOutOfView;
|
||||||
unsigned long internalOccluded;
|
unsigned long internalOccluded;
|
||||||
unsigned long internalDirty;
|
unsigned long internalDirty;
|
||||||
unsigned long leaves;
|
|
||||||
unsigned long leavesOutOfView;
|
unsigned long leavesOutOfView;
|
||||||
unsigned long leavesOccluded;
|
unsigned long leavesOccluded;
|
||||||
unsigned long leavesDirty;
|
unsigned long leavesDirty;
|
||||||
|
|
||||||
// scene network related data
|
// scene network related data
|
||||||
unsigned int packets;
|
unsigned int _packets;
|
||||||
unsigned int bytes;
|
unsigned int _bytes;
|
||||||
unsigned int passes;
|
unsigned int _passes;
|
||||||
|
|
||||||
// features related items
|
// features related items
|
||||||
bool wasFinished;
|
bool _moving;
|
||||||
bool wasMoving;
|
bool _fullSceneDraw;
|
||||||
bool hadDeltaView;
|
|
||||||
bool hadOcclusionCulling;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__VoxelSceneStats__) */
|
#endif /* defined(__hifi__VoxelSceneStats__) */
|
||||||
|
|
|
@ -1037,6 +1037,13 @@ int VoxelTree::encodeTreeBitstream(VoxelNode* node, unsigned char* outputBuffer,
|
||||||
availableBytes -= codeLength; // keep track or remaining space
|
availableBytes -= codeLength; // keep track or remaining space
|
||||||
|
|
||||||
int currentEncodeLevel = 0;
|
int currentEncodeLevel = 0;
|
||||||
|
|
||||||
|
// record some stats, this is the one node that we won't record below in the recursion function, so we need to
|
||||||
|
// track it here
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->traversed(node);
|
||||||
|
}
|
||||||
|
|
||||||
int childBytesWritten = encodeTreeBitstreamRecursion(node, outputBuffer, availableBytes, bag, params, currentEncodeLevel);
|
int childBytesWritten = encodeTreeBitstreamRecursion(node, outputBuffer, availableBytes, bag, params, currentEncodeLevel);
|
||||||
|
|
||||||
// if childBytesWritten == 1 then something went wrong... that's not possible
|
// if childBytesWritten == 1 then something went wrong... that's not possible
|
||||||
|
@ -1081,6 +1088,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
|
|
||||||
// If we're too far away for our render level, then just return
|
// If we're too far away for our render level, then just return
|
||||||
if (distance >= boundaryDistance) {
|
if (distance >= boundaryDistance) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedDistance(node);
|
||||||
|
}
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,6 +1098,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
|
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
|
||||||
// we're out of view
|
// we're out of view
|
||||||
if (!node->isInView(*params.viewFrustum)) {
|
if (!node->isInView(*params.viewFrustum)) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedOutOfView(node);
|
||||||
|
}
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1110,6 +1123,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
// if we're in deltaViewFrustum mode, and this node has changed since it was last sent, then we do
|
// if we're in deltaViewFrustum mode, and this node has changed since it was last sent, then we do
|
||||||
// need to send it.
|
// need to send it.
|
||||||
if (wasInView && !(params.deltaViewFrustum && node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
|
if (wasInView && !(params.deltaViewFrustum && node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedWasInView(node);
|
||||||
|
}
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,6 +1133,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
// then we can also bail early and save bits
|
// then we can also bail early and save bits
|
||||||
if (!params.forceSendScene && !params.deltaViewFrustum &&
|
if (!params.forceSendScene && !params.deltaViewFrustum &&
|
||||||
!node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
|
!node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedNoChange(node);
|
||||||
|
}
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1136,6 +1155,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, false);
|
CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, false);
|
||||||
delete voxelPolygon; // cleanup
|
delete voxelPolygon; // cleanup
|
||||||
if (result == OCCLUDED) {
|
if (result == OCCLUDED) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedOccluded(node);
|
||||||
|
}
|
||||||
return bytesAtThisLevel;
|
return bytesAtThisLevel;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1201,6 +1223,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
distancesToChildren[i] = 0.0f;
|
distancesToChildren[i] = 0.0f;
|
||||||
currentCount++;
|
currentCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// track stats
|
||||||
|
if (params.stats && childNode) {
|
||||||
|
params.stats->traversed(childNode);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for each child node in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
// for each child node in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
||||||
|
@ -1211,13 +1239,21 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
|
|
||||||
bool childIsInView = (childNode && (!params.viewFrustum || childNode->isInView(*params.viewFrustum)));
|
bool childIsInView = (childNode && (!params.viewFrustum || childNode->isInView(*params.viewFrustum)));
|
||||||
|
|
||||||
if (childIsInView) {
|
if (!childIsInView) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedOutOfView(childNode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Before we determine consider this further, let's see if it's in our LOD scope...
|
// Before we determine consider this further, let's see if it's in our LOD scope...
|
||||||
float distance = distancesToChildren[i]; // params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0;
|
float distance = distancesToChildren[i]; // params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0;
|
||||||
float boundaryDistance = !params.viewFrustum ? 1 :
|
float boundaryDistance = !params.viewFrustum ? 1 :
|
||||||
boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust);
|
boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust);
|
||||||
|
|
||||||
if (distance < boundaryDistance) {
|
if (!(distance < boundaryDistance)) {
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->skippedDistance(childNode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
inViewCount++;
|
inViewCount++;
|
||||||
|
|
||||||
// track children in view as existing and not a leaf, if they're a leaf,
|
// track children in view as existing and not a leaf, if they're a leaf,
|
||||||
|
@ -1261,7 +1297,18 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
} // wants occlusion culling & isLeaf()
|
} // wants occlusion culling & isLeaf()
|
||||||
|
|
||||||
|
|
||||||
bool shouldRender = !params.viewFrustum ? true : childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust);
|
bool shouldRender = !params.viewFrustum ? true :
|
||||||
|
childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust);
|
||||||
|
|
||||||
|
// track some stats
|
||||||
|
if (params.stats) {
|
||||||
|
if (!shouldRender) {
|
||||||
|
params.stats->skippedDistance(childNode);
|
||||||
|
}
|
||||||
|
if (childIsOccluded) {
|
||||||
|
params.stats->skippedOccluded(childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// track children with actual color, only if the child wasn't previously in view!
|
// track children with actual color, only if the child wasn't previously in view!
|
||||||
if (shouldRender && !childIsOccluded) {
|
if (shouldRender && !childIsOccluded) {
|
||||||
|
@ -1288,7 +1335,14 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
inViewWithColorCount++;
|
inViewWithColorCount++;
|
||||||
} else {
|
} else {
|
||||||
// otherwise just track stats of the items we discarded
|
// otherwise just track stats of the items we discarded
|
||||||
params.childWasInViewDiscarded++;
|
if (params.stats) {
|
||||||
|
if (childWasInView) {
|
||||||
|
params.stats->skippedWasInView(childNode);
|
||||||
|
} else {
|
||||||
|
params.stats->skippedNoChange(childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1297,14 +1351,23 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
*writeToThisLevelBuffer = childrenColoredBits;
|
*writeToThisLevelBuffer = childrenColoredBits;
|
||||||
writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer
|
writeToThisLevelBuffer += sizeof(childrenColoredBits); // move the pointer
|
||||||
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
bytesAtThisLevel += sizeof(childrenColoredBits); // keep track of byte count
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->colorBitsWritten(node);
|
||||||
|
}
|
||||||
|
|
||||||
// write the color data...
|
// write the color data...
|
||||||
if (params.includeColor) {
|
if (params.includeColor) {
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
if (oneAtBit(childrenColoredBits, i)) {
|
if (oneAtBit(childrenColoredBits, i)) {
|
||||||
memcpy(writeToThisLevelBuffer, &node->getChildAtIndex(i)->getColor(), BYTES_PER_COLOR);
|
VoxelNode* childNode = node->getChildAtIndex(i);
|
||||||
|
memcpy(writeToThisLevelBuffer, &childNode->getColor(), BYTES_PER_COLOR);
|
||||||
writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color
|
writeToThisLevelBuffer += BYTES_PER_COLOR; // move the pointer for color
|
||||||
bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color
|
bytesAtThisLevel += BYTES_PER_COLOR; // keep track of byte count for color
|
||||||
|
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->colorSent(childNode);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1315,12 +1378,18 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
*writeToThisLevelBuffer = childrenExistInTreeBits;
|
*writeToThisLevelBuffer = childrenExistInTreeBits;
|
||||||
writeToThisLevelBuffer += sizeof(childrenExistInTreeBits); // move the pointer
|
writeToThisLevelBuffer += sizeof(childrenExistInTreeBits); // move the pointer
|
||||||
bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count
|
bytesAtThisLevel += sizeof(childrenExistInTreeBits); // keep track of byte count
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->existsBitsWritten(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the child exist bits
|
// write the child exist bits
|
||||||
*writeToThisLevelBuffer = childrenExistInPacketBits;
|
*writeToThisLevelBuffer = childrenExistInPacketBits;
|
||||||
writeToThisLevelBuffer += sizeof(childrenExistInPacketBits); // move the pointer
|
writeToThisLevelBuffer += sizeof(childrenExistInPacketBits); // move the pointer
|
||||||
bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count
|
bytesAtThisLevel += sizeof(childrenExistInPacketBits); // keep track of byte count
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->existsInPacketBitsWritten(node);
|
||||||
|
}
|
||||||
|
|
||||||
// We only need to keep digging, if there is at least one child that is inView, and not a leaf.
|
// We only need to keep digging, if there is at least one child that is inView, and not a leaf.
|
||||||
keepDiggingDeeper = (inViewNotLeafCount > 0);
|
keepDiggingDeeper = (inViewNotLeafCount > 0);
|
||||||
|
@ -1333,6 +1402,11 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
||||||
availableBytes -= bytesAtThisLevel;
|
availableBytes -= bytesAtThisLevel;
|
||||||
} else {
|
} else {
|
||||||
bag.insert(node);
|
bag.insert(node);
|
||||||
|
|
||||||
|
if (params.stats) {
|
||||||
|
params.stats->didntFit(node);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,14 @@
|
||||||
#ifndef __hifi__VoxelTree__
|
#ifndef __hifi__VoxelTree__
|
||||||
#define __hifi__VoxelTree__
|
#define __hifi__VoxelTree__
|
||||||
|
|
||||||
#include "SimpleMovingAverage.h"
|
#include <PointerStack.h>
|
||||||
|
#include <SimpleMovingAverage.h>
|
||||||
|
|
||||||
|
#include "CoverageMap.h"
|
||||||
#include "ViewFrustum.h"
|
#include "ViewFrustum.h"
|
||||||
#include "VoxelNode.h"
|
#include "VoxelNode.h"
|
||||||
#include "VoxelNodeBag.h"
|
#include "VoxelNodeBag.h"
|
||||||
#include "CoverageMap.h"
|
#include "VoxelSceneStats.h"
|
||||||
#include "PointerStack.h"
|
|
||||||
|
|
||||||
// Callback function, for recuseTreeWithOperation
|
// Callback function, for recuseTreeWithOperation
|
||||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
|
||||||
|
@ -36,6 +38,7 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
|
||||||
#define NO_BOUNDARY_ADJUST 0
|
#define NO_BOUNDARY_ADJUST 0
|
||||||
#define LOW_RES_MOVING_ADJUST 1
|
#define LOW_RES_MOVING_ADJUST 1
|
||||||
#define IGNORE_LAST_SENT 0
|
#define IGNORE_LAST_SENT 0
|
||||||
|
#define IGNORE_SCENE_STATS NULL
|
||||||
|
|
||||||
class EncodeBitstreamParams {
|
class EncodeBitstreamParams {
|
||||||
public:
|
public:
|
||||||
|
@ -48,10 +51,10 @@ public:
|
||||||
bool deltaViewFrustum;
|
bool deltaViewFrustum;
|
||||||
const ViewFrustum* lastViewFrustum;
|
const ViewFrustum* lastViewFrustum;
|
||||||
bool wantOcclusionCulling;
|
bool wantOcclusionCulling;
|
||||||
long childWasInViewDiscarded;
|
|
||||||
int boundaryLevelAdjust;
|
int boundaryLevelAdjust;
|
||||||
uint64_t lastViewFrustumSent;
|
uint64_t lastViewFrustumSent;
|
||||||
bool forceSendScene;
|
bool forceSendScene;
|
||||||
|
VoxelSceneStats* stats;
|
||||||
CoverageMap* map;
|
CoverageMap* map;
|
||||||
|
|
||||||
EncodeBitstreamParams(
|
EncodeBitstreamParams(
|
||||||
|
@ -66,7 +69,8 @@ public:
|
||||||
CoverageMap* map = IGNORE_COVERAGE_MAP,
|
CoverageMap* map = IGNORE_COVERAGE_MAP,
|
||||||
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
|
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
|
||||||
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT,
|
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT,
|
||||||
bool forceSendScene = true) :
|
bool forceSendScene = true,
|
||||||
|
VoxelSceneStats* stats = IGNORE_SCENE_STATS) :
|
||||||
maxEncodeLevel (maxEncodeLevel),
|
maxEncodeLevel (maxEncodeLevel),
|
||||||
maxLevelReached (0),
|
maxLevelReached (0),
|
||||||
viewFrustum (viewFrustum),
|
viewFrustum (viewFrustum),
|
||||||
|
@ -76,10 +80,10 @@ public:
|
||||||
deltaViewFrustum (deltaViewFrustum),
|
deltaViewFrustum (deltaViewFrustum),
|
||||||
lastViewFrustum (lastViewFrustum),
|
lastViewFrustum (lastViewFrustum),
|
||||||
wantOcclusionCulling (wantOcclusionCulling),
|
wantOcclusionCulling (wantOcclusionCulling),
|
||||||
childWasInViewDiscarded (0),
|
|
||||||
boundaryLevelAdjust (boundaryLevelAdjust),
|
boundaryLevelAdjust (boundaryLevelAdjust),
|
||||||
lastViewFrustumSent (lastViewFrustumSent),
|
lastViewFrustumSent (lastViewFrustumSent),
|
||||||
forceSendScene (forceSendScene),
|
forceSendScene (forceSendScene),
|
||||||
|
stats (stats),
|
||||||
map (map)
|
map (map)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -200,9 +200,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
// only set our last sent time if we weren't resetting due to frustum change
|
// only set our last sent time if we weren't resetting due to frustum change
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
nodeData->setLastTimeBagEmpty(now);
|
nodeData->setLastTimeBagEmpty(now);
|
||||||
if (::debugVoxelSending) {
|
|
||||||
printf("ENTIRE SCENE SENT! nodeData->setLastTimeBagEmpty(now=[%lld])\n", now);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeData->stats.sceneCompleted();
|
nodeData->stats.sceneCompleted();
|
||||||
|
@ -210,7 +207,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
|
|
||||||
// This is the start of "resending" the scene.
|
// This is the start of "resending" the scene.
|
||||||
nodeData->nodeBag.insert(serverTree.rootNode);
|
nodeData->nodeBag.insert(serverTree.rootNode);
|
||||||
nodeData->stats.sceneStarted();
|
|
||||||
|
// start tracking our stats
|
||||||
|
bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging();
|
||||||
|
nodeData->stats.sceneStarted(fullScene, viewFrustumChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||||
|
@ -243,12 +243,15 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP;
|
CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP;
|
||||||
int boundaryLevelAdjust = viewFrustumChanged && nodeData->getWantLowResMoving()
|
int boundaryLevelAdjust = viewFrustumChanged && nodeData->getWantLowResMoving()
|
||||||
? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST;
|
? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST;
|
||||||
|
|
||||||
|
bool fullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) &&
|
||||||
|
nodeData->getViewFrustumJustStoppedChanging();
|
||||||
|
|
||||||
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
|
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
|
||||||
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
|
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
|
||||||
wantOcclusionCulling, coverageMap, boundaryLevelAdjust,
|
wantOcclusionCulling, coverageMap, boundaryLevelAdjust,
|
||||||
nodeData->getLastTimeBagEmpty(),
|
nodeData->getLastTimeBagEmpty(),
|
||||||
nodeData->getViewFrustumJustStoppedChanging());
|
fullScene, &nodeData->stats);
|
||||||
|
|
||||||
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||||
nodeData->nodeBag, params);
|
nodeData->nodeBag, params);
|
||||||
|
@ -258,6 +261,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
} else {
|
} else {
|
||||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||||
nodeData->getPacket(), nodeData->getPacketLength());
|
nodeData->getPacket(), nodeData->getPacketLength());
|
||||||
|
|
||||||
|
nodeData->stats.packetSent(nodeData->getPacketLength());
|
||||||
trueBytesSent += nodeData->getPacketLength();
|
trueBytesSent += nodeData->getPacketLength();
|
||||||
truePacketsSent++;
|
truePacketsSent++;
|
||||||
packetsSentThisInterval++;
|
packetsSentThisInterval++;
|
||||||
|
@ -268,6 +273,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
if (nodeData->isPacketWaiting()) {
|
if (nodeData->isPacketWaiting()) {
|
||||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||||
nodeData->getPacket(), nodeData->getPacketLength());
|
nodeData->getPacket(), nodeData->getPacketLength());
|
||||||
|
nodeData->stats.packetSent(nodeData->getPacketLength());
|
||||||
trueBytesSent += nodeData->getPacketLength();
|
trueBytesSent += nodeData->getPacketLength();
|
||||||
truePacketsSent++;
|
truePacketsSent++;
|
||||||
nodeData->resetVoxelPacket();
|
nodeData->resetVoxelPacket();
|
||||||
|
|
Loading…
Reference in a new issue