mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 16:36:54 +02:00
menu cleanup, support for on the fly switching of maxVoxels and useVoxelShader
This commit is contained in:
parent
552d9fadd8
commit
7845340279
6 changed files with 237 additions and 159 deletions
|
@ -1521,7 +1521,6 @@ void Application::initDisplay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::init() {
|
void Application::init() {
|
||||||
_voxels.init();
|
|
||||||
_sharedVoxelSystemViewFrustum.setPosition(glm::vec3(TREE_SCALE / 2.0f,
|
_sharedVoxelSystemViewFrustum.setPosition(glm::vec3(TREE_SCALE / 2.0f,
|
||||||
TREE_SCALE / 2.0f,
|
TREE_SCALE / 2.0f,
|
||||||
3.0f * TREE_SCALE / 2.0f));
|
3.0f * TREE_SCALE / 2.0f));
|
||||||
|
@ -1573,9 +1572,13 @@ void Application::init() {
|
||||||
if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) {
|
if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) {
|
||||||
_audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples());
|
_audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples());
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug("Loaded settings.\n");
|
qDebug("Loaded settings.\n");
|
||||||
|
|
||||||
|
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
|
||||||
|
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
|
||||||
|
_voxels.init();
|
||||||
|
|
||||||
|
|
||||||
Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL(), _myAvatar.getHead().getBlendFace().getModelURL());
|
Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL(), _myAvatar.getHead().getBlendFace().getModelURL());
|
||||||
|
|
||||||
_palette.init(_glWidget->width(), _glWidget->height());
|
_palette.init(_glWidget->width(), _glWidget->height());
|
||||||
|
@ -2915,7 +2918,10 @@ void Application::displayStats() {
|
||||||
|
|
||||||
std::stringstream voxelStats;
|
std::stringstream voxelStats;
|
||||||
voxelStats.precision(4);
|
voxelStats.precision(4);
|
||||||
voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K";
|
voxelStats << "Voxels Rendered: " << _voxels.getVoxelsRendered() / 1000.f << "K " <<
|
||||||
|
"Updated: " << _voxels.getVoxelsUpdated()/1000.f << "K " <<
|
||||||
|
"Max: " << _voxels.getMaxVoxels()/1000.f << "K ";
|
||||||
|
|
||||||
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
|
|
|
@ -48,7 +48,8 @@ Menu::Menu() :
|
||||||
_frustumDrawMode(FRUSTUM_DRAW_MODE_ALL),
|
_frustumDrawMode(FRUSTUM_DRAW_MODE_ALL),
|
||||||
_viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET),
|
_viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET),
|
||||||
_voxelModeActionsGroup(NULL),
|
_voxelModeActionsGroup(NULL),
|
||||||
_voxelStatsDialog(NULL)
|
_voxelStatsDialog(NULL),
|
||||||
|
_maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM)
|
||||||
{
|
{
|
||||||
Application *appInstance = Application::getInstance();
|
Application *appInstance = Application::getInstance();
|
||||||
|
|
||||||
|
@ -249,7 +250,8 @@ Menu::Menu() :
|
||||||
SLOT(setRenderVoxels(bool)));
|
SLOT(setRenderVoxels(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
|
||||||
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader);
|
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0,
|
||||||
|
false, this, SLOT(switchVoxelShader()));
|
||||||
|
|
||||||
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
||||||
|
|
||||||
|
@ -485,6 +487,7 @@ void Menu::loadSettings(QSettings* settings) {
|
||||||
_gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f);
|
_gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f);
|
||||||
_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);
|
||||||
|
|
||||||
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
|
||||||
|
@ -508,6 +511,7 @@ void Menu::saveSettings(QSettings* settings) {
|
||||||
settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity);
|
settings->setValue("gyroCameraSensitivity", _gyroCameraSensitivity);
|
||||||
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
||||||
settings->setValue("fieldOfView", _fieldOfView);
|
settings->setValue("fieldOfView", _fieldOfView);
|
||||||
|
settings->setValue("maxVoxels", _maxVoxels);
|
||||||
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);
|
||||||
|
@ -755,9 +759,6 @@ void Menu::editPreferences() {
|
||||||
QFormLayout* form = new QFormLayout();
|
QFormLayout* form = new QFormLayout();
|
||||||
layout->addLayout(form, 1);
|
layout->addLayout(form, 1);
|
||||||
|
|
||||||
QLineEdit* domainServerLineEdit = lineEditForDomainHostname();
|
|
||||||
form->addRow("Domain server:", domainServerLineEdit);
|
|
||||||
|
|
||||||
QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString());
|
QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString());
|
||||||
avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
|
avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
|
||||||
form->addRow("Avatar URL:", avatarURL);
|
form->addRow("Avatar URL:", avatarURL);
|
||||||
|
@ -785,6 +786,13 @@ void Menu::editPreferences() {
|
||||||
audioJitterBufferSamples->setMinimum(-10000);
|
audioJitterBufferSamples->setMinimum(-10000);
|
||||||
audioJitterBufferSamples->setValue(_audioJitterBufferSamples);
|
audioJitterBufferSamples->setValue(_audioJitterBufferSamples);
|
||||||
form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples);
|
form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples);
|
||||||
|
|
||||||
|
QSpinBox* maxVoxels = new QSpinBox();
|
||||||
|
maxVoxels->setMaximum(5000000);
|
||||||
|
maxVoxels->setMinimum(0);
|
||||||
|
maxVoxels->setSingleStep(50000);
|
||||||
|
maxVoxels->setValue(_maxVoxels);
|
||||||
|
form->addRow("Maximum Voxels:", maxVoxels);
|
||||||
|
|
||||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
|
dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
|
||||||
|
@ -797,8 +805,6 @@ void Menu::editPreferences() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDSHostname(domainServerLineEdit->text());
|
|
||||||
|
|
||||||
QUrl avatarVoxelURL(avatarURL->text());
|
QUrl avatarVoxelURL(avatarURL->text());
|
||||||
applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL);
|
applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL);
|
||||||
|
|
||||||
|
@ -808,6 +814,8 @@ void Menu::editPreferences() {
|
||||||
Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL);
|
Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL);
|
||||||
|
|
||||||
_gyroCameraSensitivity = gyroCameraSensitivity->value();
|
_gyroCameraSensitivity = gyroCameraSensitivity->value();
|
||||||
|
_maxVoxels = maxVoxels->value();
|
||||||
|
applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels);
|
||||||
|
|
||||||
applicationInstance->getAvatar()->setLeanScale(leanScale->value());
|
applicationInstance->getAvatar()->setLeanScale(leanScale->value());
|
||||||
|
|
||||||
|
@ -1007,3 +1015,32 @@ void Menu::updateFrustumRenderModeAction() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::switchVoxelShader() {
|
||||||
|
Application::getInstance()->getVoxels()->setUseVoxelShader(isOptionChecked(MenuOption::UseVoxelShader));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::displayGPUMemory() {
|
||||||
|
|
||||||
|
const int NUM_RESULTS = 4; // see notes, these APIs return up to 4 results
|
||||||
|
GLint results[NUM_RESULTS] = { 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// ATI
|
||||||
|
// http://www.opengl.org/registry/specs/ATI/meminfo.txt
|
||||||
|
//
|
||||||
|
// TEXTURE_FREE_MEMORY_ATI 0x87FC
|
||||||
|
// RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
|
||||||
|
const GLenum VBO_FREE_MEMORY_ATI = 0x87FB;
|
||||||
|
glGetIntegerv(VBO_FREE_MEMORY_ATI, &results[0]);
|
||||||
|
|
||||||
|
// NVIDIA
|
||||||
|
// http://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt
|
||||||
|
//
|
||||||
|
// GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
|
||||||
|
// GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
|
||||||
|
// GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
|
||||||
|
// GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
|
||||||
|
// GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ 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; }
|
||||||
|
int getMaxVoxels() const { return _maxVoxels; }
|
||||||
|
|
||||||
|
|
||||||
void handleViewFrustumOffsetKeyModifier(int key);
|
void handleViewFrustumOffsetKeyModifier(int key);
|
||||||
|
|
||||||
|
@ -78,6 +80,8 @@ private slots:
|
||||||
void chooseVoxelPaintColor();
|
void chooseVoxelPaintColor();
|
||||||
void runTests();
|
void runTests();
|
||||||
void resetSwatchColors();
|
void resetSwatchColors();
|
||||||
|
void displayGPUMemory();
|
||||||
|
void switchVoxelShader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Menu* _instance;
|
static Menu* _instance;
|
||||||
|
@ -115,6 +119,7 @@ private:
|
||||||
ViewFrustumOffset _viewFrustumOffset;
|
ViewFrustumOffset _viewFrustumOffset;
|
||||||
QActionGroup* _voxelModeActionsGroup;
|
QActionGroup* _voxelModeActionsGroup;
|
||||||
VoxelStatsDialog* _voxelStatsDialog;
|
VoxelStatsDialog* _voxelStatsDialog;
|
||||||
|
int _maxVoxels;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace MenuOption {
|
namespace MenuOption {
|
||||||
|
|
|
@ -74,9 +74,8 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
||||||
|
|
||||||
connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));
|
connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));
|
||||||
connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
|
connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
|
||||||
|
|
||||||
_voxelShaderInitialized = false;
|
_useVoxelShader = false;
|
||||||
_initializingVoxelShader = false;
|
|
||||||
_writeVoxelShaderData = NULL;
|
_writeVoxelShaderData = NULL;
|
||||||
_readVoxelShaderData = NULL;
|
_readVoxelShaderData = NULL;
|
||||||
|
|
||||||
|
@ -132,28 +131,7 @@ void VoxelSystem::clearFreeBufferIndexes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelSystem::~VoxelSystem() {
|
VoxelSystem::~VoxelSystem() {
|
||||||
if (_initialized) {
|
cleanupVoxelMemory();
|
||||||
// Destroy glBuffers
|
|
||||||
glDeleteBuffers(1, &_vboVerticesID);
|
|
||||||
glDeleteBuffers(1, &_vboNormalsID);
|
|
||||||
glDeleteBuffers(1, &_vboColorsID);
|
|
||||||
glDeleteBuffers(1, &_vboIndicesID);
|
|
||||||
|
|
||||||
delete[] _readVerticesArray;
|
|
||||||
delete[] _writeVerticesArray;
|
|
||||||
delete[] _readColorsArray;
|
|
||||||
delete[] _writeColorsArray;
|
|
||||||
delete[] _writeVoxelDirtyArray;
|
|
||||||
delete[] _readVoxelDirtyArray;
|
|
||||||
|
|
||||||
// these are used when in VoxelShader mode.
|
|
||||||
glDeleteBuffers(1, &_vboVoxelsID);
|
|
||||||
glDeleteBuffers(1, &_vboVoxelsIndicesID);
|
|
||||||
|
|
||||||
delete[] _writeVoxelShaderData;
|
|
||||||
delete[] _readVoxelShaderData;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete _tree;
|
delete _tree;
|
||||||
pthread_mutex_destroy(&_bufferWriteLock);
|
pthread_mutex_destroy(&_bufferWriteLock);
|
||||||
pthread_mutex_destroy(&_treeLock);
|
pthread_mutex_destroy(&_treeLock);
|
||||||
|
@ -161,43 +139,172 @@ VoxelSystem::~VoxelSystem() {
|
||||||
VoxelNode::removeDeleteHook(this);
|
VoxelNode::removeDeleteHook(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelSystem::getUseVoxelShader() {
|
void VoxelSystem::setMaxVoxels(int maxVoxels) {
|
||||||
bool useVoxelShader = false; //Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader);
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
|
bool wasInitialized = _initialized;
|
||||||
return useVoxelShader;
|
if (wasInitialized) {
|
||||||
|
cleanupVoxelMemory();
|
||||||
|
}
|
||||||
|
_maxVoxels = maxVoxels;
|
||||||
|
if (wasInitialized) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::initVoxelShader() {
|
void VoxelSystem::setUseVoxelShader(bool useVoxelShader) {
|
||||||
GLuint* indicesArray = new GLuint[_maxVoxels];
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
|
bool wasInitialized = _initialized;
|
||||||
// populate the indicesArray
|
if (wasInitialized) {
|
||||||
// this will not change given new voxels, so we can set it all up now
|
cleanupVoxelMemory();
|
||||||
for (int n = 0; n < _maxVoxels; n++) {
|
|
||||||
indicesArray[n] = n;
|
|
||||||
}
|
}
|
||||||
|
_useVoxelShader = useVoxelShader;
|
||||||
|
if (wasInitialized) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
|
}
|
||||||
|
|
||||||
// bind the indices VBO to the actual indices array
|
void VoxelSystem::cleanupVoxelMemory() {
|
||||||
glGenBuffers(1, &_vboVoxelsIndicesID);
|
if (_initialized) {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID);
|
if (_useVoxelShader) {
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW);
|
// these are used when in VoxelShader mode.
|
||||||
|
glDeleteBuffers(1, &_vboVoxelsID);
|
||||||
|
glDeleteBuffers(1, &_vboVoxelsIndicesID);
|
||||||
|
|
||||||
|
delete[] _writeVoxelShaderData;
|
||||||
|
delete[] _readVoxelShaderData;
|
||||||
|
} else {
|
||||||
|
// Destroy glBuffers
|
||||||
|
glDeleteBuffers(1, &_vboVerticesID);
|
||||||
|
glDeleteBuffers(1, &_vboNormalsID);
|
||||||
|
glDeleteBuffers(1, &_vboColorsID);
|
||||||
|
glDeleteBuffers(1, &_vboIndicesID);
|
||||||
|
|
||||||
|
delete[] _readVerticesArray;
|
||||||
|
delete[] _writeVerticesArray;
|
||||||
|
delete[] _readColorsArray;
|
||||||
|
delete[] _writeColorsArray;
|
||||||
|
delete[] _writeVoxelDirtyArray;
|
||||||
|
delete[] _readVoxelDirtyArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_initialized = false; // no longer initialized
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::initVoxelMemory() {
|
||||||
|
if (_useVoxelShader) {
|
||||||
|
GLuint* indicesArray = new GLuint[_maxVoxels];
|
||||||
|
|
||||||
|
// populate the indicesArray
|
||||||
|
// this will not change given new voxels, so we can set it all up now
|
||||||
|
for (int n = 0; n < _maxVoxels; n++) {
|
||||||
|
indicesArray[n] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind the indices VBO to the actual indices array
|
||||||
|
glGenBuffers(1, &_vboVoxelsIndicesID);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboVoxelsIndicesID);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _maxVoxels, indicesArray, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
|
||||||
glGenBuffers(1, &_vboVoxelsID);
|
glGenBuffers(1, &_vboVoxelsID);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
// delete the indices and normals arrays that are no longer needed
|
// delete the indices and normals arrays that are no longer needed
|
||||||
delete[] indicesArray;
|
delete[] indicesArray;
|
||||||
|
|
||||||
// we will track individual dirty sections with these arrays of bools
|
// we will track individual dirty sections with these arrays of bools
|
||||||
_writeVoxelDirtyArray = new bool[_maxVoxels];
|
_writeVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
_readVoxelDirtyArray = new bool[_maxVoxels];
|
_readVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
|
||||||
// prep the data structures for incoming voxel data
|
// prep the data structures for incoming voxel data
|
||||||
_writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
_writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
||||||
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
||||||
|
} else {
|
||||||
|
GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels];
|
||||||
|
|
||||||
|
// populate the indicesArray
|
||||||
|
// this will not change given new voxels, so we can set it all up now
|
||||||
|
for (int n = 0; n < _maxVoxels; n++) {
|
||||||
|
// fill the indices array
|
||||||
|
int voxelIndexOffset = n * INDICES_PER_VOXEL;
|
||||||
|
GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
|
||||||
|
int startIndex = (n * VERTICES_PER_VOXEL);
|
||||||
|
|
||||||
|
for (int i = 0; i < INDICES_PER_VOXEL; i++) {
|
||||||
|
// add indices for this side of the cube
|
||||||
|
currentIndicesPos[i] = startIndex + identityIndices[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
||||||
|
GLfloat* normalsArrayEndPointer = normalsArray;
|
||||||
|
|
||||||
|
// populate the normalsArray
|
||||||
|
for (int n = 0; n < _maxVoxels; n++) {
|
||||||
|
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
|
||||||
|
*(normalsArrayEndPointer++) = identityNormals[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenBuffers(1, &_vboVerticesID);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
// VBO for the normalsArray
|
||||||
|
glGenBuffers(1, &_vboNormalsID);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER,
|
||||||
|
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels,
|
||||||
|
normalsArray, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// VBO for colorsArray
|
||||||
|
glGenBuffers(1, &_vboColorsID);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
// VBO for the indicesArray
|
||||||
|
glGenBuffers(1, &_vboIndicesID);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels,
|
||||||
|
indicesArray, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// delete the indices and normals arrays that are no longer needed
|
||||||
|
delete[] indicesArray;
|
||||||
|
delete[] normalsArray;
|
||||||
|
|
||||||
|
|
||||||
|
// we will track individual dirty sections with these arrays of bools
|
||||||
|
_writeVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
|
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
_readVoxelDirtyArray = new bool[_maxVoxels];
|
||||||
|
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
||||||
|
|
||||||
|
// prep the data structures for incoming voxel data
|
||||||
|
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
||||||
|
_readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
||||||
|
|
||||||
|
_writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
||||||
|
_readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
||||||
|
|
||||||
|
|
||||||
|
// create our simple fragment shader if we're the first system to init
|
||||||
|
if (!_perlinModulateProgram.isLinked()) {
|
||||||
|
switchToResourcesParentIfRequired();
|
||||||
|
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert");
|
||||||
|
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag");
|
||||||
|
_perlinModulateProgram.link();
|
||||||
|
|
||||||
|
_perlinModulateProgram.bind();
|
||||||
|
_perlinModulateProgram.setUniformValue("permutationNormalTexture", 0);
|
||||||
|
_perlinModulateProgram.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
||||||
|
@ -457,7 +564,7 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() {
|
||||||
|
|
||||||
void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) {
|
void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) {
|
||||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||||
if (getUseVoxelShader()) {
|
if (_useVoxelShader) {
|
||||||
GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData);
|
GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData);
|
||||||
void* readDataAt = &_readVoxelShaderData[segmentStart];
|
void* readDataAt = &_readVoxelShaderData[segmentStart];
|
||||||
void* writeDataAt = &_writeVoxelShaderData[segmentStart];
|
void* writeDataAt = &_writeVoxelShaderData[segmentStart];
|
||||||
|
@ -598,7 +705,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) {
|
||||||
void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||||
float voxelScale, const nodeColor& color) {
|
float voxelScale, const nodeColor& color) {
|
||||||
|
|
||||||
if (getUseVoxelShader()) {
|
if (_useVoxelShader) {
|
||||||
VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
|
VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
|
||||||
writeVerticesAt->x = startVertex.x * TREE_SCALE;
|
writeVerticesAt->x = startVertex.x * TREE_SCALE;
|
||||||
writeVerticesAt->y = startVertex.y * TREE_SCALE;
|
writeVerticesAt->y = startVertex.y * TREE_SCALE;
|
||||||
|
@ -647,89 +754,7 @@ void VoxelSystem::init() {
|
||||||
_voxelsInReadArrays = 0;
|
_voxelsInReadArrays = 0;
|
||||||
|
|
||||||
// VBO for the verticesArray
|
// VBO for the verticesArray
|
||||||
//initVoxelShader();
|
initVoxelMemory();
|
||||||
|
|
||||||
if (true) {
|
|
||||||
GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels];
|
|
||||||
|
|
||||||
// populate the indicesArray
|
|
||||||
// this will not change given new voxels, so we can set it all up now
|
|
||||||
for (int n = 0; n < _maxVoxels; n++) {
|
|
||||||
// fill the indices array
|
|
||||||
int voxelIndexOffset = n * INDICES_PER_VOXEL;
|
|
||||||
GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;
|
|
||||||
int startIndex = (n * VERTICES_PER_VOXEL);
|
|
||||||
|
|
||||||
for (int i = 0; i < INDICES_PER_VOXEL; i++) {
|
|
||||||
// add indices for this side of the cube
|
|
||||||
currentIndicesPos[i] = startIndex + identityIndices[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
|
||||||
GLfloat* normalsArrayEndPointer = normalsArray;
|
|
||||||
|
|
||||||
// populate the normalsArray
|
|
||||||
for (int n = 0; n < _maxVoxels; n++) {
|
|
||||||
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
|
|
||||||
*(normalsArrayEndPointer++) = identityNormals[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenBuffers(1, &_vboVerticesID);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
|
||||||
|
|
||||||
// VBO for the normalsArray
|
|
||||||
glGenBuffers(1, &_vboNormalsID);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER,
|
|
||||||
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels,
|
|
||||||
normalsArray, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// VBO for colorsArray
|
|
||||||
glGenBuffers(1, &_vboColorsID);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
|
||||||
|
|
||||||
// VBO for the indicesArray
|
|
||||||
glGenBuffers(1, &_vboIndicesID);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
|
||||||
INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels,
|
|
||||||
indicesArray, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// delete the indices and normals arrays that are no longer needed
|
|
||||||
delete[] indicesArray;
|
|
||||||
delete[] normalsArray;
|
|
||||||
|
|
||||||
|
|
||||||
// we will track individual dirty sections with these arrays of bools
|
|
||||||
_writeVoxelDirtyArray = new bool[_maxVoxels];
|
|
||||||
memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
|
||||||
_readVoxelDirtyArray = new bool[_maxVoxels];
|
|
||||||
memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));
|
|
||||||
|
|
||||||
// prep the data structures for incoming voxel data
|
|
||||||
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
|
||||||
_readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
|
||||||
|
|
||||||
_writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
|
||||||
_readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];
|
|
||||||
|
|
||||||
|
|
||||||
// create our simple fragment shader if we're the first system to init
|
|
||||||
if (!_perlinModulateProgram.isLinked()) {
|
|
||||||
switchToResourcesParentIfRequired();
|
|
||||||
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert");
|
|
||||||
_perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag");
|
|
||||||
_perlinModulateProgram.link();
|
|
||||||
|
|
||||||
_perlinModulateProgram.bind();
|
|
||||||
_perlinModulateProgram.setUniformValue("permutationNormalTexture", 0);
|
|
||||||
_perlinModulateProgram.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,7 +826,7 @@ void VoxelSystem::updateVBOs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) {
|
void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) {
|
||||||
if (getUseVoxelShader()) {
|
if (_useVoxelShader) {
|
||||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||||
GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData);
|
GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData);
|
||||||
GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData);
|
GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData);
|
||||||
|
@ -839,9 +864,9 @@ void VoxelSystem::render(bool texture) {
|
||||||
|
|
||||||
updateVBOs();
|
updateVBOs();
|
||||||
|
|
||||||
//printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(getUseVoxelShader()));
|
//printf("render() _voxelsInReadArrays=%lu voxel shader=%s\n", _voxelsInReadArrays, debug::valueOf(_useVoxelShader));
|
||||||
|
|
||||||
if (getUseVoxelShader()) {
|
if (_useVoxelShader) {
|
||||||
|
|
||||||
Application::getInstance()->getVoxelShader().begin();
|
Application::getInstance()->getVoxelShader().begin();
|
||||||
|
|
||||||
|
@ -1349,7 +1374,7 @@ public:
|
||||||
duplicateVBOIndex(0),
|
duplicateVBOIndex(0),
|
||||||
leafNodes(0)
|
leafNodes(0)
|
||||||
{
|
{
|
||||||
memset(hasIndexFound, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
|
memset(hasIndexFound, false, DEFAULT_MAX_VOXELS_PER_SYSTEM * sizeof(bool));
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned long totalNodes;
|
unsigned long totalNodes;
|
||||||
|
@ -1364,7 +1389,7 @@ public:
|
||||||
|
|
||||||
unsigned long expectedMax;
|
unsigned long expectedMax;
|
||||||
|
|
||||||
bool hasIndexFound[MAX_VOXELS_PER_SYSTEM];
|
bool hasIndexFound[DEFAULT_MAX_VOXELS_PER_SYSTEM];
|
||||||
};
|
};
|
||||||
|
|
||||||
bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) {
|
bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) {
|
||||||
|
@ -1439,7 +1464,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
||||||
glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN;
|
glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN;
|
||||||
glBufferIndex maxInVBO = 0;
|
glBufferIndex maxInVBO = 0;
|
||||||
|
|
||||||
for (glBufferIndex i = 0; i < MAX_VOXELS_PER_SYSTEM; i++) {
|
for (glBufferIndex i = 0; i < DEFAULT_MAX_VOXELS_PER_SYSTEM; i++) {
|
||||||
if (args.hasIndexFound[i]) {
|
if (args.hasIndexFound[i]) {
|
||||||
minInVBO = std::min(minInVBO,i);
|
minInVBO = std::min(minInVBO,i);
|
||||||
maxInVBO = std::max(maxInVBO,i);
|
maxInVBO = std::max(maxInVBO,i);
|
||||||
|
|
|
@ -40,7 +40,7 @@ struct VoxelShaderVBOData
|
||||||
class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook {
|
class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM);
|
VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = DEFAULT_MAX_VOXELS_PER_SYSTEM);
|
||||||
~VoxelSystem();
|
~VoxelSystem();
|
||||||
|
|
||||||
void setDataSourceID(int dataSourceID) { _dataSourceID = dataSourceID; }
|
void setDataSourceID(int dataSourceID) { _dataSourceID = dataSourceID; }
|
||||||
|
@ -65,6 +65,10 @@ public:
|
||||||
bool readFromSquareARGB32Pixels(const char* filename);
|
bool readFromSquareARGB32Pixels(const char* filename);
|
||||||
bool readFromSchematicFile(const char* filename);
|
bool readFromSchematicFile(const char* filename);
|
||||||
|
|
||||||
|
void setUseVoxelShader(bool useVoxelShader);
|
||||||
|
|
||||||
|
void setMaxVoxels(int maxVoxels);
|
||||||
|
long int getMaxVoxels() const { return _maxVoxels; }
|
||||||
long int getVoxelsCreated();
|
long int getVoxelsCreated();
|
||||||
long int getVoxelsColored();
|
long int getVoxelsColored();
|
||||||
long int getVoxelsBytesRead();
|
long int getVoxelsBytesRead();
|
||||||
|
@ -200,9 +204,10 @@ private:
|
||||||
int _lastViewCullingElapsed;
|
int _lastViewCullingElapsed;
|
||||||
|
|
||||||
bool getUseVoxelShader();
|
bool getUseVoxelShader();
|
||||||
void initVoxelShader();
|
void initVoxelMemory();
|
||||||
bool _voxelShaderInitialized;
|
void cleanupVoxelMemory();
|
||||||
bool _initializingVoxelShader;
|
|
||||||
|
bool _useVoxelShader;
|
||||||
GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO
|
GLuint _vboVoxelsID; /// when using voxel shader, we'll use this VBO
|
||||||
GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes
|
GLuint _vboVoxelsIndicesID; /// when using voxel shader, we'll use this VBO for our indexes
|
||||||
VoxelShaderVBOData* _writeVoxelShaderData;
|
VoxelShaderVBOData* _writeVoxelShaderData;
|
||||||
|
|
|
@ -32,7 +32,7 @@ const float VOXEL_SIZE_SCALE = TREE_SCALE * 400.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;
|
||||||
const int MAX_TREE_SLICE_BYTES = 26;
|
const int MAX_TREE_SLICE_BYTES = 26;
|
||||||
const int MAX_VOXELS_PER_SYSTEM = 200000;
|
const int DEFAULT_MAX_VOXELS_PER_SYSTEM = 200000;
|
||||||
const int VERTICES_PER_VOXEL = 24; // 6 sides * 4 corners per side
|
const int VERTICES_PER_VOXEL = 24; // 6 sides * 4 corners per side
|
||||||
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // ???? xyz for each VERTICE_PER_VOXEL??
|
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; // ???? xyz for each VERTICE_PER_VOXEL??
|
||||||
const int INDICES_PER_VOXEL = 3 * 12; // 6 sides * 2 triangles per size * 3 vertices per triangle
|
const int INDICES_PER_VOXEL = 3 * 12; // 6 sides * 2 triangles per size * 3 vertices per triangle
|
||||||
|
|
Loading…
Reference in a new issue