This commit is contained in:
Andrzej Kapolka 2013-10-30 16:45:09 -07:00
commit 4ef3500096
19 changed files with 437 additions and 87 deletions

View file

@ -620,7 +620,13 @@ void Application::keyPressEvent(QKeyEvent* event) {
_audioScope.inputPaused = !_audioScope.inputPaused; _audioScope.inputPaused = !_audioScope.inputPaused;
break; break;
case Qt::Key_L: case Qt::Key_L:
if (!isShifted && !isMeta) {
_displayLevels = !_displayLevels; _displayLevels = !_displayLevels;
} else if (isShifted) {
Menu::getInstance()->triggerOption(MenuOption::LodTools);
} else if (isMeta) {
Menu::getInstance()->triggerOption(MenuOption::Log);
}
break; break;
case Qt::Key_E: case Qt::Key_E:
@ -2372,6 +2378,8 @@ void Application::queryVoxels() {
_voxelQuery.setCameraNearClip(_viewFrustum.getNearClip()); _voxelQuery.setCameraNearClip(_viewFrustum.getNearClip());
_voxelQuery.setCameraFarClip(_viewFrustum.getFarClip()); _voxelQuery.setCameraFarClip(_viewFrustum.getFarClip());
_voxelQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); _voxelQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
_voxelQuery.setVoxelSizeScale(Menu::getInstance()->getVoxelSizeScale());
_voxelQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust());
unsigned char voxelQueryPacket[MAX_PACKET_SIZE]; unsigned char voxelQueryPacket[MAX_PACKET_SIZE];

View file

@ -60,6 +60,7 @@
#include "ui/ChatEntry.h" #include "ui/ChatEntry.h"
#include "ui/VoxelStatsDialog.h" #include "ui/VoxelStatsDialog.h"
#include "ui/RearMirrorTools.h" #include "ui/RearMirrorTools.h"
#include "ui/LodToolsDialog.h"
class QAction; class QAction;
class QActionGroup; class QActionGroup;

View file

