Stephen Birardafix a silly typoee9f89312 years agoHistory
267 lines · 8.8 KB · C++
RawDownload
////  MetavoxelSystem.cpp//  interface////  Created by Andrzej Kapolka on 12/10/13.//  Copyright (c) 2013 High Fidelity, Inc. All rights reserved.// #include <QMutexLocker>#include <QtDebug> #include <SharedUtil.h> #include <MetavoxelUtil.h>#include <ScriptCache.h> #include "Application.h"#include "MetavoxelSystem.h" ProgramObject MetavoxelSystem::_program;int MetavoxelSystem::_pointScaleLocation; MetavoxelSystem::MetavoxelSystem() :    _pointVisitor(_points),    _buffer(QOpenGLBuffer::VertexBuffer) {} MetavoxelSystem::~MetavoxelSystem() {    for (QHash<QUuid, MetavoxelClient*>::const_iterator it = _clients.begin(); it != _clients.end(); it++) {        delete it.value();    }} void MetavoxelSystem::init() {    if (!_program.isLinked()) {        switchToResourcesParentIfRequired();        _program.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/metavoxel_point.vert");        _program.link();               _pointScaleLocation = _program.uniformLocation("pointScale");                // let the script cache know to use our common access manager        ScriptCache::getInstance()->setNetworkAccessManager(Application::getInstance()->getNetworkAccessManager());    }        NodeList* nodeList = NodeList::getInstance();        connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer)));    connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));        _buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);    _buffer.create();} void MetavoxelSystem::applyEdit(const MetavoxelEditMessage& edit) {    foreach (MetavoxelClient* client, _clients) {        client->applyEdit(edit);    }} void MetavoxelSystem::processData(const QByteArray& data, const HifiSockAddr& sender) {    QMetaObject::invokeMethod(this, "receivedData", Q_ARG(const QByteArray&, data), Q_ARG(const HifiSockAddr&, sender));} void MetavoxelSystem::simulate(float deltaTime) {    // simulate the clients    _points.clear();    foreach (MetavoxelClient* client, _clients) {        client->simulate(deltaTime, _pointVisitor);    }     _buffer.bind();    int bytes = _points.size() * sizeof(Point);    if (_buffer.size() < bytes) {        _buffer.allocate(_points.constData(), bytes);    } else {        _buffer.write(0, _points.constData(), bytes);    }    _buffer.release();} 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);            _buffer.bind();     Point* pt = 0;    glVertexPointer(4, GL_FLOAT, sizeof(Point), &pt->vertex);    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Point), &pt->color);    glNormalPointer(GL_BYTE, sizeof(Point), &pt->normal);         glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_COLOR_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);     glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);        glDrawArrays(GL_POINTS, 0, _points.size());        glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);        glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_COLOR_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);        _buffer.release();        _program.release();} void MetavoxelSystem::nodeAdded(SharedNodePointer node) {    if (node->getType() == NodeType::MetavoxelServer) {        QMetaObject::invokeMethod(this, "addClient", Q_ARG(const SharedNodePointer&, node));    }} void MetavoxelSystem::nodeKilled(SharedNodePointer node) {    if (node->getType() == NodeType::MetavoxelServer) {        QMetaObject::invokeMethod(this, "removeClient", Q_ARG(const QUuid&, node->getUUID()));    }} void MetavoxelSystem::addClient(const SharedNodePointer& node) {    MetavoxelClient* client = new MetavoxelClient(node);    _clients.insert(node->getUUID(), client);    _clientsBySessionID.insert(client->getSessionID(), client);} void MetavoxelSystem::removeClient(const QUuid& uuid) {    MetavoxelClient* client = _clients.take(uuid);    _clientsBySessionID.remove(client->getSessionID());    delete client;} void MetavoxelSystem::receivedData(const QByteArray& data, const SharedNodePointer& sendingNode) {    int headerPlusIDSize;    QUuid sessionID = readSessionID(data, sendingNode, headerPlusIDSize);    if (sessionID.isNull()) {        return;    }    MetavoxelClient* client = _clientsBySessionID.value(sessionID);    if (client) {        client->receivedData(data);    }} MetavoxelSystem::PointVisitor::PointVisitor(QVector<Point>& points) :    MetavoxelVisitor(QVector<AttributePointer>() <<        AttributeRegistry::getInstance()->getColorAttribute() <<        AttributeRegistry::getInstance()->getNormalAttribute(),        QVector<AttributePointer>()),    _points(points) {} bool MetavoxelSystem::PointVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return true;    }    QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();    QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();    int alpha = qAlpha(color);    if (alpha > 0) {        Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),            { qRed(color), qGreen(color), qBlue(color), alpha }, { qRed(normal), qGreen(normal), qBlue(normal) } };        _points.append(point);    }    return false;} static QByteArray createDatagramHeader(const QUuid& sessionID) {    QByteArray header = byteArrayWithPopulatedHeader(PacketTypeMetavoxelData);    header += sessionID.toRfc4122();    return header;} MetavoxelClient::MetavoxelClient(const SharedNodePointer& node) :    _node(node),    _sessionID(QUuid::createUuid()),    _sequencer(createDatagramHeader(_sessionID)) {        connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendData(const QByteArray&)));    connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&)));    connect(&_sequencer, SIGNAL(receiveAcknowledged(int)), SLOT(clearReceiveRecordsBefore(int)));        // insert the baseline receive record    ReceiveRecord record = { 0, _data };    _receiveRecords.append(record);} MetavoxelClient::~MetavoxelClient() {    // close the session    Bitstream& out = _sequencer.startPacket();    out << QVariant::fromValue(CloseSessionMessage());    _sequencer.endPacket();} void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {    // apply immediately to local tree    edit.apply(_data);     // start sending it out    _sequencer.sendHighPriorityMessage(QVariant::fromValue(edit));} void MetavoxelClient::simulate(float deltaTime, MetavoxelVisitor& visitor) {    Bitstream& out = _sequencer.startPacket();    ClientStateMessage state = { Application::getInstance()->getCamera()->getPosition() };    out << QVariant::fromValue(state);    _sequencer.endPacket();        _data.guide(visitor);} void MetavoxelClient::receivedData(const QByteArray& data) {    // process through sequencer    _sequencer.receivedDatagram(data);} void MetavoxelClient::sendData(const QByteArray& data) {    QMutexLocker locker(&_node->getMutex());    NodeList::getInstance()->writeDatagram(data, _node);} void MetavoxelClient::readPacket(Bitstream& in) {    QVariant message;    in >> message;    handleMessage(message, in);        // record the receipt    ReceiveRecord record = { _sequencer.getIncomingPacketNumber(), _data };    _receiveRecords.append(record);        // reapply local edits    foreach (const DatagramSequencer::HighPriorityMessage& message, _sequencer.getHighPriorityMessages()) {        if (message.data.userType() == MetavoxelEditMessage::Type) {            message.data.value<MetavoxelEditMessage>().apply(_data);        }    }} void MetavoxelClient::clearReceiveRecordsBefore(int index) {    _receiveRecords.erase(_receiveRecords.begin(), _receiveRecords.begin() + index + 1);} void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) {    int userType = message.userType();    if (userType == MetavoxelDeltaMessage::Type) {        _data.readDelta(_receiveRecords.first().data, in);            } else if (userType == QMetaType::QVariantList) {        foreach (const QVariant& element, message.toList()) {            handleMessage(element, in);        }    }}