599 lines · 20.4 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 <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(SphereRenderer)REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType<BufferPointVector>(); ProgramObject MetavoxelSystem::_program;int MetavoxelSystem::_pointScaleLocation; void MetavoxelSystem::init() {    MetavoxelClientManager::init();        if (!_program.isLinked()) {        _program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert");        _program.link();               _program.bind();        _pointScaleLocation = _program.uniformLocation("pointScale");        _program.release();    }    _pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new PointBufferAttribute());} MetavoxelLOD MetavoxelSystem::getLOD() const {    // the LOD threshold is temporarily tied to the avatar LOD parameter    const float BASE_LOD_THRESHOLD = 0.01f;    return MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(),        BASE_LOD_THRESHOLD * Menu::getInstance()->getAvatarLODDistanceMultiplier());} class SpannerSimulateVisitor : public SpannerVisitor {public:        SpannerSimulateVisitor(float deltaTime);        virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); private:        float _deltaTime;}; SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime) :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),        QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(),            Application::getInstance()->getMetavoxels()->getLOD()),    _deltaTime(deltaTime) {} bool SpannerSimulateVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) {    spanner->getRenderer()->simulate(_deltaTime);    return true;} void MetavoxelSystem::simulate(float deltaTime) {    // update the clients    update();        SpannerSimulateVisitor spannerSimulateVisitor(deltaTime);    guide(spannerSimulateVisitor);} class PointBufferRenderVisitor : public MetavoxelVisitor {public:        PointBufferRenderVisitor();        virtual int visit(MetavoxelInfo& info); private:        int _order;}; PointBufferRenderVisitor::PointBufferRenderVisitor() :    MetavoxelVisitor(QVector<AttributePointer>() << Application::getInstance()->getMetavoxels()->getPointBufferAttribute(),        QVector<AttributePointer>(), Application::getInstance()->getMetavoxels()->getLOD()),    _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) {} int PointBufferRenderVisitor::visit(MetavoxelInfo& info) {    PointBufferPointer buffer = info.inputValues.at(0).getInlineValue<PointBufferPointer>();    if (buffer) {        buffer->render(1000);    }    if (info.isLeaf) {        return STOP_RECURSION;    }    return _order;} class SpannerRenderVisitor : public SpannerVisitor {public:        SpannerRenderVisitor();        virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);}; SpannerRenderVisitor::SpannerRenderVisitor() :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),        QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannerMaskAttribute(),        QVector<AttributePointer>(), QVector<AttributePointer>(), Application::getInstance()->getMetavoxels()->getLOD(),        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;} void MetavoxelSystem::render() {    int viewport[4];    glGetIntegerv(GL_VIEWPORT, viewport);    const int VIEWPORT_WIDTH_INDEX = 2;    const int VIEWPORT_HEIGHT_INDEX = 3;    float viewportWidth = viewport[VIEWPORT_WIDTH_INDEX];    float viewportHeight = viewport[VIEWPORT_HEIGHT_INDEX];    float viewportDiagonal = sqrtf(viewportWidth*viewportWidth + viewportHeight*viewportHeight);    float worldDiagonal = glm::distance(Application::getInstance()->getViewFrustum()->getNearBottomLeft(),        Application::getInstance()->getViewFrustum()->getNearTopRight());     _program.bind();    _program.setUniformValue(_pointScaleLocation, viewportDiagonal *        Application::getInstance()->getViewFrustum()->getNearClip() / worldDiagonal);            glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_COLOR_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);     glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);     glDisable(GL_BLEND);     //PointBufferRenderVisitor pointBufferRenderVisitor;    //guide(pointBufferRenderVisitor);        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->render();            }        }    }        glEnable(GL_BLEND);        glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);        glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_COLOR_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);        _program.release();        SpannerRenderVisitor spannerRenderVisitor;    guide(spannerRenderVisitor);} MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) {    return new MetavoxelSystemClient(node, this);} void MetavoxelSystem::updateClient(MetavoxelClient* client) {    MetavoxelClientManager::updateClient(client);} MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelSystem* system) :    MetavoxelClient(node, system),    _pointCount(0) {        _buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);    _buffer.create();} void MetavoxelSystemClient::render() {    _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();} void MetavoxelSystemClient::setPoints(const BufferPointVector& points) {    qint64 now = QDateTime::currentMSecsSinceEpoch();    _buffer.bind();    _buffer.allocate(points.constData(), points.size() * sizeof(BufferPoint));    _buffer.release();    _pointCount = points.size();    qDebug() << "upload" << (QDateTime::currentMSecsSinceEpoch() - now);    qDebug() << _pointCount;    } 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 BufferBuilder : public MetavoxelVisitor {public:     BufferBuilder(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);    virtual bool postVisit(MetavoxelInfo& info); private:        QVector<BufferPointVectorPair> _depthPoints;}; BufferBuilder::BufferBuilder(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<        AttributeRegistry::getInstance()->getNormalAttribute() <<            Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), QVector<AttributePointer>() <<                Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod) {} const int ALPHA_RENDER_THRESHOLD = 0; const int BUFFER_LEVELS = 5;const int LAST_BUFFER_LEVEL = BUFFER_LEVELS - 1; int BufferBuilder::visit(MetavoxelInfo& info) {    if (info.inputValues.at(2).getInlineValue<PointBufferPointer>()) {        info.outputValues[0] = AttributeValue(_outputs.at(0));    }    if (_depth >= _depthPoints.size()) {        _depthPoints.resize(_depth + 1);    }    QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();    quint8 alpha = qAlpha(color);    if (alpha <= ALPHA_RENDER_THRESHOLD) {        return info.isLeaf ? STOP_RECURSION : DEFAULT_ORDER;    }    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)) } };    if (info.isLeaf) {        _depthPoints[_depth].first.append(point);        return STOP_RECURSION;    }    _depthPoints[_depth].second.append(point);    return DEFAULT_ORDER | ((_depth % BUFFER_LEVELS) == LAST_BUFFER_LEVEL ? 0 : ALL_NODES);} bool BufferBuilder::postVisit(MetavoxelInfo& info) {    if (_depth % BUFFER_LEVELS != 0) {        return false;    }    QVector<int> offsets;    offsets.append(0);    int leafCount = 0;    int totalPoints = 0;    int lastDepth = qMin(_depth + BUFFER_LEVELS, _depthPoints.size());    for (int i = _depth; i < lastDepth; i++) {        const BufferPointVectorPair& pair = _depthPoints.at(i);        offsets.append(totalPoints += ((leafCount += pair.first.size()) + pair.second.size()));    }    QOpenGLBuffer buffer;    buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);    buffer.create();    buffer.bind();    buffer.allocate(totalPoints * sizeof(BufferPoint));    int offset = 0;    for (int i = _depth; i < lastDepth; i++) {        // write the internal nodes from the current level        BufferPointVector& internal = _depthPoints[i].second;        int length = internal.size() * sizeof(BufferPoint);        buffer.write(offset, internal.constData(), length);        offset += length;        internal.clear();                // and the leaves from the top down        for (int j = _depth; j <= i; j++) {            const BufferPointVector& leaves = _depthPoints.at(j).first;            length = leaves.size() * sizeof(BufferPoint);            buffer.write(offset, leaves.constData(), length);            offset += length;        }    }    // clear the leaves now that we're done with them    for (int i = _depth; i < lastDepth; i++) {        _depthPoints[i].first.clear();    }    buffer.release();    info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(PointBufferPointer(        new PointBuffer(buffer, offsets, leafCount))));    return true;} class PointCollector : public MetavoxelVisitor {public:        QVector<BufferPoint> points;        PointCollector(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);}; PointCollector::PointCollector(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<        AttributeRegistry::getInstance()->getNormalAttribute(), QVector<AttributePointer>(), lod) {} int PointCollector::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();    quint8 alpha = qAlpha(color);    if (alpha <= ALPHA_RENDER_THRESHOLD) {        return STOP_RECURSION;    }    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);    return STOP_RECURSION;} /// Builds a point buffer.class PointBufferBuilder : public QRunnable {public:        PointBufferBuilder(const SharedNodePointer& node, const MetavoxelData& data, const MetavoxelLOD& lod);        virtual void run(); private:        QWeakPointer<Node> _node;    MetavoxelData _data;    MetavoxelLOD _lod;}; PointBufferBuilder::PointBufferBuilder(const SharedNodePointer& node, const MetavoxelData& data, const MetavoxelLOD& lod) :    _node(node),    _data(data),    _lod(lod) {} void PointBufferBuilder::run() {    SharedNodePointer node = _node;    if (!node) {        return;    }    qint64 now = QDateTime::currentMSecsSinceEpoch();    PointCollector collector(_lod);    _data.guide(collector);    QMetaObject::invokeMethod(node->getLinkedData(), "setPoints", Q_ARG(const BufferPointVector&, collector.points));    qDebug() << "collect" << (QDateTime::currentMSecsSinceEpoch() - now);} void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) {    /* BufferBuilder builder(_remoteDataLOD);    const AttributePointer& pointBufferAttribute = Application::getInstance()->getMetavoxels()->getPointBufferAttribute();    MetavoxelNode* oldRoot = oldData.getRoot(pointBufferAttribute);    if (oldRoot && oldData.getSize() == _data.getSize()) {        oldRoot->incrementReferenceCount();        _data.setRoot(pointBufferAttribute, oldRoot);        _data.guideToDifferent(oldData, builder);            } else {        _data.clear(pointBufferAttribute);        _data.guide(builder);    } */    QThreadPool::globalInstance()->start(new PointBufferBuilder(_node, _data, _remoteDataLOD));} void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {    NodeList::getInstance()->writeDatagram(data, _node);    Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size());} PointBuffer::PointBuffer(const QOpenGLBuffer& buffer, const QVector<int>& offsets, int lastLeafCount) :    _buffer(buffer),    _offsets(offsets),    _lastLeafCount(lastLeafCount) {} void PointBuffer::render(int level) {    int first, count;    int nextLevel = level + 1;    if (nextLevel >= _offsets.size()) {        first = _offsets.last() - _lastLeafCount;        count = _lastLeafCount;            } else {        first = _offsets.at(level);        count = _offsets.at(nextLevel) - first;    }    if (count == 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, first, count);        _buffer.release();} PointBufferAttribute::PointBufferAttribute() :    InlineAttribute<PointBufferPointer>("pointBuffer") {} MetavoxelNode* PointBufferAttribute::createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const {    return new MetavoxelNode(value, original);} bool PointBufferAttribute::merge(void*& parent, void* children[], bool postRead) const {    for (int i = 0; i < MERGE_COUNT; i++) {        if (decodeInline<PointBufferPointer>(children[i])) {            return false;        }    }    return true;} AttributeValue PointBufferAttribute::inherit(const AttributeValue& parentValue) const {    return AttributeValue(parentValue.getAttribute());} static void enableClipPlane(GLenum plane, float x, float y, float z, float w) {    GLdouble coefficients[] = { x, y, z, w };    glClipPlane(plane, coefficients);    glEnable(plane);} void ClippedRenderer::render(float alpha, Mode mode, const glm::vec3& clipMinimum, float clipSize) {    if (clipSize == 0.0f) {        renderUnclipped(alpha, mode);        return;    }    enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipSize);    enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x);    enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipSize);    enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y);    enableClipPlane(GL_CLIP_PLANE4, 0.0f, 0.0f, -1.0f, clipMinimum.z + clipSize);    enableClipPlane(GL_CLIP_PLANE5, 0.0f, 0.0f, 1.0f, -clipMinimum.z);        renderUnclipped(alpha, mode);        glDisable(GL_CLIP_PLANE0);    glDisable(GL_CLIP_PLANE1);    glDisable(GL_CLIP_PLANE2);    glDisable(GL_CLIP_PLANE3);    glDisable(GL_CLIP_PLANE4);    glDisable(GL_CLIP_PLANE5);} SphereRenderer::SphereRenderer() {} void SphereRenderer::render(float alpha, Mode mode, const glm::vec3& clipMinimum, float clipSize) {    if (clipSize == 0.0f) {        renderUnclipped(alpha, mode);        return;

Lines 1–500 of 599.