@ -53,7 +53,10 @@ Menu::Menu() :
_viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET), _viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET),
_voxelModeActionsGroup(NULL), _voxelModeActionsGroup(NULL),
_voxelStatsDialog(NULL), _voxelStatsDialog(NULL),
_maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM) _lodToolsDialog(NULL),
_maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM),
_voxelSizeScale(DEFAULT_VOXEL_SIZE_SCALE),
_boundaryLevelAdjust(0)
{ {
Application *appInstance = Application::getInstance(); Application *appInstance = Application::getInstance();
@ -277,6 +280,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
QMenu* cullingOptionsMenu = voxelOptionsMenu->addMenu("Culling Options"); QMenu* cullingOptionsMenu = voxelOptionsMenu->addMenu("Culling Options");
addDisabledActionAndSeparator(cullingOptionsMenu, "Standard Settings"); addDisabledActionAndSeparator(cullingOptionsMenu, "Standard Settings");
@ -517,6 +521,8 @@ void Menu::loadSettings(QSettings* settings) {
_audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0);
_fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES);
_maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM);
_voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_VOXEL_SIZE_SCALE);
_boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0);
settings->beginGroup("View Frustum Offset Camera"); settings->beginGroup("View Frustum Offset Camera");
// in case settings is corrupt or missing loadSetting() will check for NaN // in case settings is corrupt or missing loadSetting() will check for NaN
@ -543,6 +549,8 @@ void Menu::saveSettings(QSettings* settings) {
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
settings->setValue("fieldOfView", _fieldOfView); settings->setValue("fieldOfView", _fieldOfView);
settings->setValue("maxVoxels", _maxVoxels); settings->setValue("maxVoxels", _maxVoxels);
settings->setValue("voxelSizeScale", _voxelSizeScale);
settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust);
settings->beginGroup("View Frustum Offset Camera"); settings->beginGroup("View Frustum Offset Camera");
settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw);
settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch);
@ -1022,7 +1030,6 @@ void Menu::goToUser() {
} }
void Menu::bandwidthDetails() { void Menu::bandwidthDetails() {
if (! _bandwidthDialog) { if (! _bandwidthDialog) {
_bandwidthDialog = new BandwidthDialog(Application::getInstance()->getGLWidget(), _bandwidthDialog = new BandwidthDialog(Application::getInstance()->getGLWidget(),
Application::getInstance()->getBandwidthMeter()); Application::getInstance()->getBandwidthMeter());
@ -1057,6 +1064,32 @@ void Menu::voxelStatsDetailsClosed() {
} }
} }
void Menu::setVoxelSizeScale(float sizeScale) {
_voxelSizeScale = sizeScale;
Application::getInstance()->getVoxels()->redrawInViewVoxels();
}
void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
_boundaryLevelAdjust = boundaryLevelAdjust;
Application::getInstance()->getVoxels()->redrawInViewVoxels();
}
void Menu::lodTools() {
if (!_lodToolsDialog) {
_lodToolsDialog = new LodToolsDialog(Application::getInstance()->getGLWidget());
connect(_lodToolsDialog, SIGNAL(closed()), SLOT(lodToolsClosed()));
_lodToolsDialog->show();
}
_lodToolsDialog->raise();
}
void Menu::lodToolsClosed() {
if (_lodToolsDialog) {
delete _lodToolsDialog;
_lodToolsDialog = NULL;
}
}
void Menu::cycleFrustumRenderMode() { void Menu::cycleFrustumRenderMode() {
_frustumDrawMode = (FrustumDrawMode)((_frustumDrawMode + 1) % FRUSTUM_DRAW_MODE_COUNT); _frustumDrawMode = (FrustumDrawMode)((_frustumDrawMode + 1) % FRUSTUM_DRAW_MODE_COUNT);
updateFrustumRenderModeAction(); updateFrustumRenderModeAction();

View file

@ -35,6 +35,7 @@ class QSettings;
class BandwidthDialog; class BandwidthDialog;
class VoxelStatsDialog; class VoxelStatsDialog;
class LodToolsDialog;
class Menu : public QMenuBar { class Menu : public QMenuBar {
Q_OBJECT Q_OBJECT
@ -53,15 +54,23 @@ public:
FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; } FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; }
ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; }
VoxelStatsDialog* getVoxelStatsDialog() const { return _voxelStatsDialog; } VoxelStatsDialog* getVoxelStatsDialog() const { return _voxelStatsDialog; }
LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; }
int getMaxVoxels() const { return _maxVoxels; } int getMaxVoxels() const { return _maxVoxels; }
QAction* getUseVoxelShader() const { return _useVoxelShader; } QAction* getUseVoxelShader() const { return _useVoxelShader; }
void handleViewFrustumOffsetKeyModifier(int key); void handleViewFrustumOffsetKeyModifier(int key);
// User Tweakable LOD Items
void setVoxelSizeScale(float sizeScale);
float getVoxelSizeScale() const { return _voxelSizeScale; }
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
public slots: public slots:
void bandwidthDetails(); void bandwidthDetails();
void voxelStatsDetails(); void voxelStatsDetails();
void lodTools();
void loadSettings(QSettings* settings = NULL); void loadSettings(QSettings* settings = NULL);
void saveSettings(QSettings* settings = NULL); void saveSettings(QSettings* settings = NULL);
void importSettings(); void importSettings();
@ -76,6 +85,7 @@ private slots:
void goToLocation(); void goToLocation();
void bandwidthDetailsClosed(); void bandwidthDetailsClosed();
void voxelStatsDetailsClosed(); void voxelStatsDetailsClosed();
void lodToolsClosed();
void cycleFrustumRenderMode(); void cycleFrustumRenderMode();
void updateVoxelModeActions(); void updateVoxelModeActions();
void chooseVoxelPaintColor(); void chooseVoxelPaintColor();
@ -120,7 +130,10 @@ private:
ViewFrustumOffset _viewFrustumOffset; ViewFrustumOffset _viewFrustumOffset;
QActionGroup* _voxelModeActionsGroup; QActionGroup* _voxelModeActionsGroup;
VoxelStatsDialog* _voxelStatsDialog; VoxelStatsDialog* _voxelStatsDialog;
LodToolsDialog* _lodToolsDialog;
int _maxVoxels; int _maxVoxels;
float _voxelSizeScale;
int _boundaryLevelAdjust;
QAction* _useVoxelShader; QAction* _useVoxelShader;
}; };
@ -178,6 +191,7 @@ namespace MenuOption {
const QString GoHome = "Go Home"; const QString GoHome = "Go Home";
const QString Gravity = "Use Gravity"; const QString Gravity = "Use Gravity";
const QString ParticleCloud = "Particle Cloud"; const QString ParticleCloud = "Particle Cloud";
const QString LodTools = "LOD Tools";
const QString Log = "Log"; const QString Log = "Log";
const QString Login = "Login"; const QString Login = "Login";
const QString LookAtIndicator = "Look-at Indicator"; const QString LookAtIndicator = "Look-at Indicator";

View file

@ -109,6 +109,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
_useFastVoxelPipeline = false; _useFastVoxelPipeline = false;
_culledOnce = false; _culledOnce = false;
_inhideOutOfView = false;
} }
void VoxelSystem::voxelDeleted(VoxelNode* node) { void VoxelSystem::voxelDeleted(VoxelNode* node) {
@ -139,7 +140,9 @@ void VoxelSystem::voxelUpdated(VoxelNode* node) {
if (node->getVoxelSystem() == this) { if (node->getVoxelSystem() == this) {
bool shouldRender = false; // assume we don't need to render it bool shouldRender = false; // assume we don't need to render it
// if it's colored, we might need to render it! // if it's colored, we might need to render it!
shouldRender = node->calculateShouldRender(_viewFrustum); float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
shouldRender = node->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust);
if (node->getShouldRender() != shouldRender) { if (node->getShouldRender() != shouldRender) {
node->setShouldRender(shouldRender); node->setShouldRender(shouldRender);
@ -155,7 +158,7 @@ void VoxelSystem::voxelUpdated(VoxelNode* node) {
VoxelNode* childNode = node->getChildAtIndex(i); VoxelNode* childNode = node->getChildAtIndex(i);
if (childNode) { if (childNode) {
bool wasShouldRender = childNode->getShouldRender(); bool wasShouldRender = childNode->getShouldRender();
bool isShouldRender = childNode->calculateShouldRender(_viewFrustum); bool isShouldRender = childNode->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust);
if (wasShouldRender && !isShouldRender) { if (wasShouldRender && !isShouldRender) {
childrenGotHiddenCount++; childrenGotHiddenCount++;
} }
@ -923,7 +926,9 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
int voxelsUpdated = 0; int voxelsUpdated = 0;
bool shouldRender = false; // assume we don't need to render it bool shouldRender = false; // assume we don't need to render it
// if it's colored, we might need to render it! // if it's colored, we might need to render it!
shouldRender = node->calculateShouldRender(_viewFrustum); float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();;
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
shouldRender = node->calculateShouldRender(_viewFrustum, voxelSizeScale, boundaryLevelAdjust);
node->setShouldRender(shouldRender); node->setShouldRender(shouldRender);
// let children figure out their renderness // let children figure out their renderness
@ -1384,6 +1389,10 @@ void VoxelSystem::killLocalVoxels() {
setupNewVoxelsForDrawing(); setupNewVoxelsForDrawing();
} }
void VoxelSystem::redrawInViewVoxels() {
hideOutOfView(true);
}
bool VoxelSystem::clearAllNodesBufferIndexOperation(VoxelNode* node, void* extraData) { bool VoxelSystem::clearAllNodesBufferIndexOperation(VoxelNode* node, void* extraData) {
_nodeCount++; _nodeCount++;
@ -1771,7 +1780,9 @@ bool VoxelSystem::showAllLocalVoxelsOperation(VoxelNode* node, void* extraData)
args->nodesScanned++; args->nodesScanned++;
bool shouldRender = true; // node->calculateShouldRender(&args->thisViewFrustum); float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();;
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
bool shouldRender = node->calculateShouldRender(&args->thisViewFrustum, voxelSizeScale, boundaryLevelAdjust);
node->setShouldRender(shouldRender); node->setShouldRender(shouldRender);
if (shouldRender) { if (shouldRender) {
@ -1838,6 +1849,14 @@ public:
}; };
void VoxelSystem::hideOutOfView(bool forceFullFrustum) { void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
// don't re-enter...
if (_inhideOutOfView) {
return;
}
_inhideOutOfView = true;
bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showDebugDetails, "hideOutOfView()", showDebugDetails); PerformanceWarning warn(showDebugDetails, "hideOutOfView()", showDebugDetails);
bool widenFrustum = true; bool widenFrustum = true;
@ -1869,10 +1888,13 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.isVerySimilar(args.thisViewFrustum)) { if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.isVerySimilar(args.thisViewFrustum)) {
//printf("view frustum hasn't changed BAIL!!!\n"); //printf("view frustum hasn't changed BAIL!!!\n");
_inhideOutOfView = false;
return; return;
} }
pthread_mutex_lock(&_treeLock);
_tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args);
pthread_mutex_unlock(&_treeLock);
_lastCulledViewFrustum = args.thisViewFrustum; // save last stable _lastCulledViewFrustum = args.thisViewFrustum; // save last stable
_culledOnce = true; _culledOnce = true;
@ -1890,6 +1912,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside
); );
} }
_inhideOutOfView = false;
} }
bool VoxelSystem::hideAllSubTreeOperation(VoxelNode* node, void* extraData) { bool VoxelSystem::hideAllSubTreeOperation(VoxelNode* node, void* extraData) {
@ -1947,7 +1970,9 @@ bool VoxelSystem::showAllSubTreeOperation(VoxelNode* node, void* extraData) {
args->nodesInside++; args->nodesInside++;
bool shouldRender = node->calculateShouldRender(&args->thisViewFrustum); float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
bool shouldRender = node->calculateShouldRender(&args->thisViewFrustum, voxelSizeScale, boundaryLevelAdjust);
node->setShouldRender(shouldRender); node->setShouldRender(shouldRender);
if (shouldRender && !node->isKnownBufferIndex()) { if (shouldRender && !node->isKnownBufferIndex()) {

View file

@ -83,6 +83,7 @@ public:
float getVoxelsBytesReadPerSecondAverage(); float getVoxelsBytesReadPerSecondAverage();
void killLocalVoxels(); void killLocalVoxels();
void redrawInViewVoxels();
virtual void removeOutOfView(); virtual void removeOutOfView();
virtual void hideOutOfView(bool forceFullFrustum = false); virtual void hideOutOfView(bool forceFullFrustum = false);
@ -298,6 +299,8 @@ private:
bool _inSetupNewVoxelsForDrawing; bool _inSetupNewVoxelsForDrawing;
bool _useFastVoxelPipeline; bool _useFastVoxelPipeline;
bool _inhideOutOfView;
}; };
#endif #endif

View file

@ -0,0 +1,153 @@
//
// LodToolsDialog.cpp
// interface
//
// Created by Brad Hefta-Gaub on 7/19/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include <QFormLayout>
#include <QDialogButtonBox>
#include <QPalette>
#include <QColor>
#include <QSlider>
#include <QPushButton>
#include <QString>
#include <VoxelConstants.h>
#include "Menu.h"
#include "ui/LodToolsDialog.h"
LodToolsDialog::LodToolsDialog(QWidget* parent) :
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)
{
this->setWindowTitle("LOD Tools");
// Create layouter
QFormLayout* form = new QFormLayout();
_lodSize = new QSlider(Qt::Horizontal);
const int MAX_LOD_SIZE = MAX_LOD_SIZE_MULTIPLIER;
const int MIN_LOD_SIZE = 0;
const int STEP_LOD_SIZE = 1;
const int PAGE_STEP_LOD_SIZE = 100;
const int SLIDER_WIDTH = 300;
_lodSize->setMaximum(MAX_LOD_SIZE);
_lodSize->setMinimum(MIN_LOD_SIZE);
_lodSize->setSingleStep(STEP_LOD_SIZE);
_lodSize->setTickInterval(PAGE_STEP_LOD_SIZE);
_lodSize->setTickPosition(QSlider::TicksBelow);
_lodSize->setFixedWidth(SLIDER_WIDTH);
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
int sliderValue = Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE;
_lodSize->setValue(sliderValue);
form->addRow("LOD Size Scale:", _lodSize);
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
_boundaryLevelAdjust = new QSlider(Qt::Horizontal);
const int MAX_ADJUST = 10;
const int MIN_ADJUST = 0;
const int STEP_ADJUST = 1;
_boundaryLevelAdjust->setMaximum(MAX_ADJUST);
_boundaryLevelAdjust->setMinimum(MIN_ADJUST);
_boundaryLevelAdjust->setSingleStep(STEP_ADJUST);
_boundaryLevelAdjust->setTickInterval(STEP_ADJUST);
_boundaryLevelAdjust->setTickPosition(QSlider::TicksBelow);
_boundaryLevelAdjust->setFixedWidth(SLIDER_WIDTH);
sliderValue = Menu::getInstance()->getBoundaryLevelAdjust();
_boundaryLevelAdjust->setValue(sliderValue);
form->addRow("Boundary Level Adjust:", _boundaryLevelAdjust);
connect(_boundaryLevelAdjust,SIGNAL(valueChanged(int)),this,SLOT(boundaryLevelValueChanged(int)));
// Create a label with feedback...
_feedback = new QLabel();
QPalette palette = _feedback->palette();
const unsigned redish = 0xfff00000;
palette.setColor(QPalette::WindowText, QColor::fromRgb(redish));
_feedback->setPalette(palette);
_feedback->setText(getFeedbackText());
const int FEEDBACK_WIDTH = 350;
_feedback->setFixedWidth(FEEDBACK_WIDTH);
form->addRow("You can see... ", _feedback);
// Add a button to reset
QPushButton* resetButton = new QPushButton("Reset");
form->addRow("", resetButton);
connect(resetButton,SIGNAL(clicked(bool)),this,SLOT(resetClicked(bool)));
this->QDialog::setLayout(form);
}
QString LodToolsDialog::getFeedbackText() {
// determine granularity feedback
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
QString granularityFeedback;
switch (boundaryLevelAdjust) {
case 0: {
granularityFeedback = QString("at standard granularity.");
} break;
case 1: {
granularityFeedback = QString("at half of standard granularity.");
} break;
case 2: {
granularityFeedback = QString("at a third of standard granularity.");
} break;
default: {
granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
} break;
}
// distance feedback
float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
float relativeToDefault = voxelSizeScale / DEFAULT_VOXEL_SIZE_SCALE;
QString result;
if (relativeToDefault > 1.01) {
result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
} else if (relativeToDefault > 0.99) {
result = QString("the default distance %1").arg(granularityFeedback);
} else {
result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback);
}
return result;
}
LodToolsDialog::~LodToolsDialog() {
delete _feedback;
delete _lodSize;
delete _boundaryLevelAdjust;
}
void LodToolsDialog::sizeScaleValueChanged(int value) {
float realValue = value * TREE_SCALE;
Menu::getInstance()->setVoxelSizeScale(realValue);
_feedback->setText(getFeedbackText());
}
void LodToolsDialog::boundaryLevelValueChanged(int value) {
Menu::getInstance()->setBoundaryLevelAdjust(value);
_feedback->setText(getFeedbackText());
}
void LodToolsDialog::resetClicked(bool checked) {
int sliderValue = DEFAULT_VOXEL_SIZE_SCALE / TREE_SCALE;
//sizeScaleValueChanged(sliderValue);
_lodSize->setValue(sliderValue);
_boundaryLevelAdjust->setValue(0);
}
void LodToolsDialog::reject() {
// Just regularly close upon ESC
this->QDialog::close();
}
void LodToolsDialog::closeEvent(QCloseEvent* event) {
this->QDialog::closeEvent(event);
emit closed();
}

View file

@ -0,0 +1,48 @@
//
// LodToolsDialog.h
// interface
//
// Created by Brad Hefta-Gaub on 7/19/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__LodToolsDialog__
#define __hifi__LodToolsDialog__
#include <QDialog>
#include <QLabel>
#include <QSlider>
#include <VoxelSceneStats.h>
class LodToolsDialog : public QDialog {
Q_OBJECT
public:
// Sets up the UI
LodToolsDialog(QWidget* parent);
~LodToolsDialog();
signals:
void closed();
public slots:
void reject();
void sizeScaleValueChanged(int value);
void boundaryLevelValueChanged(int value);
void resetClicked(bool checked);
protected:
// Emits a 'closed' signal when this dialog is closed.
void closeEvent(QCloseEvent*);
private:
QString getFeedbackText();
QSlider* _lodSize;
QSlider* _boundaryLevelAdjust;
QLabel* _feedback;
};
#endif /* defined(__interface__LodToolsDialog__) */

View file

@ -36,6 +36,9 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
case PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY: case PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY:
return 1; return 1;
case PACKET_TYPE_VOXEL_QUERY:
return 1;
default: default:
return 0; return 0;
} }

