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

View file

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

View file

@ -53,7 +53,10 @@ Menu::Menu() :
_viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET),
_voxelModeActionsGroup(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();
@ -277,6 +280,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
QMenu* cullingOptionsMenu = voxelOptionsMenu->addMenu("Culling Options");
addDisabledActionAndSeparator(cullingOptionsMenu, "Standard Settings");
@ -517,6 +521,8 @@ void Menu::loadSettings(QSettings* settings) {
_audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0);
_fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES);
_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");
// 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("fieldOfView", _fieldOfView);
settings->setValue("maxVoxels", _maxVoxels);
settings->setValue("voxelSizeScale", _voxelSizeScale);
settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust);
settings->beginGroup("View Frustum Offset Camera");
settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw);
settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch);
@ -1022,7 +1030,6 @@ void Menu::goToUser() {
}
void Menu::bandwidthDetails() {
if (! _bandwidthDialog) {
_bandwidthDialog = new BandwidthDialog(Application::getInstance()->getGLWidget(),
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() {
_frustumDrawMode = (FrustumDrawMode)((_frustumDrawMode + 1) % FRUSTUM_DRAW_MODE_COUNT);
updateFrustumRenderModeAction();

View file

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

View file

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

View file

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

@ -35,7 +35,10 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
case PACKET_TYPE_DOMAIN_LIST_REQUEST:
case PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY:
return 1;
case PACKET_TYPE_VOXEL_QUERY:
return 1;
default:
return 0;
}

View file

@ -23,7 +23,11 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
_viewFrustumChanging(false),
_viewFrustumJustStoppedChanging(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];
_voxelPacketAt = _voxelPacket;
@ -140,6 +144,23 @@ bool VoxelNodeData::updateCurrentViewFrustum() {
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.
// but we don't change it back to false until we've completely sent this
// scene.
@ -154,6 +175,7 @@ void VoxelNodeData::setViewSent(bool viewSent) {
_viewSent = viewSent;
if (viewSent) {
_viewFrustumJustStoppedChanging = false;
_lodChanged = false;
}
}

View file

@ -48,25 +48,27 @@ public:
VoxelNodeBag nodeBag;
CoverageMap map;
ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; };
ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; };
ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; };
ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; };
// These are not classic setters because they are calculating and maintaining state
// which is set asynchronously through the network receive
bool updateCurrentViewFrustum();
void updateLastKnownViewFrustum();
bool getViewSent() const { return _viewSent; };
bool getViewSent() const { return _viewSent; };
void setViewSent(bool viewSent);
bool getViewFrustumChanging() const { return _viewFrustumChanging; };
bool getViewFrustumChanging() const { return _viewFrustumChanging; };
bool getViewFrustumJustStoppedChanging() const { return _viewFrustumJustStoppedChanging; };
uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; };
void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; };
uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; };
void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; };
bool getCurrentPacketIsColor() const { return _currentPacketIsColor; };
bool hasLodChanged() const { return _lodChanged; };
VoxelSceneStats stats;
@ -98,6 +100,12 @@ private:
bool _currentPacketIsColor;
VoxelSendThread* _voxelSendThread;
// watch for LOD changes
int _lastClientBoundaryLevelAdjust;
float _lastClientVoxelSizeScale;
bool _lodChanged;
bool _lodInitialized;
};
#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 (viewFrustumChanged) {
if (_myServer->wantDumpVoxelsOnMove()) {
if (_myServer->wantDumpVoxelsOnMove() || nodeData->hasLodChanged()) {
nodeData->nodeBag.deleteAll();
}
nodeData->map.erase();
@ -194,7 +194,8 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
}
// 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 (isFullScene) {
@ -250,15 +251,20 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
VoxelNode* subTree = nodeData->nodeBag.extract();
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
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()) &&
nodeData->getViewFrustumJustStoppedChanging();
float voxelSizeScale = nodeData->getVoxelSizeScale();
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,
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
wantOcclusionCulling, coverageMap, boundaryLevelAdjust,
wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale,
nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction());

View file

