685 lines · 23.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 <QMutexLocker>#include <QReadLocker>#include <QWriteLocker>#include <QtDebug> #include <glm/gtx/transform.hpp> #include <SharedUtil.h> #include <MetavoxelUtil.h>#include <ScriptCache.h> #include "Application.h"#include "MetavoxelSystem.h"#include "renderer/Model.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation)REGISTER_META_OBJECT(SphereRenderer)REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType<BufferPointVector>(); void MetavoxelSystem::init() {    MetavoxelClientManager::init();    DefaultMetavoxelRendererImplementation::init();    _pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new BufferDataAttribute("pointBuffer"));    _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(        new BufferDataAttribute("heightfieldBuffer"));} MetavoxelLOD MetavoxelSystem::getLOD() {    QReadLocker locker(&_lodLock);    return _lod;} 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    {        // the LOD threshold is temporarily tied to the avatar LOD parameter        QWriteLocker locker(&_lodLock);        const float BASE_LOD_THRESHOLD = 0.01f;        _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(),            BASE_LOD_THRESHOLD * Menu::getInstance()->getAvatarLODDistanceMultiplier());    }     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;} void MetavoxelSystem::render() {    RenderVisitor renderVisitor(getLOD());    guideToAugmented(renderVisitor);} MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) {    return new MetavoxelSystemClient(node, _updater);} void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor) {    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) {                client->getAugmentedData().guide(visitor);            }        }    }} MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) :    MetavoxelClient(node, updater) {} void MetavoxelSystemClient::setAugmentedData(const MetavoxelData& data) {    QWriteLocker locker(&_augmentedDataLock);    _augmentedData = data;} MetavoxelData MetavoxelSystemClient::getAugmentedData() {    QReadLocker locker(&_augmentedDataLock);    return _augmentedData;} int MetavoxelSystemClient::parseData(const QByteArray& packet) {    // process through sequencer    QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet));    Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::METAVOXELS).updateValue(packet.size());    return packet.size();} class AugmentVisitor : public MetavoxelVisitor {public:        AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData);        virtual int visit(MetavoxelInfo& info); private:        const MetavoxelData& _previousData;}; AugmentVisitor::AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(),        QVector<AttributePointer>(), lod),    _previousData(previousData) {} int AugmentVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue<        SharedObjectPointer>().data())->getImplementation()->augment(*_data, _previousData, info, _lod);    return STOP_RECURSION;} class Augmenter : public QRunnable {public:        Augmenter(const SharedNodePointer& node, const MetavoxelData& data,        const MetavoxelData& previousData, const MetavoxelLOD& lod);        virtual void run(); private:        QWeakPointer<Node> _node;    MetavoxelData _data;    MetavoxelData _previousData;    MetavoxelLOD _lod;}; Augmenter::Augmenter(const SharedNodePointer& node, const MetavoxelData& data,        const MetavoxelData& previousData, const MetavoxelLOD& lod) :    _node(node),    _data(data),    _previousData(previousData),    _lod(lod) {} void Augmenter::run() {    SharedNodePointer node = _node;    if (!node) {        return;    }    AugmentVisitor visitor(_lod, _previousData);    _data.guide(visitor);    QMutexLocker locker(&node->getMutex());    QMetaObject::invokeMethod(node->getLinkedData(), "setAugmentedData", Q_ARG(const MetavoxelData&, _data));} void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) {    MetavoxelClient::dataChanged(oldData);    QThreadPool::globalInstance()->start(new Augmenter(_node, _data, getAugmentedData(), _remoteDataLOD));} void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {    NodeList::getInstance()->writeDatagram(data, _node);    Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size());} BufferData::~BufferData() {} PointBuffer::PointBuffer(const BufferPointVector& points) :    _points(points) {} void PointBuffer::render() {    // initialize buffer, etc. on first render    if (!_buffer.isCreated()) {        _buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);        _buffer.create();        _buffer.bind();        _pointCount = _points.size();        _buffer.allocate(_points.constData(), _pointCount * sizeof(BufferPoint));        _points.clear();        _buffer.release();    }    if (_pointCount == 0) {        return;    }    _buffer.bind();        BufferPoint* point = 0;    glVertexPointer(4, GL_FLOAT, sizeof(BufferPoint), &point->vertex);    glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(BufferPoint), &point->color);    glNormalPointer(GL_BYTE, sizeof(BufferPoint), &point->normal);        glDrawArrays(GL_POINTS, 0, _pointCount);        _buffer.release();} HeightfieldBuffer::HeightfieldBuffer(const QByteArray& height, const QByteArray& color, const QByteArray& normal) :    _height(height),    _color(color),    _normal(normal),    _heightTexture(QOpenGLTexture::Target2D),    _colorTexture(QOpenGLTexture::Target2D),    _normalTexture(QOpenGLTexture::Target2D) {} void HeightfieldBuffer::render() {    // initialize textures, etc. on first render    if (!_heightTexture.isCreated()) {        int heightSize = glm::sqrt(_height.size());        _heightTexture.setSize(heightSize, heightSize);        _heightTexture.setFormat(QOpenGLTexture::LuminanceFormat);        _heightTexture.allocateStorage();        _heightTexture.setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8, _height.data());        _height.clear();                int colorSize = glm::sqrt(_color.size() / 3);        _colorTexture.setSize(colorSize, colorSize);        _colorTexture.setFormat(QOpenGLTexture::RGBFormat);        _colorTexture.allocateStorage();        _colorTexture.setData(QOpenGLTexture::BGR, QOpenGLTexture::UInt8, _color.data());        _color.clear();                int normalSize = glm::sqrt(_normal.size() / 3);        _normalTexture.setSize(normalSize, normalSize);        _normalTexture.setFormat(QOpenGLTexture::RGBFormat);        _normalTexture.allocateStorage();        _normalTexture.setData(QOpenGLTexture::BGR, QOpenGLTexture::UInt8, _normal.data());        _normal.clear();    }    } BufferDataAttribute::BufferDataAttribute(const QString& name) :    InlineAttribute<BufferDataPointer>(name) {} bool BufferDataAttribute::merge(void*& parent, void* children[], bool postRead) const {    BufferDataPointer firstChild = decodeInline<BufferDataPointer>(children[0]);    for (int i = 1; i < MERGE_COUNT; i++) {        if (firstChild != decodeInline<BufferDataPointer>(children[i])) {            *(BufferDataPointer*)&parent = _defaultValue;            return false;        }    }    *(BufferDataPointer*)&parent = firstChild;    return true;} void DefaultMetavoxelRendererImplementation::init() {    if (!_pointProgram.isLinked()) {        _pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert");        _pointProgram.link();               _pointProgram.bind();        _pointScaleLocation = _pointProgram.uniformLocation("pointScale");        _pointProgram.release();                _heightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/metavoxel_heightfield.vert");        _heightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/metavoxel_heightfield.frag");        _heightfieldProgram.link();    }} DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {} class PointAugmentVisitor : public MetavoxelVisitor {public:     PointAugmentVisitor(const MetavoxelLOD& lod);        virtual void prepare(MetavoxelData* data);    virtual int visit(MetavoxelInfo& info);    virtual bool postVisit(MetavoxelInfo& info); private:        BufferPointVector _points;    float _pointLeafSize;}; PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<        AttributeRegistry::getInstance()->getNormalAttribute(), QVector<AttributePointer>() <<            Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod) {} const int ALPHA_RENDER_THRESHOLD = 0; void PointAugmentVisitor::prepare(MetavoxelData* data) {    MetavoxelVisitor::prepare(data);    const float MAX_POINT_LEAF_SIZE = 64.0f;    _pointLeafSize = qMin(data->getSize(), MAX_POINT_LEAF_SIZE);} int PointAugmentVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return (info.size > _pointLeafSize) ? DEFAULT_ORDER : (DEFAULT_ORDER | ALL_NODES_REST);        }    QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();    quint8 alpha = qAlpha(color);    if (alpha > ALPHA_RENDER_THRESHOLD) {        QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();        BufferPoint point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),            { quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)) },             { quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };        _points.append(point);    }    if (info.size >= _pointLeafSize) {           BufferPointVector swapPoints;        _points.swap(swapPoints);        info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(            new PointBuffer(swapPoints))));    }    return STOP_RECURSION;} bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) {    if (info.size != _pointLeafSize) {        return false;    }    BufferPointVector swapPoints;    _points.swap(swapPoints);    info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(        new PointBuffer(swapPoints))));    return true;} class HeightfieldAugmentVisitor : public MetavoxelVisitor {public:     HeightfieldAugmentVisitor(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);}; HeightfieldAugmentVisitor::HeightfieldAugmentVisitor(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<        AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>() <<            Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod) {} int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) {    return STOP_RECURSION;} void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous,        MetavoxelInfo& info, const MetavoxelLOD& lod) {    // copy the previous buffers    MetavoxelData expandedPrevious = previous;    while (expandedPrevious.getSize() < data.getSize()) {        expandedPrevious.expand();    }    const AttributePointer& pointBufferAttribute = Application::getInstance()->getMetavoxels()->getPointBufferAttribute();    MetavoxelNode* root = expandedPrevious.getRoot(pointBufferAttribute);    if (root) {        data.setRoot(pointBufferAttribute, root);        root->incrementReferenceCount();    }        PointAugmentVisitor visitor(lod);    data.guideToDifferent(expandedPrevious, visitor);        } class SpannerSimulateVisitor : public SpannerVisitor {public:        SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod);        virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); private:        float _deltaTime;}; SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),        QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod),    _deltaTime(deltaTime) {} bool SpannerSimulateVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {    spanner->getRenderer()->simulate(_deltaTime);    return true;} void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime,        MetavoxelInfo& info, const MetavoxelLOD& lod) {    SpannerSimulateVisitor spannerSimulateVisitor(deltaTime, lod);    data.guide(spannerSimulateVisitor);} class SpannerRenderVisitor : public SpannerVisitor {public:        SpannerRenderVisitor(const MetavoxelLOD& lod);        virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);}; SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),        QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(),        lod, encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) {} bool SpannerRenderVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {    spanner->getRenderer()->render(1.0f, SpannerRenderer::DEFAULT_MODE, clipMinimum, clipSize);    return true;} class BufferRenderVisitor : public MetavoxelVisitor {public:        BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info); private:        int _order;}; BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << attribute, QVector<AttributePointer>(), lod),    _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) {} int BufferRenderVisitor::visit(MetavoxelInfo& info) {    BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>();    if (buffer) {        buffer->render();    }    return info.isLeaf ? STOP_RECURSION : _order;}

Lines 1–500 of 685.