3173 lines · 138.0 KB · C++
RawDownload
 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 CursorRenderVisitor : public MetavoxelVisitor {public:        CursorRenderVisitor(const AttributePointer& attribute, const Box& bounds);        virtual int visit(MetavoxelInfo& info); private:        Box _bounds;}; CursorRenderVisitor::CursorRenderVisitor(const AttributePointer& attribute, const Box& bounds) :    MetavoxelVisitor(QVector<AttributePointer>() << attribute),    _bounds(bounds) {} int CursorRenderVisitor::visit(MetavoxelInfo& info) {    if (!info.getBounds().intersects(_bounds)) {        return STOP_RECURSION;    }    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>();    if (buffer) {        buffer->render(true);    }    return 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);    CursorRenderVisitor visitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(),        Box(position - extents, position + extents));    guideToAugmented(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);} 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);        DefaultMetavoxelRendererImplementation::getVoxelCursorProgram().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);    CursorRenderVisitor voxelVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), bounds);    guideToAugmented(voxelVisitor);        DefaultMetavoxelRendererImplementation::getVoxelCursorProgram().release();        glEnableClientState(GL_TEXTURE_COORD_ARRAY);        DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind();        CursorRenderVisitor heightfieldVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(),        bounds);    guideToAugmented(heightfieldVisitor);        DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();        glDisableClientState(GL_TEXTURE_COORD_ARRAY);    glDisableClientState(GL_VERTEX_ARRAY);        glDisable(GL_POLYGON_OFFSET_FILL);    glDisable(GL_CULL_FACE);    glDepthFunc(GL_LESS);} void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) {    glDeleteTextures(1, (GLuint*)&heightID);    glDeleteTextures(1, (GLuint*)&colorID);    glDeleteTextures(1, (GLuint*)&textureID);} 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);                }            }        }    }} 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) {} 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::refreshVoxelData() {    // make it look as if all the colors have changed    MetavoxelData oldData = getAugmentedData();    oldData.touch(AttributeRegistry::getInstance()->getVoxelColorAttribute());     QThreadPool::globalInstance()->start(new Augmenter(_node, _data, oldData, _remoteDataLOD));} void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) {    MetavoxelClient::dataChanged(oldData);    QThreadPool::globalInstance()->start(new Augmenter(_node, _data, getAugmentedData(), _remoteDataLOD));} class SendDelayer : public QObject {public:        SendDelayer(const SharedNodePointer& node, const QByteArray& data);     virtual void timerEvent(QTimerEvent* event); private:        SharedNodePointer _node;    QByteArray _data;}; SendDelayer::SendDelayer(const SharedNodePointer& node, const QByteArray& data) :    _node(node),    _data(data.constData(), data.size()) {} void SendDelayer::timerEvent(QTimerEvent* event) {    NodeList::getInstance()->writeDatagram(_data, _node);    deleteLater();} void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {    MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation();    if (randFloat() < simulation.dropRate) {        return;    }    int count = (randFloat() < simulation.repeatRate) ? 2 : 1;    for (int i = 0; i < count; i++) {        if (simulation.bandwidthLimit > 0) {            _sendThrottle.setLimit(simulation.bandwidthLimit);            if (_sendThrottle.shouldThrottle(data.size())) {                continue;            }        }        int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay);        if (delay > 0) {            SendDelayer* delayer = new SendDelayer(_node, data);            delayer->startTimer(delay);                    } else {            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(bool cursor) {    // 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();} const int HeightfieldBuffer::HEIGHT_BORDER = 1;const int HeightfieldBuffer::SHARED_EDGE = 1;const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE; HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale,        const QByteArray& height, const QByteArray& color, const QByteArray& material,        const QVector<SharedObjectPointer>& materials) :    _translation(translation),    _scale(scale),    _heightBounds(translation, translation + glm::vec3(scale, scale, scale)),    _colorBounds(_heightBounds),    _materialBounds(_heightBounds),    _height(height),    _color(color),    _material(material),    _materials(materials),    _heightTextureID(0),    _colorTextureID(0),    _materialTextureID(0),    _heightSize(glm::sqrt((float)height.size())),    _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)),    _colorSize(glm::sqrt((float)color.size() / DataBlock::COLOR_BYTES)),    _colorIncrement(scale / (_colorSize - SHARED_EDGE)),    _materialSize(glm::sqrt((float)material.size())),    _materialIncrement(scale / (_materialSize - SHARED_EDGE)) {        _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER;    _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER;    _heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);    _heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);        _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE;    _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE;        _materialBounds.maximum.x += _materialIncrement * SHARED_EDGE;    _materialBounds.maximum.z += _materialIncrement * SHARED_EDGE;} HeightfieldBuffer::~HeightfieldBuffer() {    // the textures have to be deleted on the main thread (for its opengl context)    if (QThread::currentThread() != Application::getInstance()->thread()) {        QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures",            Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID));    } else {        glDeleteTextures(1, &_heightTextureID);        glDeleteTextures(1, &_colorTextureID);        glDeleteTextures(1, &_materialTextureID);    }

Lines 501–1000 of 3173. Previous lines