View file

@ -23,7 +23,11 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
_viewFrustumChanging(false), _viewFrustumChanging(false),
_viewFrustumJustStoppedChanging(true), _viewFrustumJustStoppedChanging(true),
_currentPacketIsColor(true), _currentPacketIsColor(true),
_voxelSendThread(NULL) _voxelSendThread(NULL),
_lastClientBoundaryLevelAdjust(0),
_lastClientVoxelSizeScale(DEFAULT_VOXEL_SIZE_SCALE),
_lodChanged(false),
_lodInitialized(false)
{ {
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; _voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
_voxelPacketAt = _voxelPacket; _voxelPacketAt = _voxelPacket;
@ -140,6 +144,23 @@ bool VoxelNodeData::updateCurrentViewFrustum() {
currentViewFrustumChanged = true; currentViewFrustumChanged = true;
} }
// Also check for LOD changes from the client
if (_lodInitialized) {
if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
_lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
_lodChanged = true;
}
if (_lastClientVoxelSizeScale != getVoxelSizeScale()) {
_lastClientVoxelSizeScale = getVoxelSizeScale();
_lodChanged = true;
}
} else {
_lodInitialized = true;
_lastClientVoxelSizeScale = getVoxelSizeScale();
_lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
_lodChanged = false;
}
// When we first detect that the view stopped changing, we record this. // When we first detect that the view stopped changing, we record this.
// but we don't change it back to false until we've completely sent this // but we don't change it back to false until we've completely sent this
// scene. // scene.
@ -154,6 +175,7 @@ void VoxelNodeData::setViewSent(bool viewSent) {
_viewSent = viewSent; _viewSent = viewSent;
if (viewSent) { if (viewSent) {
_viewFrustumJustStoppedChanging = false; _viewFrustumJustStoppedChanging = false;
_lodChanged = false;
} }
} }

