2352 lines · 101.2 KB · C++
RawDownload
            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);} void MetavoxelSystem::deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const {    glDeleteTextures(1, (const GLuint*)&heightTextureID);    glDeleteTextures(1, (const GLuint*)&colorTextureID);    glDeleteTextures(1, (const GLuint*)&materialTextureID);} class SpannerRenderVisitor : public SpannerVisitor {public:        SpannerRenderVisitor(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);    virtual bool visit(Spanner* spanner); protected:        int _containmentDepth;}; SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),        QVector<AttributePointer>(), QVector<AttributePointer>(), lod,        encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())),    _containmentDepth(INT_MAX) {} int SpannerRenderVisitor::visit(MetavoxelInfo& info) {    if (_containmentDepth >= _depth) {        Frustum::IntersectionType intersection = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType(            info.getBounds());        if (intersection == Frustum::NO_INTERSECTION) {            return STOP_RECURSION;        }        _containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX;    }    return SpannerVisitor::visit(info);} bool SpannerRenderVisitor::visit(Spanner* spanner) {    spanner->getRenderer()->render(_lod, _containmentDepth <= _depth);    return true;} class SpannerCursorRenderVisitor : public SpannerRenderVisitor {public:        SpannerCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds);        virtual bool visit(Spanner* spanner);        virtual int visit(MetavoxelInfo& info); private:        Box _bounds;}; SpannerCursorRenderVisitor::SpannerCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) :    SpannerRenderVisitor(lod),    _bounds(bounds) {} bool SpannerCursorRenderVisitor::visit(Spanner* spanner) {    if (spanner->isHeightfield()) {         spanner->getRenderer()->render(_lod, _containmentDepth <= _depth, true);    }    return true;} int SpannerCursorRenderVisitor::visit(MetavoxelInfo& info) {    return info.getBounds().intersects(_bounds) ? SpannerRenderVisitor::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);        _heightfieldCursorProgram.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(getLOD(), Box(position - extents, position + extents));    guide(visitor);        _heightfieldCursorProgram.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);    glPolygonOffset(-1.0f, -1.0f);        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);        glEnableClientState(GL_VERTEX_ARRAY);        _voxelCursorProgram.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, scale, 0.0f, -scale * position.y);    glm::vec4 rCoefficients(0.0f, 0.0f, scale, -scale * position.z);    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);    Box bounds(position - extents, position + extents);    BufferCursorRenderVisitor voxelVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), bounds);    guideToAugmented(voxelVisitor);        _voxelCursorProgram.release();        glEnableClientState(GL_TEXTURE_COORD_ARRAY);        _heightfieldCursorProgram.bind();        SpannerCursorRenderVisitor spannerVisitor(getLOD(), bounds);    guide(spannerVisitor);        _heightfieldCursorProgram.release();        glDisableClientState(GL_TEXTURE_COORD_ARRAY);        glDisableClientState(GL_VERTEX_ARRAY);        glDisable(GL_POLYGON_OFFSET_FILL);    glDisable(GL_CULL_FACE);    glDepthFunc(GL_LESS);} class MaterialEditApplier : public SignalHandler {public:     MaterialEditApplier(const MetavoxelEditMessage& message, const QSharedPointer<NetworkTexture> texture);        virtual void handle(); protected:        MetavoxelEditMessage _message;    QSharedPointer<NetworkTexture> _texture;}; MaterialEditApplier::MaterialEditApplier(const MetavoxelEditMessage& message, const QSharedPointer<NetworkTexture> texture) :    _message(message),    _texture(texture) {} void MaterialEditApplier::handle() {    static_cast<MaterialEdit*>(_message.edit.data())->averageColor = _texture->getAverageColor();    Application::getInstance()->getMetavoxels()->applyEdit(_message, true);    deleteLater();} void MetavoxelSystem::applyMaterialEdit(const MetavoxelEditMessage& message, bool reliable) {    const MaterialEdit* edit = static_cast<const MaterialEdit*>(message.edit.constData());    MaterialObject* material = static_cast<MaterialObject*>(edit->material.data());    if (material && material->getDiffuse().isValid()) {        if (QThread::currentThread() != thread()) {            QMetaObject::invokeMethod(this, "applyMaterialEdit", Q_ARG(const MetavoxelEditMessage&, message),                Q_ARG(bool, reliable));            return;        }        QSharedPointer<NetworkTexture> texture = Application::getInstance()->getTextureCache()->getTexture(            material->getDiffuse(), SPLAT_TEXTURE);        if (texture->isLoaded()) {            MetavoxelEditMessage newMessage = message;            static_cast<MaterialEdit*>(newMessage.edit.data())->averageColor = texture->getAverageColor();            applyEdit(newMessage, true);                    } else {            MaterialEditApplier* applier = new MaterialEditApplier(message, texture);            connect(texture.data(), &Resource::loaded, applier, &SignalHandler::handle);        }    } else {        applyEdit(message, true);    }} MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) {    return new MetavoxelSystemClient(node, _updater);} void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) {    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) {                MetavoxelData data = client->getAugmentedData();                data.guide(visitor);                if (render) {                    // save the rendered augmented data so that its cached texture references, etc., don't                    // get collected when we replace it with more recent versions                    client->setRenderedAugmentedData(data);                }            }        }    }} void MetavoxelSystem::loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations) {    program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +        "shaders/metavoxel_" + type + "_splat.vert");    program.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +        "shaders/metavoxel_" + type + "_splat.frag");    program.link();        program.bind();    program.setUniformValue("heightMap", 0);    program.setUniformValue("textureMap", 1);    program.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT);    locations.heightScale = program.uniformLocation("heightScale");    locations.textureScale = program.uniformLocation("textureScale");    locations.splatTextureOffset = program.uniformLocation("splatTextureOffset");    locations.splatTextureScalesS = program.uniformLocation("splatTextureScalesS");    locations.splatTextureScalesT = program.uniformLocation("splatTextureScalesT");    locations.textureValueMinima = program.uniformLocation("textureValueMinima");    locations.textureValueMaxima = program.uniformLocation("textureValueMaxima");    locations.materials = program.attributeLocation("materials");    locations.materialWeights = program.attributeLocation("materialWeights");    program.release();} Throttle::Throttle() :    _limit(INT_MAX),    _total(0) {} bool Throttle::shouldThrottle(int bytes) {    // clear expired buckets    qint64 now = QDateTime::currentMSecsSinceEpoch();    while (!_buckets.isEmpty() && now >= _buckets.first().first) {        _total -= _buckets.takeFirst().second;    }        // if possible, add the new bucket    if (_total + bytes > _limit) {        return true;    }    const int BUCKET_DURATION = 1000;    _buckets.append(Bucket(now + BUCKET_DURATION, bytes));    _total += bytes;    return false;} 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;} class ReceiveDelayer : public QObject {public:        ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet); protected:     virtual void timerEvent(QTimerEvent* event); private:        SharedNodePointer _node;    QByteArray _packet;}; ReceiveDelayer::ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet) :    _node(node),    _packet(packet) {} void ReceiveDelayer::timerEvent(QTimerEvent* event) {    QMutexLocker locker(&_node->getMutex());    MetavoxelClient* client = static_cast<MetavoxelClient*>(_node->getLinkedData());    if (client) {        QMetaObject::invokeMethod(&client->getSequencer(), "receivedDatagram", Q_ARG(const QByteArray&, _packet));    }    deleteLater();} int MetavoxelSystemClient::parseData(const QByteArray& packet) {    // process through sequencer    MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation();    if (randFloat() < simulation.dropRate) {        return packet.size();    }    int count = (randFloat() < simulation.repeatRate) ? 2 : 1;    for (int i = 0; i < count; i++) {        if (simulation.bandwidthLimit > 0) {            _receiveThrottle.setLimit(simulation.bandwidthLimit);            if (_receiveThrottle.shouldThrottle(packet.size())) {                continue;            }        }        int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay);        if (delay > 0) {            ReceiveDelayer* delayer = new ReceiveDelayer(_node, packet);            delayer->startTimer(delay);                    } else {            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) {

Lines 501–1000 of 2352. Previous lines