@ -13,6 +13,7 @@
#define __hifi_VoxelConstants_h__
#include <limits.h>
#include <stdint.h>
#include <OctalCode.h>
#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
// 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 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"
// 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
bool VoxelNode::calculateShouldRender(const ViewFrustum* viewFrustum, int boundaryLevelAdjust) const {
bool VoxelNode::calculateShouldRender(const ViewFrustum* viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
bool shouldRender = false;
if (isColored()) {
float furthestDistance = furthestDistanceToCamera(*viewFrustum);
float boundary = boundaryDistanceForRenderLevel(getLevel() + boundaryLevelAdjust);
float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust);
float boundary = boundaryDistanceForRenderLevel(getLevel() + boundaryLevelAdjust, voxelScaleSize);
float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust, voxelScaleSize);
bool inBoundary = (furthestDistance <= boundary);
bool inChildBoundary = (furthestDistance <= childBoundary);
shouldRender = (isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary);

View file

@ -69,7 +69,8 @@ public:
float distanceToCamera(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)
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),
_wantLowResMoving(true),
_wantOcclusionCulling(true),
_maxVoxelPPS(DEFAULT_MAX_VOXEL_PPS)
_maxVoxelPPS(DEFAULT_MAX_VOXEL_PPS),
_voxelSizeScale(DEFAULT_VOXEL_SIZE_SCALE)
{
}
@ -78,6 +79,14 @@ int VoxelQuery::getBroadcastData(unsigned char* destinationBuffer) {
// desired Max Voxel PPS
memcpy(destinationBuffer, &_maxVoxelPPS, 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;
}
@ -120,7 +129,15 @@ int VoxelQuery::parseData(unsigned char* sourceBuffer, int numBytes) {
// desired Max Voxel PPS
memcpy(&_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;
}

View file

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

View file

@ -33,13 +33,8 @@
#include "VoxelTree.h"
#include <PacketHeaders.h>
float boundaryDistanceForRenderLevel(unsigned int renderLevel) {
return ::VOXEL_SIZE_SCALE / 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));
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
return voxelSizeScale / powf(2, renderLevel);
}
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
if (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 (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...
float distance = distancesToChildren[i]; // params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0;
float boundaryDistance = !params.viewFrustum ? 1 :
boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust);
boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust,
params.voxelSizeScale);
if (!(distance < boundaryDistance)) {
// 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
? true
: childNode->calculateShouldRender(params.viewFrustum, params.boundaryLevelAdjust);
: childNode->calculateShouldRender(params.viewFrustum,
params.voxelSizeScale, params.boundaryLevelAdjust);
// track some stats
if (params.stats) {

View file

@ -47,52 +47,55 @@ const uint64_t IGNORE_LAST_SENT = 0;
class EncodeBitstreamParams {
public:
int maxEncodeLevel;
int maxLevelReached;
const ViewFrustum* viewFrustum;
bool includeColor;
bool includeExistsBits;
int chopLevels;
bool deltaViewFrustum;
const ViewFrustum* lastViewFrustum;
bool wantOcclusionCulling;
int boundaryLevelAdjust;
uint64_t lastViewFrustumSent;
bool forceSendScene;
VoxelSceneStats* stats;
CoverageMap* map;
JurisdictionMap* jurisdictionMap;
int maxEncodeLevel;
int maxLevelReached;
const ViewFrustum* viewFrustum;
bool includeColor;
bool includeExistsBits;
int chopLevels;
bool deltaViewFrustum;
const ViewFrustum* lastViewFrustum;
bool wantOcclusionCulling;
int boundaryLevelAdjust;
float voxelSizeScale;
uint64_t lastViewFrustumSent;
bool forceSendScene;
VoxelSceneStats* stats;
CoverageMap* map;
JurisdictionMap* jurisdictionMap;
EncodeBitstreamParams(
int maxEncodeLevel = INT_MAX,
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
bool includeColor = WANT_COLOR,
bool includeExistsBits = WANT_EXISTS_BITS,
int chopLevels = 0,
bool deltaViewFrustum = false,
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
bool wantOcclusionCulling= NO_OCCLUSION_CULLING,
CoverageMap* map = IGNORE_COVERAGE_MAP,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT,
bool forceSendScene = true,
VoxelSceneStats* stats = IGNORE_SCENE_STATS,
JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP) :
maxEncodeLevel (maxEncodeLevel),
maxLevelReached (0),
viewFrustum (viewFrustum),
includeColor (includeColor),
includeExistsBits (includeExistsBits),
chopLevels (chopLevels),
deltaViewFrustum (deltaViewFrustum),
lastViewFrustum (lastViewFrustum),
wantOcclusionCulling (wantOcclusionCulling),
boundaryLevelAdjust (boundaryLevelAdjust),
lastViewFrustumSent (lastViewFrustumSent),
forceSendScene (forceSendScene),
stats (stats),
map (map),
jurisdictionMap (jurisdictionMap)
int maxEncodeLevel = INT_MAX,
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
bool includeColor = WANT_COLOR,
bool includeExistsBits = WANT_EXISTS_BITS,
int chopLevels = 0,
bool deltaViewFrustum = false,
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
bool wantOcclusionCulling = NO_OCCLUSION_CULLING,
CoverageMap* map = IGNORE_COVERAGE_MAP,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
float voxelSizeScale = DEFAULT_VOXEL_SIZE_SCALE,
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT,
bool forceSendScene = true,
VoxelSceneStats* stats = IGNORE_SCENE_STATS,
JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP) :
maxEncodeLevel(maxEncodeLevel),
maxLevelReached(0),
viewFrustum(viewFrustum),
includeColor(includeColor),
includeExistsBits(includeExistsBits),
chopLevels(chopLevels),
deltaViewFrustum(deltaViewFrustum),
lastViewFrustum(lastViewFrustum),
wantOcclusionCulling(wantOcclusionCulling),
boundaryLevelAdjust(boundaryLevelAdjust),
voxelSizeScale(voxelSizeScale),
lastViewFrustumSent(lastViewFrustumSent),
forceSendScene(forceSendScene),
stats(stats),
map(map),
jurisdictionMap(jurisdictionMap)
{}
};
@ -265,7 +268,6 @@ private:
void chunkifyLeaf(VoxelNode* node);
};
float boundaryDistanceForRenderLevel(unsigned int renderLevel);
float boundaryDistanceSquaredForRenderLevel(unsigned int renderLevel);
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
#endif /* defined(__hifi__VoxelTree__) */