mirror of
https://github.com/overte-org/overte.git
synced 2025-06-05 14:21:04 +02:00
first cut at local voxel cache
This commit is contained in:
parent
03794f7218
commit
c181d0a849
9 changed files with 416 additions and 344 deletions
|
@ -86,6 +86,8 @@ const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
|
|||
const float MIRROR_REARVIEW_DISTANCE = 0.65f;
|
||||
const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
|
||||
|
||||
const char* LOCAL_VOXEL_CACHE = "/Users/brad/local_voxel_cache.svo";
|
||||
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) {
|
||||
fprintf(stdout, "%s", message.toLocal8Bit().constData());
|
||||
|
@ -143,7 +145,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_resetRecentMaxPacketsSoon(true),
|
||||
_swatch(NULL),
|
||||
_pasteMode(false),
|
||||
_logger(new FileLogger())
|
||||
_logger(new FileLogger()),
|
||||
_persistThread(NULL)
|
||||
{
|
||||
_applicationStartupTime = startup_time;
|
||||
|
||||
|
@ -250,6 +253,14 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
|
||||
// Set the sixense filtering
|
||||
_sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
||||
|
||||
_persistThread = new OctreePersistThread(_voxels.getTree(), LOCAL_VOXEL_CACHE);
|
||||
|
||||
if (_persistThread) {
|
||||
_voxels.beginLoadingLocalVoxelCache(); // while local voxels are importing, don't do individual node VBO updates
|
||||
connect(_persistThread, SIGNAL(loadCompleted()), &_voxels, SLOT(localVoxelCacheLoaded()));
|
||||
_persistThread->initialize(true);
|
||||
}
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
@ -1436,6 +1447,8 @@ void Application::terminate() {
|
|||
_voxelHideShowThread.terminate();
|
||||
_voxelEditSender.terminate();
|
||||
_particleEditSender.terminate();
|
||||
_persistThread->terminate();
|
||||
_persistThread = NULL;
|
||||
}
|
||||
|
||||
static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) {
|
||||
|
@ -2400,6 +2413,7 @@ void Application::updateThreads(float deltaTime) {
|
|||
_voxelHideShowThread.threadRoutine();
|
||||
_voxelEditSender.threadRoutine();
|
||||
_particleEditSender.threadRoutine();
|
||||
_persistThread->threadRoutine();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4536,3 +4550,8 @@ void Application::toggleLogDialog() {
|
|||
_logDialog->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Application::initAvatarAndViewFrustum() {
|
||||
updateAvatar(0.f);
|
||||
}
|
|
@ -229,6 +229,7 @@ public slots:
|
|||
void increaseVoxelSize();
|
||||
void loadScript();
|
||||
void toggleLogDialog();
|
||||
void initAvatarAndViewFrustum();
|
||||
|
||||
private slots:
|
||||
|
||||
|
@ -512,6 +513,8 @@ private:
|
|||
QPointer<LogDialog> _logDialog;
|
||||
|
||||
FileLogger* _logger;
|
||||
|
||||
OctreePersistThread* _persistThread;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Application__) */
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
const bool VoxelSystem::DONT_BAIL_EARLY = false;
|
||||
|
||||
|
||||
float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
|
||||
|
||||
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7
|
||||
|
@ -111,12 +110,14 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
|||
_culledOnce = false;
|
||||
_inhideOutOfView = false;
|
||||
_treeIsBusy = false;
|
||||
|
||||
}
|
||||
|
||||
void VoxelSystem::elementDeleted(OctreeElement* element) {
|
||||
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
|
||||
if (voxel->getVoxelSystem() == this) {
|
||||
if (_voxelsInWriteArrays != 0) {
|
||||
qDebug() << "elementDeleted()... about to call forceRemoveNodeFromArrays()\n";
|
||||
forceRemoveNodeFromArrays(voxel);
|
||||
} else {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
|
||||
|
@ -642,8 +643,6 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
}
|
||||
|
||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||
|
||||
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"setupNewVoxelsForDrawing()");
|
||||
|
||||
|
@ -703,6 +702,11 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
|||
_setupNewVoxelsForDrawingLastFinished = end;
|
||||
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
||||
_inSetupNewVoxelsForDrawing = false;
|
||||
|
||||
bool extraDebugging = Application::getInstance()->getLogger()->extraDebugging();
|
||||
if (extraDebugging) {
|
||||
qDebug("setupNewVoxelsForDrawing()... _voxelsUpdated=%lu...\n",_voxelsUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) {
|
||||
|
@ -746,14 +750,12 @@ void VoxelSystem::checkForCulling() {
|
|||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()");
|
||||
uint64_t start = usecTimestampNow();
|
||||
|
||||
|
||||
// track how long its been since we were last moving. If we have recently moved then only use delta frustums, if
|
||||
// it's been a long time since we last moved, then go ahead and do a full frustum cull.
|
||||
if (isViewChanging()) {
|
||||
_lastViewIsChanging = start;
|
||||
}
|
||||
uint64_t sinceLastMoving = (start - _lastViewIsChanging) / 1000;
|
||||
|
||||
bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS));
|
||||
|
||||
// These has changed events will occur before we stop. So we need to remember this for when we finally have stopped
|
||||
|
@ -930,6 +932,11 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) {
|
|||
voxel->calculateAverageFromChildren();
|
||||
}
|
||||
}
|
||||
|
||||
// for either voxels that should not render, or those that should render and are in view
|
||||
// update their geometry in the array.if the voxel "should render" but is not in view, then
|
||||
// it actually doesn't need to be rendered
|
||||
if (!shouldRender || voxel->isInView(*_viewFrustum)) {
|
||||
if (_writeRenderFullVBO) {
|
||||
const bool DONT_REUSE_INDEX = false;
|
||||
const bool FORCE_REDRAW = true;
|
||||
|
@ -939,6 +946,7 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) {
|
|||
const bool DONT_FORCE_REDRAW = false;
|
||||
voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
|
||||
}
|
||||
}
|
||||
voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
|
||||
|
||||
return voxelsUpdated;
|
||||
|
@ -959,7 +967,7 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) {
|
|||
// If this node has not yet been written to the array, then add it to the end of the array.
|
||||
glBufferIndex nodeIndex = node->getBufferIndex();
|
||||
node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
|
||||
freeBufferIndex(nodeIndex); // NOTE: This is make the node invisible!
|
||||
freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible!
|
||||
return 1; // updated!
|
||||
}
|
||||
return 0; // not-updated
|
||||
|
@ -1016,7 +1024,7 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo
|
|||
void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||
float voxelScale, const nodeColor& color) {
|
||||
|
||||
if (_initialized) {
|
||||
if (_initialized && nodeIndex <= _maxVoxels) {
|
||||
_writeVoxelDirtyArray[nodeIndex] = true;
|
||||
|
||||
if (_useVoxelShader) {
|
||||
|
@ -1074,12 +1082,14 @@ void VoxelSystem::init() {
|
|||
|
||||
// our own _removedVoxels doesn't need to be notified of voxel deletes
|
||||
VoxelTreeElement::removeDeleteHook(&_removedVoxels);
|
||||
|
||||
}
|
||||
|
||||
void VoxelSystem::changeTree(VoxelTree* newTree) {
|
||||
disconnect(_tree, 0, this, 0);
|
||||
|
||||
_tree = newTree;
|
||||
|
||||
_tree->setDirtyBit();
|
||||
_tree->getRoot()->setVoxelSystem(this);
|
||||
|
||||
|
@ -1880,6 +1890,7 @@ public:
|
|||
unsigned long nodesOutsideInside;
|
||||
unsigned long nodesInsideOutside;
|
||||
unsigned long nodesOutsideOutside;
|
||||
unsigned long nodesShown;
|
||||
|
||||
hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree,
|
||||
bool culledOnce, bool widenViewFrustum, bool wantDeltaFrustums) :
|
||||
|
@ -1898,7 +1909,8 @@ public:
|
|||
nodesIntersectInside(0),
|
||||
nodesOutsideInside(0),
|
||||
nodesInsideOutside(0),
|
||||
nodesOutsideOutside(0)
|
||||
nodesOutsideOutside(0),
|
||||
nodesShown(0)
|
||||
{
|
||||
// Widen the FOV for trimming
|
||||
if (widenViewFrustum) {
|
||||
|
@ -1923,6 +1935,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
|||
PerformanceWarning warn(showDebugDetails, "hideOutOfView()");
|
||||
bool widenFrustum = true;
|
||||
|
||||
|
||||
// When using "delta" view frustums and only hide/show items that are in the difference
|
||||
// between the two view frustums. There are some potential problems with this mode.
|
||||
//
|
||||
|
@ -1964,15 +1977,18 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
|||
setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
|
||||
}
|
||||
|
||||
bool extraDebugDetails = Application::getInstance()->getLogger()->extraDebugging();
|
||||
bool extraDebugDetails = false; // Application::getInstance()->getLogger()->extraDebugging();
|
||||
if (extraDebugDetails) {
|
||||
qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n",
|
||||
args.nodesScanned, args.nodesRemoved, args.nodesInside,
|
||||
qDebug("hideOutOfView() scanned=%ld removed=%ld show=%ld inside=%ld intersect=%ld outside=%ld\n",
|
||||
args.nodesScanned, args.nodesRemoved, args.nodesShown, args.nodesInside,
|
||||
args.nodesIntersect, args.nodesOutside
|
||||
);
|
||||
qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n",
|
||||
args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside
|
||||
);
|
||||
|
||||
qDebug() << "args.thisViewFrustum....\n";
|
||||
args.thisViewFrustum.printDebugDetails();
|
||||
}
|
||||
_inhideOutOfView = false;
|
||||
}
|
||||
|
@ -2047,6 +2063,7 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat
|
|||
// These are both needed to force redraw...
|
||||
voxel->setDirtyBit();
|
||||
voxel->markWithChangedTime();
|
||||
args->nodesShown++;
|
||||
}
|
||||
|
||||
return true; // keep recursing!
|
||||
|
@ -2129,6 +2146,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData
|
|||
// here because we know will block any children anyway
|
||||
if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) {
|
||||
voxel->setDirtyBit(); // will this make it draw?
|
||||
args->nodesShown++;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2763,4 +2781,22 @@ void VoxelSystem::unlockTree() {
|
|||
}
|
||||
|
||||
|
||||
void VoxelSystem::localVoxelCacheLoaded() {
|
||||
qDebug() << "localVoxelCacheLoaded()\n";
|
||||
|
||||
// Make sure that the application has properly set up the view frustum for our loaded state
|
||||
Application::getInstance()->initAvatarAndViewFrustum();
|
||||
|
||||
_tree->setDirtyBit();
|
||||
setupNewVoxelsForDrawing();
|
||||
_inhideOutOfView = false; // reenable hideOutOfView behavior
|
||||
}
|
||||
|
||||
void VoxelSystem::beginLoadingLocalVoxelCache() {
|
||||
qDebug() << "beginLoadingLocalVoxelCache()\n";
|
||||
_writeRenderFullVBO = true; // this will disable individual node updates
|
||||
_inhideOutOfView = true; // this will disable hidOutOfView which we want to do until local cache is loaded
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <NodeData.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <OctreePersistThread.h>
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Util.h"
|
||||
|
@ -146,6 +147,9 @@ public slots:
|
|||
void setUseVoxelShader(bool useVoxelShader);
|
||||
void setVoxelsAsPoints(bool voxelsAsPoints);
|
||||
|
||||
void localVoxelCacheLoaded();
|
||||
void beginLoadingLocalVoxelCache();
|
||||
|
||||
protected:
|
||||
float _treeScale;
|
||||
int _maxVoxels;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <SharedUtil.h>
|
||||
|
||||
#include "OctreePersistThread.h"
|
||||
#include "OctreeServer.h"
|
||||
|
||||
OctreePersistThread::OctreePersistThread(Octree* tree, const char* filename, int persistInterval) :
|
||||
_tree(tree),
|
||||
|
@ -60,6 +59,10 @@ bool OctreePersistThread::process() {
|
|||
|
||||
_initialLoadComplete = true;
|
||||
_lastCheck = usecTimestampNow(); // we just loaded, no need to save again
|
||||
|
||||
qDebug() << "about to emit loadCompleted();\n";
|
||||
emit loadCompleted();
|
||||
qDebug() << "after emit loadCompleted();\n";
|
||||
}
|
||||
|
||||
if (isStillRunning()) {
|
|
@ -12,10 +12,11 @@
|
|||
#define __Octree_server__OctreePersistThread__
|
||||
|
||||
#include <GenericThread.h>
|
||||
#include <Octree.h>
|
||||
#include "Octree.h"
|
||||
|
||||
/// Generalized threaded processor for handling received inbound packets.
|
||||
class OctreePersistThread : public virtual GenericThread {
|
||||
class OctreePersistThread : public GenericThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static const int DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
||||
|
||||
|
@ -26,6 +27,9 @@ public:
|
|||
time_t* getLoadCompleted() { return &_loadCompleted; }
|
||||
uint64_t getLoadElapsedTime() const { return _loadTimeUSecs; }
|
||||
|
||||
signals:
|
||||
void loadCompleted();
|
||||
|
||||
protected:
|
||||
/// Implements generic processing behavior for this thread.
|
||||
virtual bool process();
|
|
@ -11,11 +11,14 @@
|
|||
#ifndef __shared__GenericThread__
|
||||
#define __shared__GenericThread__
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/// A basic generic "thread" class. Handles a single thread of control within the application. Can operate in non-threaded
|
||||
/// mode but caller must regularly call threadRoutine() method.
|
||||
class GenericThread {
|
||||
class GenericThread : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
GenericThread();
|
||||
virtual ~GenericThread();
|
||||
|
|
Loading…
Reference in a new issue