2109 lines · 79.9 KB · C++
RawDownload
////  Cube.cpp//  interface////  Created by Philip on 12/31/12.//  Copyright (c) 2012 High Fidelity, Inc. All rights reserved.// #ifdef _WIN32#define _timeval_#define _USE_MATH_DEFINES#endif #include <cstring>#include <cmath>#include <iostream> // to load voxels from file#include <fstream> // to load voxels from file#include <pthread.h> #include <OctalCode.h>#include <PacketHeaders.h>#include <PerfStat.h>#include <SharedUtil.h>#include <NodeList.h>#include <NodeTypes.h> #include "Application.h"#include "CoverageMap.h"#include "CoverageMapV2.h"#include "InterfaceConfig.h"#include "Menu.h"#include "renderer/ProgramObject.h"#include "VoxelConstants.h"#include "VoxelSystem.h" float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7                             0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //8-15                             0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; // 16-23 GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,                              0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1,                              0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0,                              0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0,                              -1,0,0, +1,0,0, +1,0,0, -1,0,0,                              -1,0,0, +1,0,0, +1,0,0, -1,0,0 }; GLubyte identityIndices[] = { 0,2,1,    0,3,2,    // Z-                              8,9,13,   8,13,12,  // Y-                              16,23,19, 16,20,23, // X-                              17,18,22, 17,22,21, // X+                              10,11,15, 10,15,14, // Y+                              4,5,6,    4,6,7 };  // Z+ GLubyte identityIndicesTop[]    = {  2, 3, 7,  2, 7, 6 };GLubyte identityIndicesBottom[] = {  0, 1, 5,  0, 5, 4 };GLubyte identityIndicesLeft[]   = {  0, 7, 3,  0, 4, 7 };GLubyte identityIndicesRight[]  = {  1, 2, 6,  1, 6, 5 };GLubyte identityIndicesFront[]  = {  0, 2, 1,  0, 3, 2 };GLubyte identityIndicesBack[]   = {  4, 5, 6,  4, 6, 7 }; VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)    : NodeData(NULL),      _treeScale(treeScale),      _maxVoxels(maxVoxels),      _initialized(false) {     _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;    _writeRenderFullVBO = true;    _readRenderFullVBO = true;    _tree = new VoxelTree();    pthread_mutex_init(&_bufferWriteLock, NULL);    pthread_mutex_init(&_treeLock, NULL);     VoxelNode::addDeleteHook(this);    _abandonedVBOSlots = 0;    _falseColorizeBySource = false;    _dataSourceID = UNKNOWN_NODE_ID;    _voxelServerCount = 0;     _viewFrustum = Application::getInstance()->getViewFrustum();     connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));    connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));     _useVoxelShader = false;    _useByteNormals = false;    _useGlobalNormals = false;        _writeVoxelShaderData = NULL;    _readVoxelShaderData = NULL;     _readVerticesArray = NULL;    _writeVerticesArray = NULL;    _readColorsArray = NULL;    _writeColorsArray = NULL;    _writeVoxelDirtyArray = NULL;    _readVoxelDirtyArray = NULL; } void VoxelSystem::nodeDeleted(VoxelNode* node) {    if (node->isKnownBufferIndex() && (node->getVoxelSystem() == this)) {        freeBufferIndex(node->getBufferIndex());    }} // returns an available index, starts by reusing a previously freed index, but if there isn't one available// it will use the end of the VBO array and grow our accounting of that array.// and makes the index available for some other node to useglBufferIndex VoxelSystem::getNextBufferIndex() {    glBufferIndex output = GLBUFFER_INDEX_UNKNOWN;    // if there's a free index, use it...    if (_freeIndexes.size() > 0) {        output = _freeIndexes.back();        _freeIndexes.pop_back();    } else {        output = _voxelsInWriteArrays;        _voxelsInWriteArrays++;    }    return output;} // Doesn't actually clean up the VBOs for the index, but does release responsibility of the index from the VoxelNode, // and makes the index available for some other node to usevoid VoxelSystem::freeBufferIndex(glBufferIndex index) {    _freeIndexes.push_back(index);} // This will run through the list of _freeIndexes and reset their VBO array values to be "invisible".void VoxelSystem::clearFreeBufferIndexes() {    for (int i = 0; i < _freeIndexes.size(); i++) {        glBufferIndex nodeIndex = _freeIndexes[i];        glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX);        float voxelScale = 0;        _writeVoxelDirtyArray[nodeIndex] = true;        nodeColor color = {0, 0, 0, 0};        updateNodeInArrays(nodeIndex, startVertex, voxelScale, color);        _abandonedVBOSlots++;    }    _freeIndexes.clear();} VoxelSystem::~VoxelSystem() {    cleanupVoxelMemory();    delete _tree;    pthread_mutex_destroy(&_bufferWriteLock);    pthread_mutex_destroy(&_treeLock);     VoxelNode::removeDeleteHook(this);} void VoxelSystem::setUseByteNormals(bool useByteNormals) {    pthread_mutex_lock(&_bufferWriteLock);    bool wasInitialized = _initialized;    if (wasInitialized) {        clearAllNodesBufferIndex();        cleanupVoxelMemory();    }    _useByteNormals = useByteNormals;    if (wasInitialized) {        init();    }    pthread_mutex_unlock(&_bufferWriteLock);     if (wasInitialized) {        forceRedrawEntireTree();    }} void VoxelSystem::setUseGlobalNormals(bool useGlobalNormals) {    pthread_mutex_lock(&_bufferWriteLock);    bool wasInitialized = _initialized;    if (wasInitialized) {        clearAllNodesBufferIndex();        cleanupVoxelMemory();    }    _useGlobalNormals = useGlobalNormals;    if (wasInitialized) {        init();    }    pthread_mutex_unlock(&_bufferWriteLock);     if (wasInitialized) {        forceRedrawEntireTree();    }} void VoxelSystem::setMaxVoxels(int maxVoxels) {    pthread_mutex_lock(&_bufferWriteLock);    bool wasInitialized = _initialized;    if (wasInitialized) {        clearAllNodesBufferIndex();        cleanupVoxelMemory();    }    _maxVoxels = maxVoxels;    if (wasInitialized) {        init();    }    pthread_mutex_unlock(&_bufferWriteLock);     if (wasInitialized) {        forceRedrawEntireTree();    }} void VoxelSystem::setUseVoxelShader(bool useVoxelShader) {    pthread_mutex_lock(&_bufferWriteLock);    bool wasInitialized = _initialized;    if (wasInitialized) {        clearAllNodesBufferIndex();        cleanupVoxelMemory();    }    _useVoxelShader = useVoxelShader;    if (wasInitialized) {        init();    }    pthread_mutex_unlock(&_bufferWriteLock);     if (wasInitialized) {        forceRedrawEntireTree();    }} 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, &_vboColorsID);             if (!_useGlobalNormals) {                glDeleteBuffers(1, &_vboNormalsID);                glDeleteBuffers(1, &_vboIndicesID);            } else {                glDeleteBuffers(1, &_vboIndicesTop);                glDeleteBuffers(1, &_vboIndicesBottom);                glDeleteBuffers(1, &_vboIndicesLeft);                glDeleteBuffers(1, &_vboIndicesRight);                glDeleteBuffers(1, &_vboIndicesFront);                glDeleteBuffers(1, &_vboIndicesBack);            }                    delete[] _readVerticesArray;            delete[] _writeVerticesArray;            delete[] _readColorsArray;            delete[] _writeColorsArray;        }        delete[] _writeVoxelDirtyArray;        delete[] _readVoxelDirtyArray;    }    _initialized = false; // no longer initialized} void VoxelSystem::setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]) {    GLuint* indicesArray = new GLuint[INDICES_PER_FACE * _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_FACE;        GLuint* currentIndicesPos = indicesArray + voxelIndexOffset;        int startIndex = (n * GLOBAL_NORMALS_VERTICES_PER_VOXEL);         for (int i = 0; i < INDICES_PER_FACE; i++) {            // add indices for this side of the cube            currentIndicesPos[i] = startIndex + faceIdentityIndices[i];        }    }     glGenBuffers(1, &faceVBOID);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, faceVBOID);    glBufferData(GL_ELEMENT_ARRAY_BUFFER,                 INDICES_PER_FACE * sizeof(GLuint) * _maxVoxels,                 indicesArray, GL_STATIC_DRAW);    _memoryUsageVBO += INDICES_PER_FACE * sizeof(GLuint) * _maxVoxels;     // delete the indices and normals arrays that are no longer needed    delete[] indicesArray;} void VoxelSystem::initVoxelMemory() {    _initialMemoryUsageGPU = getFreeMemoryGPU();    _memoryUsageRAM = 0;    _memoryUsageVBO = 0; // our VBO allocations as we know them    if (_useVoxelShader) {        qDebug("Using Voxel Shader...\n");        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, sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW);        _memoryUsageVBO += sizeof(GLuint) * _maxVoxels;         glGenBuffers(1, &_vboVoxelsID);        glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);        glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW);        _memoryUsageVBO += _maxVoxels * sizeof(VoxelShaderVBOData);            // 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));        _memoryUsageRAM += (_maxVoxels * sizeof(bool));         _readVoxelDirtyArray = new bool[_maxVoxels];        memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));        _memoryUsageRAM += (_maxVoxels * sizeof(bool));         // prep the data structures for incoming voxel data        _writeVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];        _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);         _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];        _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);    } else {        if (_useGlobalNormals) {            // Global Normals mode uses a technique of not including normals on any voxel vertices, and instead            // rendering the voxel faces in 6 passes that use a global call to glNormal3f()            qDebug("Using Global Normals...\n");            setupFaceIndices(_vboIndicesTop,    identityIndicesTop);            setupFaceIndices(_vboIndicesBottom, identityIndicesBottom);            setupFaceIndices(_vboIndicesLeft,   identityIndicesLeft);            setupFaceIndices(_vboIndicesRight,  identityIndicesRight);            setupFaceIndices(_vboIndicesFront,  identityIndicesFront);            setupFaceIndices(_vboIndicesBack,   identityIndicesBack);        } else {            if (_useByteNormals) {                qDebug("Using Byte Normals...\n");                GLbyte* normalsArray = new GLbyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels];                GLbyte* 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] * CHAR_MAX);                    }                }                 // VBO for the normalsArray                glGenBuffers(1, &_vboNormalsID);                glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);                glBufferData(GL_ARRAY_BUFFER,                             VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels,                             normalsArray, GL_STATIC_DRAW);                _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLbyte) * _maxVoxels;                 // delete the indices and normals arrays that are no longer needed                delete[] normalsArray;            } else {                qDebug("Using Float Normals...\n");                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];                    }                }                            // 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);                _memoryUsageVBO += VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels;                 // delete the indices and normals arrays that are no longer needed                delete[] normalsArray;            }             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];                }            }             // 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);            _memoryUsageVBO += INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels;             // delete the indices and normals arrays that are no longer needed            delete[] indicesArray;         }                // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel        int vertexPointsPerVoxel = _useGlobalNormals ? GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL : VERTEX_POINTS_PER_VOXEL;        glGenBuffers(1, &_vboVerticesID);        glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);        glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);        _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLfloat) * _maxVoxels;         // VBO for colorsArray        glGenBuffers(1, &_vboColorsID);        glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);        glBufferData(GL_ARRAY_BUFFER, vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);        _memoryUsageVBO += vertexPointsPerVoxel * sizeof(GLubyte) * _maxVoxels;         // we will track individual dirty sections with these arrays of bools        _writeVoxelDirtyArray = new bool[_maxVoxels];        memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool));        _memoryUsageRAM += (sizeof(bool) * _maxVoxels);         _readVoxelDirtyArray = new bool[_maxVoxels];        memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool));        _memoryUsageRAM += (sizeof(bool) * _maxVoxels);         // prep the data structures for incoming voxel data        _writeVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];        _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);        _readVerticesArray = new GLfloat[vertexPointsPerVoxel * _maxVoxels];        _memoryUsageRAM += (sizeof(GLfloat) * vertexPointsPerVoxel * _maxVoxels);         _writeColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];        _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _maxVoxels);        _readColorsArray = new GLubyte[vertexPointsPerVoxel * _maxVoxels];        _memoryUsageRAM += (sizeof(GLubyte) * vertexPointsPerVoxel * _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) {    _tree->loadVoxelsFile(fileName, wantColorRandomizer);    setupNewVoxelsForDrawing();} void VoxelSystem::writeToSVOFile(const char* filename, VoxelNode* node) const {    _tree->writeToSVOFile(filename, node);} bool VoxelSystem::readFromSVOFile(const char* filename) {    bool result = _tree->readFromSVOFile(filename);    if (result) {        setupNewVoxelsForDrawing();    }    return result;} bool VoxelSystem::readFromSquareARGB32Pixels(const char *filename) {    bool result = _tree->readFromSquareARGB32Pixels(filename);    if (result) {        setupNewVoxelsForDrawing();    }    return result;} bool VoxelSystem::readFromSchematicFile(const char* filename) {    bool result = _tree->readFromSchematicFile(filename);    if (result) {        setupNewVoxelsForDrawing();    }    return result;}

Lines 1–500 of 2109.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t