View file

@ -68,6 +68,8 @@ public:
bool getCurrentPacketIsColor() const { return _currentPacketIsColor; }; bool getCurrentPacketIsColor() const { return _currentPacketIsColor; };
bool hasLodChanged() const { return _lodChanged; };
VoxelSceneStats stats; VoxelSceneStats stats;
void initializeVoxelSendThread(VoxelServer* voxelServer); void initializeVoxelSendThread(VoxelServer* voxelServer);
@ -98,6 +100,12 @@ private:
bool _currentPacketIsColor; bool _currentPacketIsColor;
VoxelSendThread* _voxelSendThread; VoxelSendThread* _voxelSendThread;
// watch for LOD changes
int _lastClientBoundaryLevelAdjust;
float _lastClientVoxelSizeScale;
bool _lodChanged;
bool _lodInitialized;
}; };
#endif /* defined(__hifi__VoxelNodeData__) */ #endif /* defined(__hifi__VoxelNodeData__) */

View file

@ -175,7 +175,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
// if our view has changed, we need to reset these things... // if our view has changed, we need to reset these things...
if (viewFrustumChanged) { if (viewFrustumChanged) {
if (_myServer->wantDumpVoxelsOnMove()) { if (_myServer->wantDumpVoxelsOnMove() || nodeData->hasLodChanged()) {
nodeData->nodeBag.deleteAll(); nodeData->nodeBag.deleteAll();
} }
nodeData->map.erase(); nodeData->map.erase();
@ -194,7 +194,8 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
} }
// start tracking our stats // start tracking our stats
bool isFullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging(); bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta())
&& nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged();
// If we're starting a full scene, then definitely we want to empty the nodeBag // If we're starting a full scene, then definitely we want to empty the nodeBag
if (isFullScene) { if (isFullScene) {
@ -250,15 +251,20 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
VoxelNode* subTree = nodeData->nodeBag.extract(); VoxelNode* subTree = nodeData->nodeBag.extract();
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling(); bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP; CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP;
int boundaryLevelAdjust = viewFrustumChanged && nodeData->getWantLowResMoving()
? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST;
bool isFullScene = (!viewFrustumChanged || !nodeData->getWantDelta()) && float voxelSizeScale = nodeData->getVoxelSizeScale();
nodeData->getViewFrustumJustStoppedChanging(); int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged && nodeData->getWantLowResMoving()
? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) &&
nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged();
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, voxelSizeScale,
nodeData->getLastTimeBagEmpty(), nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction()); isFullScene, &nodeData->stats, _myServer->getJurisdiction());

