mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
First cut are removing out of view voxels and switch to using PerformanceWarnings
This commit is contained in:
parent
e0d040a73b
commit
7ba9d4aa86
2 changed files with 83 additions and 63 deletions
|
@ -15,6 +15,7 @@
|
|||
#include <fstream> // to load voxels from file
|
||||
#include <SharedUtil.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
#include <OctalCode.h>
|
||||
#include <pthread.h>
|
||||
#include "Log.h"
|
||||
|
@ -44,6 +45,7 @@ VoxelSystem::VoxelSystem() {
|
|||
_voxelsInArrays = _voxelsUpdated = 0;
|
||||
_tree = new VoxelTree();
|
||||
pthread_mutex_init(&_bufferWriteLock, NULL);
|
||||
pthread_mutex_init(&_voxelCleanupLock, NULL);
|
||||
}
|
||||
|
||||
VoxelSystem::~VoxelSystem() {
|
||||
|
@ -54,6 +56,7 @@ VoxelSystem::~VoxelSystem() {
|
|||
delete[] _voxelDirtyArray;
|
||||
delete _tree;
|
||||
pthread_mutex_destroy(&_bufferWriteLock);
|
||||
pthread_mutex_destroy(&_voxelCleanupLock);
|
||||
}
|
||||
|
||||
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
||||
|
@ -98,24 +101,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
switch(command) {
|
||||
case PACKET_HEADER_VOXEL_DATA:
|
||||
{
|
||||
double start = usecTimestampNow();
|
||||
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
||||
// ask the VoxelTree to read the bitstream into the tree
|
||||
_tree->readBitstreamToTree(voxelData, numBytes - 1);
|
||||
if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) {
|
||||
printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n",
|
||||
_tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") );
|
||||
}
|
||||
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec);
|
||||
} else {
|
||||
printLog("WARNING! readBitstreamToTree() took %lf milliseconds\n",elapsedmsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PACKET_HEADER_ERASE_VOXEL:
|
||||
|
@ -153,14 +145,19 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
}
|
||||
|
||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||
PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated
|
||||
double start = usecTimestampNow();
|
||||
|
||||
double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished);
|
||||
|
||||
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
|
||||
return; // bail early, it hasn't been long enough since the last time we ran
|
||||
}
|
||||
|
||||
// If the view frustum has changed, since last time, then remove nodes that are out of view
|
||||
//if (hasViewChanged()) {
|
||||
// removeOutOfView();
|
||||
//}
|
||||
|
||||
if (_tree->isDirty()) {
|
||||
_callsToTreesToArrays++;
|
||||
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
||||
|
@ -179,21 +176,12 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
|||
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! newTreeToArrays() took %lf seconds %ld voxels updated\n", elapsedsec, _voxelsUpdated);
|
||||
} else {
|
||||
printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
_setupNewVoxelsForDrawingLastFinished = end;
|
||||
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
||||
}
|
||||
|
||||
void VoxelSystem::copyWrittenDataToReadArrays() {
|
||||
double start = usecTimestampNow();
|
||||
PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated
|
||||
if (_voxelsDirty && _voxelsUpdated) {
|
||||
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
||||
pthread_mutex_lock(&_bufferWriteLock);
|
||||
|
@ -203,18 +191,6 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
|
|||
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
|
||||
pthread_mutex_unlock(&_bufferWriteLock);
|
||||
}
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds for %ld voxels %ld updated\n",
|
||||
elapsedsec, _voxelsInArrays, _voxelsUpdated);
|
||||
} else {
|
||||
printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds for %ld voxels %ld updated\n",
|
||||
elapsedmsec, _voxelsInArrays, _voxelsUpdated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
||||
|
@ -301,6 +277,7 @@ void VoxelSystem::init() {
|
|||
// When we change voxels representations in the arrays, we'll update this
|
||||
_voxelsDirty = false;
|
||||
_voxelsInArrays = 0;
|
||||
_unusedArraySpace = 0;
|
||||
|
||||
// we will track individual dirty sections with this array of bools
|
||||
_voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
|
||||
|
@ -369,7 +346,7 @@ void VoxelSystem::init() {
|
|||
}
|
||||
|
||||
void VoxelSystem::updateVBOs() {
|
||||
double start = usecTimestampNow();
|
||||
PerformanceWarning warn(_renderWarningsOn, "updateVBOs()"); // would like to include _callsToTreesToArrays
|
||||
if (_voxelsDirty) {
|
||||
glBufferIndex segmentStart = 0;
|
||||
glBufferIndex segmentEnd = 0;
|
||||
|
@ -401,28 +378,13 @@ void VoxelSystem::updateVBOs() {
|
|||
}
|
||||
_voxelsDirty = false;
|
||||
}
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! updateVBOs() took %lf seconds after %d calls to newTreeToArrays()\n",
|
||||
elapsedsec, _callsToTreesToArrays);
|
||||
} else {
|
||||
printLog("WARNING! updateVBOs() took %lf milliseconds after %d calls to newTreeToArrays()\n",
|
||||
elapsedmsec, _callsToTreesToArrays);
|
||||
}
|
||||
} else {
|
||||
printLog("WARNING! updateVBOs() called after %d calls to newTreeToArrays()\n",_callsToTreesToArrays);
|
||||
}
|
||||
}
|
||||
_callsToTreesToArrays = 0; // clear it
|
||||
}
|
||||
|
||||
void VoxelSystem::render() {
|
||||
double start = usecTimestampNow();
|
||||
PerformanceWarning warn(_renderWarningsOn, "render()");
|
||||
glPushMatrix();
|
||||
//cleanupRemovedVoxels();
|
||||
updateVBOs();
|
||||
// tell OpenGL where to find vertex and color information
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -454,16 +416,6 @@ void VoxelSystem::render() {
|
|||
|
||||
// scale back down to 1 so heads aren't massive
|
||||
glPopMatrix();
|
||||
double end = usecTimestampNow();
|
||||
double elapsedmsec = (end - start)/1000.0;
|
||||
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||
if (elapsedmsec > 1000) {
|
||||
double elapsedsec = (end - start)/1000000.0;
|
||||
printLog("WARNING! render() took %lf seconds\n",elapsedsec);
|
||||
} else {
|
||||
printLog("WARNING! render() took %lf milliseconds\n",elapsedmsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VoxelSystem::_nodeCount = 0;
|
||||
|
@ -591,4 +543,63 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
|
|||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
// "Remove" voxels from the tree that are not in view. We don't actually delete them,
|
||||
// we remove them from the tree and place them into a holding area for later deletion
|
||||
int removedCount;
|
||||
bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
|
||||
VoxelSystem* thisVoxelSystem = (VoxelSystem*) extraData;
|
||||
_nodeCount++;
|
||||
// Need to operate on our child nodes, so we can remove them
|
||||
for (int i = 0; i < 8; i++) {
|
||||
VoxelNode* childNode = node->getChildAtIndex(i);
|
||||
if (childNode && !childNode->isInView(*thisVoxelSystem->_viewFrustum)) {
|
||||
node->removeChildAtIndex(i);
|
||||
removedCount++;
|
||||
|
||||
// Note: VoxelNodeBag is more expensive than we need, because it checks octal code matches,
|
||||
// we really just want a simple bag that checks pointers only, consider switching
|
||||
thisVoxelSystem->_removedVoxels.insert(childNode);
|
||||
}
|
||||
}
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
bool VoxelSystem::hasViewChanged() {
|
||||
bool result = false; // assume the best
|
||||
if (_viewFrustum && !_lastKnowViewFrustum.matches(_viewFrustum)) {
|
||||
result = true;
|
||||
_lastKnowViewFrustum = *_viewFrustum; // save last known
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void VoxelSystem::removeOutOfView() {
|
||||
PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); // would like to include removedCount, _nodeCount, _removedVoxels.count()
|
||||
pthread_mutex_lock(&_voxelCleanupLock);
|
||||
_nodeCount = 0;
|
||||
removedCount = 0;
|
||||
_tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)this);
|
||||
pthread_mutex_unlock(&_voxelCleanupLock);
|
||||
}
|
||||
|
||||
// Deletes the VoxelNodes from the _removedVoxels bag, but also cleans up those items from the vertex arrays
|
||||
void VoxelSystem::cleanupRemovedVoxels() {
|
||||
if (!pthread_mutex_trylock(&_voxelCleanupLock)) {
|
||||
while (!_removedVoxels.isEmpty()){
|
||||
VoxelNode* node = _removedVoxels.extract();
|
||||
// If the voxel is in the vertex, and it was previously rendered, then set it's vertices to "hidden"
|
||||
if (node->isKnownBufferIndex() && node->getShouldRender()) {
|
||||
unsigned long nodeIndex = node->getBufferIndex();
|
||||
_voxelDirtyArray[nodeIndex] = true;
|
||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
||||
GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
|
||||
*(writeVerticesAt+j) = FLT_MAX;
|
||||
}
|
||||
_voxelsDirty = true; // yep
|
||||
}
|
||||
_unusedArraySpace++; // track this so we can blow away our arrays if they get too much
|
||||
delete node; // actually delete the node
|
||||
}
|
||||
pthread_mutex_unlock(&_voxelCleanupLock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,9 +61,14 @@ public:
|
|||
void killLocalVoxels();
|
||||
void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; };
|
||||
bool getRenderPipelineWarnings() const { return _renderWarningsOn; };
|
||||
|
||||
void removeOutOfView();
|
||||
bool hasViewChanged();
|
||||
void cleanupRemovedVoxels();
|
||||
|
||||
private:
|
||||
int _callsToTreesToArrays;
|
||||
VoxelNodeBag _removedVoxels;
|
||||
|
||||
bool _renderWarningsOn;
|
||||
// Operation functions for tree recursion methods
|
||||
|
@ -74,6 +79,7 @@ private:
|
|||
static bool falseColorizeInViewOperation(VoxelNode* node, void* extraData);
|
||||
static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData);
|
||||
static bool getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData);
|
||||
static bool removeOutOfViewOperation(VoxelNode* node, void* extraData);
|
||||
|
||||
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
|
||||
static float _maxDistance;
|
||||
|
@ -89,6 +95,7 @@ private:
|
|||
bool* _voxelDirtyArray;
|
||||
unsigned long _voxelsUpdated;
|
||||
unsigned long _voxelsInArrays;
|
||||
unsigned long _unusedArraySpace;
|
||||
|
||||
|
||||
double _setupNewVoxelsForDrawingLastElapsed;
|
||||
|
@ -99,8 +106,10 @@ private:
|
|||
GLuint _vboColorsID;
|
||||
GLuint _vboIndicesID;
|
||||
pthread_mutex_t _bufferWriteLock;
|
||||
pthread_mutex_t _voxelCleanupLock;
|
||||
|
||||
ViewFrustum* _viewFrustum;
|
||||
ViewFrustum _lastKnowViewFrustum;
|
||||
|
||||
int newTreeToArrays(VoxelNode *currentNode);
|
||||
void setupNewVoxelsForDrawing();
|
||||
|
|
Loading…
Reference in a new issue