From 78453402792d296f277574ae657759f6262fbb63 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 26 Sep 2013 16:26:49 -0700 Subject: [PATCH] menu cleanup, support for on the fly switching of maxVoxels and useVoxelShader --- interface/src/Application.cpp | 12 +- interface/src/Menu.cpp | 51 ++++- interface/src/Menu.h | 5 + interface/src/VoxelSystem.cpp | 313 ++++++++++++++------------ interface/src/VoxelSystem.h | 13 +- libraries/voxels/src/VoxelConstants.h | 2 +- 6 files changed, 237 insertions(+), 159 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b10ed430bf..1f231b9e2f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1521,7 +1521,6 @@ void Application::initDisplay() { } void Application::init() { - _voxels.init(); _sharedVoxelSystemViewFrustum.setPosition(glm::vec3(TREE_SCALE / 2.0f, TREE_SCALE / 2.0f, 3.0f * TREE_SCALE / 2.0f)); @@ -1573,9 +1572,13 @@ void Application::init() { if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) { _audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples()); } - 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()); _palette.init(_glWidget->width(), _glWidget->height()); @@ -2915,7 +2918,10 @@ void Application::displayStats() { std::stringstream voxelStats; 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()); voxelStats.str(""); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6f385c3e99..3fd9334830 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -48,7 +48,8 @@ Menu::Menu() : _frustumDrawMode(FRUSTUM_DRAW_MODE_ALL), _viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET), _voxelModeActionsGroup(NULL), - _voxelStatsDialog(NULL) + _voxelStatsDialog(NULL), + _maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM) { Application *appInstance = Application::getInstance(); @@ -249,7 +250,8 @@ Menu::Menu() : SLOT(setRenderVoxels(bool))); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader); + addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::UseVoxelShader, 0, + false, this, SLOT(switchVoxelShader())); QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options"); @@ -485,6 +487,7 @@ void Menu::loadSettings(QSettings* settings) { _gyroCameraSensitivity = loadSetting(settings, "gyroCameraSensitivity", 0.5f); _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); _fieldOfView = loadSetting(settings, "fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES); + _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); settings->beginGroup("View Frustum Offset Camera"); // 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("audioJitterBufferSamples", _audioJitterBufferSamples); settings->setValue("fieldOfView", _fieldOfView); + settings->setValue("maxVoxels", _maxVoxels); settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); @@ -755,9 +759,6 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); - QLineEdit* domainServerLineEdit = lineEditForDomainHostname(); - form->addRow("Domain server:", domainServerLineEdit); - QLineEdit* avatarURL = new QLineEdit(applicationInstance->getAvatar()->getVoxels()->getVoxelURL().toString()); avatarURL->setMinimumWidth(QLINE_MINIMUM_WIDTH); form->addRow("Avatar URL:", avatarURL); @@ -785,6 +786,13 @@ void Menu::editPreferences() { audioJitterBufferSamples->setMinimum(-10000); audioJitterBufferSamples->setValue(_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); dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); @@ -797,8 +805,6 @@ void Menu::editPreferences() { return; } - updateDSHostname(domainServerLineEdit->text()); - QUrl avatarVoxelURL(avatarURL->text()); applicationInstance->getAvatar()->getVoxels()->setVoxelURL(avatarVoxelURL); @@ -808,6 +814,8 @@ void Menu::editPreferences() { Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL); _gyroCameraSensitivity = gyroCameraSensitivity->value(); + _maxVoxels = maxVoxels->value(); + applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels); applicationInstance->getAvatar()->setLeanScale(leanScale->value()); @@ -1007,3 +1015,32 @@ void Menu::updateFrustumRenderModeAction() { 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 + + +} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a30fc4cdb0..332f89176c 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -54,6 +54,8 @@ public: FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; } ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } VoxelStatsDialog* getVoxelStatsDialog() const { return _voxelStatsDialog; } + int getMaxVoxels() const { return _maxVoxels; } + void handleViewFrustumOffsetKeyModifier(int key); @@ -78,6 +80,8 @@ private slots: void chooseVoxelPaintColor(); void runTests(); void resetSwatchColors(); + void displayGPUMemory(); + void switchVoxelShader(); private: static Menu* _instance; @@ -115,6 +119,7 @@ private: ViewFrustumOffset _viewFrustumOffset; QActionGroup* _voxelModeActionsGroup; VoxelStatsDialog* _voxelStatsDialog; + int _maxVoxels; }; namespace MenuOption { diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 759a2f178a..b430afdd10 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -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(importProgress(int)), SIGNAL(importProgress(int))); - - _voxelShaderInitialized = false; - _initializingVoxelShader = false; + + _useVoxelShader = false; _writeVoxelShaderData = NULL; _readVoxelShaderData = NULL; @@ -132,28 +131,7 @@ void VoxelSystem::clearFreeBufferIndexes() { } VoxelSystem::~VoxelSystem() { - if (_initialized) { - // 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; - } - + cleanupVoxelMemory(); delete _tree; pthread_mutex_destroy(&_bufferWriteLock); pthread_mutex_destroy(&_treeLock); @@ -161,43 +139,172 @@ VoxelSystem::~VoxelSystem() { VoxelNode::removeDeleteHook(this); } -bool VoxelSystem::getUseVoxelShader() { - bool useVoxelShader = false; //Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader); - - return useVoxelShader; +void VoxelSystem::setMaxVoxels(int maxVoxels) { + pthread_mutex_lock(&_bufferWriteLock); + bool wasInitialized = _initialized; + if (wasInitialized) { + cleanupVoxelMemory(); + } + _maxVoxels = maxVoxels; + if (wasInitialized) { + init(); + } + pthread_mutex_unlock(&_bufferWriteLock); } -void VoxelSystem::initVoxelShader() { - 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; +void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { + pthread_mutex_lock(&_bufferWriteLock); + bool wasInitialized = _initialized; + if (wasInitialized) { + cleanupVoxelMemory(); } + _useVoxelShader = useVoxelShader; + if (wasInitialized) { + init(); + } + pthread_mutex_unlock(&_bufferWriteLock); +} - // 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); +void VoxelSystem::cleanupVoxelMemory() { + if (_initialized) { + if (_useVoxelShader) { + // 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); - glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); - glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); + glGenBuffers(1, &_vboVoxelsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); + glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); - // delete the indices and normals arrays that are no longer needed - delete[] indicesArray; + // delete the indices and normals arrays that are no longer needed + delete[] indicesArray; - // 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)); + // 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 - _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; - _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; + // prep the data structures for incoming voxel data + _writeVoxelShaderData = 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) { @@ -457,7 +564,7 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { int segmentLength = (segmentEnd - segmentStart) + 1; - if (getUseVoxelShader()) { + if (_useVoxelShader) { GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); void* readDataAt = &_readVoxelShaderData[segmentStart]; void* writeDataAt = &_writeVoxelShaderData[segmentStart]; @@ -598,7 +705,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, float voxelScale, const nodeColor& color) { - if (getUseVoxelShader()) { + if (_useVoxelShader) { VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; writeVerticesAt->x = startVertex.x * TREE_SCALE; writeVerticesAt->y = startVertex.y * TREE_SCALE; @@ -647,89 +754,7 @@ void VoxelSystem::init() { _voxelsInReadArrays = 0; // VBO for the verticesArray - //initVoxelShader(); - - 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(); - } - } + initVoxelMemory(); _initialized = true; } @@ -801,7 +826,7 @@ void VoxelSystem::updateVBOs() { } void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { - if (getUseVoxelShader()) { + if (_useVoxelShader) { int segmentLength = (segmentEnd - segmentStart) + 1; GLintptr segmentStartAt = segmentStart * sizeof(VoxelShaderVBOData); GLsizeiptr segmentSizeBytes = segmentLength * sizeof(VoxelShaderVBOData); @@ -839,9 +864,9 @@ void VoxelSystem::render(bool texture) { 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(); @@ -1349,7 +1374,7 @@ public: duplicateVBOIndex(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; @@ -1364,7 +1389,7 @@ public: unsigned long expectedMax; - bool hasIndexFound[MAX_VOXELS_PER_SYSTEM]; + bool hasIndexFound[DEFAULT_MAX_VOXELS_PER_SYSTEM]; }; bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) { @@ -1439,7 +1464,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; 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]) { minInVBO = std::min(minInVBO,i); maxInVBO = std::max(maxInVBO,i); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index fe088ce042..7a44034590 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -40,7 +40,7 @@ struct VoxelShaderVBOData class VoxelSystem : public NodeData, public VoxelNodeDeleteHook, public NodeListHook { Q_OBJECT 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(); void setDataSourceID(int dataSourceID) { _dataSourceID = dataSourceID; } @@ -65,6 +65,10 @@ public: bool readFromSquareARGB32Pixels(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 getVoxelsColored(); long int getVoxelsBytesRead(); @@ -200,9 +204,10 @@ private: int _lastViewCullingElapsed; bool getUseVoxelShader(); - void initVoxelShader(); - bool _voxelShaderInitialized; - bool _initializingVoxelShader; + void initVoxelMemory(); + void cleanupVoxelMemory(); + + bool _useVoxelShader; 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 VoxelShaderVBOData* _writeVoxelShaderData; diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 1c6e6cd0e6..0e89ab9cdb 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -32,7 +32,7 @@ const float VOXEL_SIZE_SCALE = TREE_SCALE * 400.0f; const int NUMBER_OF_CHILDREN = 8; const int MAX_VOXEL_PACKET_SIZE = 1492; 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 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