View file

@ -13,6 +13,7 @@
#define __hifi_VoxelConstants_h__ #define __hifi_VoxelConstants_h__
#include <limits.h> #include <limits.h>
#include <stdint.h>
#include <OctalCode.h> #include <OctalCode.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
@ -27,7 +28,8 @@ const uint64_t CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if
const int TREE_SCALE = 16384; // ~10 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe const int TREE_SCALE = 16384; // ~10 miles.. This is the number of meters of the 0.0 to 1.0 voxel universe
// This controls the LOD. Larger number will make smaller voxels visible at greater distance. // This controls the LOD. Larger number will make smaller voxels visible at greater distance.
const float VOXEL_SIZE_SCALE = TREE_SCALE * 400.0f; const float DEFAULT_VOXEL_SIZE_SCALE = TREE_SCALE * 400.0f;
const float MAX_LOD_SIZE_MULTIPLIER = 2000.0f;
const int NUMBER_OF_CHILDREN = 8; const int NUMBER_OF_CHILDREN = 8;
const int MAX_VOXEL_PACKET_SIZE = 1492; const int MAX_VOXEL_PACKET_SIZE = 1492;

View file

@ -1371,12 +1371,12 @@ ViewFrustum::location VoxelNode::inFrustum(const ViewFrustum& viewFrustum) const
// Since, if we know the camera position and orientation, we can know which of the corners is the "furthest" // Since, if we know the camera position and orientation, we can know which of the corners is the "furthest"
// corner. We can use we can use this corner as our "voxel position" to do our distance calculations off of. // corner. We can use we can use this corner as our "voxel position" to do our distance calculations off of.
// By doing this, we don't need to test each child voxel's position vs the LOD boundary // By doing this, we don't need to test each child voxel's position vs the LOD boundary
bool VoxelNode::calculateShouldRender(const ViewFrustum* viewFrustum, int boundaryLevelAdjust) const { bool VoxelNode::calculateShouldRender(const ViewFrustum* viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
bool shouldRender = false; bool shouldRender = false;
if (isColored()) { if (isColored()) {
float furthestDistance = furthestDistanceToCamera(*viewFrustum); float furthestDistance = furthestDistanceToCamera(*viewFrustum);
float boundary = boundaryDistanceForRenderLevel(getLevel() + boundaryLevelAdjust); float boundary = boundaryDistanceForRenderLevel(getLevel() + boundaryLevelAdjust, voxelScaleSize);
float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust); float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust, voxelScaleSize);
bool inBoundary = (furthestDistance <= boundary); bool inBoundary = (furthestDistance <= boundary);
bool inChildBoundary = (furthestDistance <= childBoundary); bool inChildBoundary = (furthestDistance <= childBoundary);
shouldRender = (isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary); shouldRender = (isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary);

View file

@ -69,7 +69,8 @@ public:
float distanceToCamera(const ViewFrustum& viewFrustum) const; float distanceToCamera(const ViewFrustum& viewFrustum) const;
float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const; float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
bool calculateShouldRender(const ViewFrustum* viewFrustum, int boundaryLevelAdjust = 0) const; bool calculateShouldRender(const ViewFrustum* viewFrustum,
float voxelSizeScale = DEFAULT_VOXEL_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
// points are assumed to be in Voxel Coordinates (not TREE_SCALE'd) // points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)
float distanceSquareToPoint(const glm::vec3& point) const; // when you don't need the actual distance, use this. float distanceSquareToPoint(const glm::vec3& point) const; // when you don't need the actual distance, use this.

View file

@ -35,7 +35,8 @@ VoxelQuery::VoxelQuery(Node* owningNode) :
_wantDelta(true), _wantDelta(true),
_wantLowResMoving(true), _wantLowResMoving(true),
_wantOcclusionCulling(true), _wantOcclusionCulling(true),
_maxVoxelPPS(DEFAULT_MAX_VOXEL_PPS) _maxVoxelPPS(DEFAULT_MAX_VOXEL_PPS),
_voxelSizeScale(DEFAULT_VOXEL_SIZE_SCALE)
{ {
} }
@ -79,6 +80,14 @@ int VoxelQuery::getBroadcastData(unsigned char* destinationBuffer) {
memcpy(destinationBuffer, &_maxVoxelPPS, sizeof(_maxVoxelPPS)); memcpy(destinationBuffer, &_maxVoxelPPS, sizeof(_maxVoxelPPS));
destinationBuffer += sizeof(_maxVoxelPPS); destinationBuffer += sizeof(_maxVoxelPPS);
// desired voxelSizeScale
memcpy(destinationBuffer, &_voxelSizeScale, sizeof(_voxelSizeScale));
destinationBuffer += sizeof(_voxelSizeScale);
// desired boundaryLevelAdjust
memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust));
destinationBuffer += sizeof(_boundaryLevelAdjust);
return destinationBuffer - bufferStart; return destinationBuffer - bufferStart;
} }
@ -121,6 +130,14 @@ int VoxelQuery::parseData(unsigned char* sourceBuffer, int numBytes) {
memcpy(&_maxVoxelPPS, sourceBuffer, sizeof(_maxVoxelPPS)); memcpy(&_maxVoxelPPS, sourceBuffer, sizeof(_maxVoxelPPS));
sourceBuffer += sizeof(_maxVoxelPPS); sourceBuffer += sizeof(_maxVoxelPPS);
// desired voxelSizeScale
memcpy(&_voxelSizeScale, sourceBuffer, sizeof(_voxelSizeScale));
sourceBuffer += sizeof(_voxelSizeScale);
// desired boundaryLevelAdjust
memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust));
sourceBuffer += sizeof(_boundaryLevelAdjust);
return sourceBuffer - startPosition; return sourceBuffer - startPosition;
} }

