2302 lines · 99.7 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 <SharedUtil.h> #include <MetavoxelMessages.h>#include <MetavoxelUtil.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();    DefaultMetavoxelRendererImplementation::init();        _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(        new BufferDataAttribute("voxelBuffer"));    _voxelBufferAttribute->setLODThresholdMultiplier(        AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier());} 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);            Application::getInstance()->getTextureCache()->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);                DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();                foreach (const HeightfieldBaseBatch& 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);                        DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniform(                DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), batch.heightScale);            DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniform(                DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), 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);                    glPopMatrix();        }                Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);                DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().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);                        DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind();            const DefaultMetavoxelRendererImplementation::SplatLocations& locations =                DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations();                            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);                                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(                    locations.heightScale, batch.heightScale.x, batch.heightScale.y);                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(                    locations.textureScale, batch.textureScale);                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(locations.splatTextureOffset,                    batch.splatTextureOffset);                                const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(                    locations.splatTextureScalesS, batch.splatTextureScalesS);                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniform(                    locations.splatTextureScalesT, batch.splatTextureScalesT);                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(                    locations.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);                DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(                    locations.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);                            glPopMatrix();               }                        DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().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();    }        // 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) {            QMutexLocker locker(&node->getMutex());            MetavoxelSystemClient* client = static_cast<MetavoxelSystemClient*>(node->getLinkedData());            if (client) {                QMetaObject::invokeMethod(client, "refreshVoxelData");            }        }    }} class RayVoxelIntersectionVisitor : public RayIntersectionVisitor {public:        float intersectionDistance;        RayVoxelIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info, float distance);}; RayVoxelIntersectionVisitor::RayVoxelIntersectionVisitor(const glm::vec3& origin,        const glm::vec3& direction, const MetavoxelLOD& lod) :    RayIntersectionVisitor(origin, direction, QVector<AttributePointer>() <<        Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), QVector<AttributePointer>(), lod),    intersectionDistance(FLT_MAX) {} int RayVoxelIntersectionVisitor::visit(MetavoxelInfo& info, float distance) {    if (!info.isLeaf) {        return _order;    }    const VoxelBuffer* buffer = static_cast<VoxelBuffer*>(        info.inputValues.at(0).getInlineValue<BufferDataPointer>().data());    if (!buffer) {        return STOP_RECURSION;    }    glm::vec3 entry = ((_origin + distance * _direction) - info.minimum) / info.size;    if (buffer->findFirstRayIntersection(entry, _origin, _direction, intersectionDistance)) {        return SHORT_CIRCUIT;    }    return STOP_RECURSION;} bool MetavoxelSystem::findFirstRayVoxelIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) {    RayVoxelIntersectionVisitor visitor(origin, direction, getLOD());    guideToAugmented(visitor);    if (visitor.intersectionDistance == FLT_MAX) {        return false;    }    distance = visitor.intersectionDistance;    return true;} void MetavoxelSystem::paintHeightfieldColor(const glm::vec3& position, float radius, const QColor& color) {    MetavoxelEditMessage edit = { QVariant::fromValue(PaintHeightfieldMaterialEdit(position, radius, SharedObjectPointer(), color)) };    applyEdit(edit, true);} void MetavoxelSystem::paintHeightfieldMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material) {    MetavoxelEditMessage edit = { QVariant::fromValue(PaintHeightfieldMaterialEdit(position, radius, material)) };    applyMaterialEdit(edit, true);} void MetavoxelSystem::paintVoxelColor(const glm::vec3& position, float radius, const QColor& color) {    MetavoxelEditMessage edit = { QVariant::fromValue(PaintVoxelMaterialEdit(position, radius, SharedObjectPointer(), color)) };    applyEdit(edit, true);} void MetavoxelSystem::paintVoxelMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material) {    MetavoxelEditMessage edit = { QVariant::fromValue(PaintVoxelMaterialEdit(position, radius, material)) };    applyMaterialEdit(edit, true);} void MetavoxelSystem::setVoxelColor(const SharedObjectPointer& spanner, const QColor& color) {    MetavoxelEditMessage edit = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, SharedObjectPointer(), color)) };    applyEdit(edit, true);} void MetavoxelSystem::setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material) {    MetavoxelEditMessage edit = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, material)) };    applyMaterialEdit(edit, true);} class SpannerCursorRenderVisitor : public SpannerVisitor {public:        SpannerCursorRenderVisitor(const Box& bounds);        virtual bool visit(Spanner* spanner);        virtual int visit(MetavoxelInfo& info); private:        Box _bounds;}; SpannerCursorRenderVisitor::SpannerCursorRenderVisitor(const Box& bounds) :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute()),    _bounds(bounds) {} bool SpannerCursorRenderVisitor::visit(Spanner* spanner) {    if (spanner->isHeightfield()) {        spanner->getRenderer()->render(true);    }    return true;} int SpannerCursorRenderVisitor::visit(MetavoxelInfo& info) {    return info.getBounds().intersects(_bounds) ? SpannerVisitor::visit(info) : STOP_RECURSION;} void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) {    glDepthFunc(GL_LEQUAL);    glEnable(GL_CULL_FACE);    glEnable(GL_POLYGON_OFFSET_FILL);    glPolygonOffset(-1.0f, -1.0f);        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);        glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_TEXTURE_COORD_ARRAY);        DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind();        glActiveTexture(GL_TEXTURE4);    float scale = 1.0f / radius;    glm::vec4 sCoefficients(scale, 0.0f, 0.0f, -scale * position.x);    glm::vec4 tCoefficients(0.0f, 0.0f, scale, -scale * position.z);    glm::vec4 rCoefficients(0.0f, 0.0f, 0.0f, 0.0f);    glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients);    glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients);    glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&rCoefficients);    glActiveTexture(GL_TEXTURE0);        glm::vec3 extents(radius, radius, radius);    SpannerCursorRenderVisitor visitor(Box(position - extents, position + extents));    guide(visitor);        DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();        glDisableClientState(GL_TEXTURE_COORD_ARRAY);    glDisableClientState(GL_VERTEX_ARRAY);        glDisable(GL_POLYGON_OFFSET_FILL);    glDisable(GL_CULL_FACE);    glDepthFunc(GL_LESS);} class BufferCursorRenderVisitor : public MetavoxelVisitor {public:        BufferCursorRenderVisitor(const AttributePointer& attribute, const Box& bounds);     virtual int visit(MetavoxelInfo& info); private:        Box _bounds;}; BufferCursorRenderVisitor::BufferCursorRenderVisitor(const AttributePointer& attribute, const Box& bounds) :    MetavoxelVisitor(QVector<AttributePointer>() << attribute),    _bounds(bounds) {} int BufferCursorRenderVisitor::visit(MetavoxelInfo& info) {    if (!info.getBounds().intersects(_bounds)) {        return STOP_RECURSION;    }    BufferData* buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>().data();    if (buffer) {        buffer->render(true);    }    return info.isLeaf ? STOP_RECURSION : DEFAULT_ORDER;} void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) {    glDepthFunc(GL_LEQUAL);    glEnable(GL_CULL_FACE);    glEnable(GL_POLYGON_OFFSET_FILL);

Lines 1–500 of 2302.