2337 lines · 100.5 KB · C++
RawDownload
////  MetavoxelSystem.cpp//  interface/src////  Created by Andrzej Kapolka on 12/10/13.//  Copyright 2013 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL#include "InterfaceConfig.h" #include <QMutexLocker>#include <QOpenGLFramebufferObject>#include <QReadLocker>#include <QWriteLocker>#include <QThreadPool>#include <QtDebug> #include <glm/gtx/transform.hpp> #include <GeometryUtil.h>#include <SharedUtil.h> #include <MetavoxelMessages.h>#include <MetavoxelUtil.h>#include <PathUtils.h>#include <ScriptCache.h> #include "Application.h"#include "MetavoxelSystem.h"#include "renderer/Model.h"#include "renderer/RenderUtil.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation)REGISTER_META_OBJECT(SphereRenderer)REGISTER_META_OBJECT(CuboidRenderer)REGISTER_META_OBJECT(StaticModelRenderer)REGISTER_META_OBJECT(HeightfieldRenderer) MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate,        int minimumDelay, int maximumDelay, int bandwidthLimit) :    dropRate(dropRate),    repeatRate(repeatRate),    minimumDelay(minimumDelay),    maximumDelay(maximumDelay),    bandwidthLimit(bandwidthLimit) {}     MetavoxelSystem::~MetavoxelSystem() {    // kill the updater before we delete our network simulation objects    _updater->thread()->quit();    _updater->thread()->wait();    _updater = NULL;} void MetavoxelSystem::init() {    MetavoxelClientManager::init();        _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(        new BufferDataAttribute("voxelBuffer"));    _voxelBufferAttribute->setLODThresholdMultiplier(        AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier());            _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() +            "shaders/metavoxel_heightfield_base.vert");    _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() +        "shaders/metavoxel_heightfield_base.frag");    _baseHeightfieldProgram.link();        _baseHeightfieldProgram.bind();    _baseHeightfieldProgram.setUniformValue("heightMap", 0);    _baseHeightfieldProgram.setUniformValue("diffuseMap", 1);    _baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale");    _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale");    _baseHeightfieldProgram.release();        loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations);        _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() +        "shaders/metavoxel_heightfield_cursor.vert");    _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() +        "shaders/metavoxel_cursor.frag");    _heightfieldCursorProgram.link();        _heightfieldCursorProgram.bind();    _heightfieldCursorProgram.setUniformValue("heightMap", 0);    _heightfieldCursorProgram.release();        _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() +        "shaders/metavoxel_voxel_base.vert");    _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() +        "shaders/metavoxel_voxel_base.frag");    _baseVoxelProgram.link();        loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations);        _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() +        "shaders/metavoxel_voxel_cursor.vert");    _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() +        "shaders/metavoxel_cursor.frag");    _voxelCursorProgram.link();} MetavoxelLOD MetavoxelSystem::getLOD() {    QReadLocker locker(&_lodLock);    return _lod;} void MetavoxelSystem::setNetworkSimulation(const NetworkSimulation& simulation) {    QWriteLocker locker(&_networkSimulationLock);    _networkSimulation = simulation;} MetavoxelSystem::NetworkSimulation MetavoxelSystem::getNetworkSimulation() {    QReadLocker locker(&_networkSimulationLock);    return _networkSimulation;} class SimulateVisitor : public MetavoxelVisitor {public:        SimulateVisitor(float deltaTime, const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info); private:        float _deltaTime;}; SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(),        QVector<AttributePointer>(), lod),    _deltaTime(deltaTime) {} int SimulateVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue<        SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod);    return STOP_RECURSION;} void MetavoxelSystem::simulate(float deltaTime) {    // update the lod    {        QWriteLocker locker(&_lodLock);        const float DEFAULT_LOD_THRESHOLD = 0.01f;        _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), DEFAULT_LOD_THRESHOLD);    }     SimulateVisitor simulateVisitor(deltaTime, getLOD());    guideToAugmented(simulateVisitor);} class RenderVisitor : public MetavoxelVisitor {public:        RenderVisitor(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);}; RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(),        QVector<AttributePointer>(), lod) {} int RenderVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue<        SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod);    return STOP_RECURSION;} class HeightfieldPoint {public:    glm::vec3 vertex;    glm::vec2 textureCoord;}; const int SPLAT_COUNT = 4;const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; static const int EIGHT_BIT_MAXIMUM = 255;static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() {    // update the frustum    ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum();    _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(),        viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(),        viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight());       RenderVisitor renderVisitor(getLOD());    guideToAugmented(renderVisitor, true);        if (!_heightfieldBaseBatches.isEmpty()) {        glEnableClientState(GL_VERTEX_ARRAY);        glEnableClientState(GL_TEXTURE_COORD_ARRAY);            DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true);            glDisable(GL_BLEND);        glEnable(GL_CULL_FACE);        glEnable(GL_ALPHA_TEST);        glAlphaFunc(GL_EQUAL, 0.0f);                glColor4f(1.0f, 1.0f, 1.0f, 1.0f);                _baseHeightfieldProgram.bind();                foreach (const HeightfieldBaseLayerBatch& batch, _heightfieldBaseBatches) {            glPushMatrix();            glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z);            glm::vec3 axis = glm::axis(batch.rotation);            glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z);            glScalef(batch.scale.x, batch.scale.y, batch.scale.z);                        batch.vertexBuffer->bind();            batch.indexBuffer->bind();                    HeightfieldPoint* point = 0;            glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);            glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);                        glBindTexture(GL_TEXTURE_2D, batch.heightTextureID);                        _baseHeightfieldProgram.setUniform(_baseHeightScaleLocation, batch.heightScale);            _baseHeightfieldProgram.setUniform(_baseColorScaleLocation, batch.colorScale);                            glActiveTexture(GL_TEXTURE1);            glBindTexture(GL_TEXTURE_2D, batch.colorTextureID);                        glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);                        glBindTexture(GL_TEXTURE_2D, 0);                        glActiveTexture(GL_TEXTURE0);            glBindTexture(GL_TEXTURE_2D, 0);                    batch.vertexBuffer->release();            batch.indexBuffer->release();                    glPopMatrix();        }                DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false);                _baseHeightfieldProgram.release();                glDisable(GL_ALPHA_TEST);        glEnable(GL_BLEND);                if (!_heightfieldSplatBatches.isEmpty()) {            glDepthFunc(GL_LEQUAL);            glDepthMask(false);            glEnable(GL_POLYGON_OFFSET_FILL);            glPolygonOffset(-1.0f, -1.0f);                        _splatHeightfieldProgram.bind();                        foreach (const HeightfieldSplatBatch& batch, _heightfieldSplatBatches) {                glPushMatrix();                glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z);                glm::vec3 axis = glm::axis(batch.rotation);                glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z);                glScalef(batch.scale.x, batch.scale.y, batch.scale.z);                                batch.vertexBuffer->bind();                batch.indexBuffer->bind();                            HeightfieldPoint* point = 0;                glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);                glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);                                glBindTexture(GL_TEXTURE_2D, batch.heightTextureID);                                _splatHeightfieldProgram.setUniformValue(_splatHeightfieldLocations.heightScale,                    batch.heightScale.x, batch.heightScale.y);                _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.textureScale, batch.textureScale);                _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureOffset, batch.splatTextureOffset);                                const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;                _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesS, batch.splatTextureScalesS);                _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesT, batch.splatTextureScalesT);                _splatHeightfieldProgram.setUniformValue(                    _splatHeightfieldLocations.textureValueMinima,                    (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,                    (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,                    (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,                    (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);                _splatHeightfieldProgram.setUniformValue(                    _splatHeightfieldLocations.textureValueMaxima,                    (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,                    (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,                    (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,                    (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);                                    glActiveTexture(GL_TEXTURE1);                glBindTexture(GL_TEXTURE_2D, batch.materialTextureID);                                for (int i = 0; i < SPLAT_COUNT; i++) {                    glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);                    glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]);                }                                glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);                             for (int i = 0; i < SPLAT_COUNT; i++) {                    glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);                    glBindTexture(GL_TEXTURE_2D, 0);                }                            glActiveTexture(GL_TEXTURE1);                glBindTexture(GL_TEXTURE_2D, 0);                            glActiveTexture(GL_TEXTURE0);                glBindTexture(GL_TEXTURE_2D, 0);                            batch.vertexBuffer->release();                batch.indexBuffer->release();                                glPopMatrix();               }                        _splatHeightfieldProgram.release();                        glDisable(GL_POLYGON_OFFSET_FILL);            glDepthMask(true);            glDepthFunc(GL_LESS);                        _heightfieldSplatBatches.clear();        }                glDisable(GL_CULL_FACE);                glDisableClientState(GL_TEXTURE_COORD_ARRAY);            glDisableClientState(GL_VERTEX_ARRAY);                  _heightfieldBaseBatches.clear();    }        if (!_voxelBaseBatches.isEmpty()) {        DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true);            glEnableClientState(GL_VERTEX_ARRAY);        glDisable(GL_BLEND);        glEnable(GL_CULL_FACE);        glEnable(GL_ALPHA_TEST);        glAlphaFunc(GL_EQUAL, 0.0f);                glColor4f(1.0f, 1.0f, 1.0f, 1.0f);                glEnableClientState(GL_COLOR_ARRAY);        glEnableClientState(GL_NORMAL_ARRAY);                    _baseVoxelProgram.bind();                foreach (const VoxelBatch& batch, _voxelBaseBatches) {            batch.vertexBuffer->bind();            batch.indexBuffer->bind();                        VoxelPoint* point = 0;            glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);            glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);            glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);                        glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);                        batch.vertexBuffer->release();            batch.indexBuffer->release();        }                _baseVoxelProgram.release();            glDisable(GL_ALPHA_TEST);        glEnable(GL_BLEND);                    DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false);                if (!_voxelSplatBatches.isEmpty()) {            glDepthFunc(GL_LEQUAL);            glDepthMask(false);            glEnable(GL_POLYGON_OFFSET_FILL);            glPolygonOffset(-1.0f, -1.0f);                        _splatVoxelProgram.bind();                        _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materials);            _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materialWeights);                        foreach (const VoxelSplatBatch& batch, _voxelSplatBatches) {                batch.vertexBuffer->bind();                batch.indexBuffer->bind();                                VoxelPoint* point = 0;                glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);                glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);                glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);                                _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materials,                    GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint));                _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materialWeights,                    GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint));                                const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;                _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesS, batch.splatTextureScalesS);                _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesT, batch.splatTextureScalesT);                _splatVoxelProgram.setUniformValue(                    _splatVoxelLocations.textureValueMinima,                    (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,                    (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,                    (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,                    (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);                _splatVoxelProgram.setUniformValue(                    _splatVoxelLocations.textureValueMaxima,                    (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,                    (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,                    (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,                    (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);                                for (int i = 0; i < SPLAT_COUNT; i++) {                    glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);                    glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]);                }                                glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0);                                for (int i = 0; i < SPLAT_COUNT; i++) {                    glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);                    glBindTexture(GL_TEXTURE_2D, 0);                }                            glActiveTexture(GL_TEXTURE0);                        batch.vertexBuffer->release();                batch.indexBuffer->release();            }                        glDisable(GL_POLYGON_OFFSET_FILL);            glDepthMask(true);            glDepthFunc(GL_LESS);                        _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materials);            _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materialWeights);                        _voxelSplatBatches.clear();        }                glDisableClientState(GL_VERTEX_ARRAY);        glDisableClientState(GL_COLOR_ARRAY);        glDisableClientState(GL_NORMAL_ARRAY);        glDisable(GL_CULL_FACE);                _voxelBaseBatches.clear();    }        if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) {        DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true);                glEnableClientState(GL_VERTEX_ARRAY);                glColor4f(1.0f, 1.0f, 1.0f, 1.0f);        glNormal3f(0.0f, 1.0f, 0.0f);                Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram();                foreach (const HermiteBatch& batch, _hermiteBatches) {            batch.vertexBuffer->bind();                        glVertexPointer(3, GL_FLOAT, 0, 0);                        glDrawArrays(GL_LINES, 0, batch.vertexCount);                        batch.vertexBuffer->release();        }                Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram();                glDisableClientState(GL_VERTEX_ARRAY);                DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false);    }    _hermiteBatches.clear();        // give external parties a chance to join in    emit rendering();} void MetavoxelSystem::refreshVoxelData() {    foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {        if (node->getType() == NodeType::MetavoxelServer) {

Lines 1–500 of 2337.