View file

@ -69,6 +69,8 @@ public:
bool getWantLowResMoving() const { return _wantLowResMoving; } bool getWantLowResMoving() const { return _wantLowResMoving; }
bool getWantOcclusionCulling() const { return _wantOcclusionCulling; } bool getWantOcclusionCulling() const { return _wantOcclusionCulling; }
int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPPS; } int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPPS; }
float getVoxelSizeScale() const { return _voxelSizeScale; }
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
public slots: public slots:
void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; } void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; }
@ -76,6 +78,8 @@ public slots:
void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; }
void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; } void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; }
void setMaxVoxelPacketsPerSecond(int maxVoxelPPS) { _maxVoxelPPS = maxVoxelPPS; } void setMaxVoxelPacketsPerSecond(int maxVoxelPPS) { _maxVoxelPPS = maxVoxelPPS; }
void setVoxelSizeScale(float voxelSizeScale) { _voxelSizeScale = voxelSizeScale; }
void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; }
protected: protected:
QUuid _uuid; QUuid _uuid;
@ -95,6 +99,8 @@ protected:
bool _wantLowResMoving; bool _wantLowResMoving;
bool _wantOcclusionCulling; bool _wantOcclusionCulling;
int _maxVoxelPPS; int _maxVoxelPPS;
float _voxelSizeScale; /// used for LOD calculations
int _boundaryLevelAdjust; /// used for LOD calculations
private: private:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called

View file

@ -33,13 +33,8 @@
#include "VoxelTree.h" #include "VoxelTree.h"
#include <PacketHeaders.h> #include <PacketHeaders.h>
float boundaryDistanceForRenderLevel(unsigned int renderLevel) { float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
return ::VOXEL_SIZE_SCALE / powf(2, renderLevel); return voxelSizeScale / powf(2, renderLevel);
}
float boundaryDistanceSquaredForRenderLevel(unsigned int renderLevel) {
const float voxelSizeScale = (::VOXEL_SIZE_SCALE/TREE_SCALE) * (::VOXEL_SIZE_SCALE/TREE_SCALE);
return voxelSizeScale / powf(2, (2 * renderLevel));
} }
VoxelTree::VoxelTree(bool shouldReaverage) : VoxelTree::VoxelTree(bool shouldReaverage) :
@ -1114,7 +1109,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
// caller can pass NULL as viewFrustum if they want everything // caller can pass NULL as viewFrustum if they want everything
if (params.viewFrustum) { if (params.viewFrustum) {
float distance = node->distanceToCamera(*params.viewFrustum); float distance = node->distanceToCamera(*params.viewFrustum);
float boundaryDistance = boundaryDistanceForRenderLevel(node->getLevel() + params.boundaryLevelAdjust); float boundaryDistance = boundaryDistanceForRenderLevel(node->getLevel() + params.boundaryLevelAdjust,
params.voxelSizeScale);
// 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) {
@ -1288,7 +1284,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
// 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,
params.voxelSizeScale);
if (!(distance < boundaryDistance)) { if (!(distance < boundaryDistance)) {
// don't need to check childNode here, because we can't get here with no childNode // don't need to check childNode here, because we can't get here with no childNode
@ -1341,7 +1338,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
bool shouldRender = !params.viewFrustum bool shouldRender = !params.viewFrustum
? true ? true
: childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust); : childNode->calculateShouldRender(params.viewFrustum,
params.voxelSizeScale, params.boundaryLevelAdjust);
// track some stats // track some stats
if (params.stats) { if (params.stats) {

View file

@ -57,6 +57,7 @@ public:
const ViewFrustum* lastViewFrustum; const ViewFrustum* lastViewFrustum;
bool wantOcclusionCulling; bool wantOcclusionCulling;
int boundaryLevelAdjust; int boundaryLevelAdjust;
float voxelSizeScale;
uint64_t lastViewFrustumSent; uint64_t lastViewFrustumSent;
bool forceSendScene; bool forceSendScene;
VoxelSceneStats* stats; VoxelSceneStats* stats;
@ -74,6 +75,7 @@ public:
bool wantOcclusionCulling = NO_OCCLUSION_CULLING, bool wantOcclusionCulling = NO_OCCLUSION_CULLING,
CoverageMap* map = IGNORE_COVERAGE_MAP, CoverageMap* map = IGNORE_COVERAGE_MAP,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST, int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
float voxelSizeScale = DEFAULT_VOXEL_SIZE_SCALE,
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT, uint64_t lastViewFrustumSent = IGNORE_LAST_SENT,
bool forceSendScene = true, bool forceSendScene = true,
VoxelSceneStats* stats = IGNORE_SCENE_STATS, VoxelSceneStats* stats = IGNORE_SCENE_STATS,
@ -88,6 +90,7 @@ public:
lastViewFrustum(lastViewFrustum), lastViewFrustum(lastViewFrustum),
wantOcclusionCulling(wantOcclusionCulling), wantOcclusionCulling(wantOcclusionCulling),
boundaryLevelAdjust(boundaryLevelAdjust), boundaryLevelAdjust(boundaryLevelAdjust),
voxelSizeScale(voxelSizeScale),
lastViewFrustumSent(lastViewFrustumSent), lastViewFrustumSent(lastViewFrustumSent),
forceSendScene(forceSendScene), forceSendScene(forceSendScene),
stats(stats), stats(stats),
@ -265,7 +268,6 @@ private:
void chunkifyLeaf(VoxelNode* node); void chunkifyLeaf(VoxelNode* node);
}; };
float boundaryDistanceForRenderLevel(unsigned int renderLevel); float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
float boundaryDistanceSquaredForRenderLevel(unsigned int renderLevel);
#endif /* defined(__hifi__VoxelTree__) */ #endif /* defined(__hifi__VoxelTree__) */