2352 lines · 101.2 KB · C++
RawDownload
} 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() {} void VoxelPoint::setNormal(const glm::vec3& normal) {    this->normal[0] = (char)(normal.x * 127.0f);    this->normal[1] = (char)(normal.y * 127.0f);    this->normal[2] = (char)(normal.z * 127.0f);} VoxelBuffer::VoxelBuffer(const QVector<VoxelPoint>& vertices, const QVector<int>& indices, const QVector<glm::vec3>& hermite,        const QMultiHash<VoxelCoord, int>& quadIndices, int size, const QVector<SharedObjectPointer>& materials) :    _vertices(vertices),    _indices(indices),    _hermite(hermite),    _quadIndices(quadIndices),    _size(size),    _vertexCount(vertices.size()),    _indexCount(indices.size()),    _hermiteCount(hermite.size()),    _indexBuffer(QOpenGLBuffer::IndexBuffer),    _materials(materials) {} static bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction,        const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance) {    glm::vec3 firstSide = v0 - v1;    glm::vec3 secondSide = v2 - v1;    glm::vec3 normal = glm::cross(secondSide, firstSide);    float dividend = glm::dot(normal, v1) - glm::dot(origin, normal);    if (dividend > 0.0f) {        return false; // origin below plane    }    float divisor = glm::dot(normal, direction);    if (divisor > -EPSILON) {        return false;    }    float t = dividend / divisor;    glm::vec3 point = origin + direction * t;    if (glm::dot(normal, glm::cross(point - v1, firstSide)) > 0.0f &&            glm::dot(normal, glm::cross(secondSide, point - v1)) > 0.0f &&            glm::dot(normal, glm::cross(point - v0, v2 - v0)) > 0.0f) {        distance = t;        return true;    }    return false;} bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& entry, const glm::vec3& origin,        const glm::vec3& direction, float& distance) const {    float highest = _size - 1.0f;    glm::vec3 position = entry * highest;    glm::vec3 floors = glm::floor(position);    int max = _size - 2;    int x = qMin((int)floors.x, max), y = qMin((int)floors.y, max), z = qMin((int)floors.z, max);    forever {        for (QMultiHash<VoxelCoord, int>::const_iterator it = _quadIndices.constFind(qRgb(x + 1, y + 1, z + 1));                it != _quadIndices.constEnd(); it++) {            const int* indices = _indices.constData() + *it;            if (findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex,                    _vertices.at(indices[1]).vertex, _vertices.at(indices[2]).vertex, distance) ||                findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex,                    _vertices.at(indices[2]).vertex, _vertices.at(indices[3]).vertex, distance)) {                return true;            }        }        float xDistance = FLT_MAX, yDistance = FLT_MAX, zDistance = FLT_MAX;        if (direction.x > 0.0f) {            xDistance = (x + 1.0f - position.x) / direction.x;        } else if (direction.x < 0.0f) {            xDistance = (x - position.x) / direction.x;        }        if (direction.y > 0.0f) {            yDistance = (y + 1.0f - position.y) / direction.y;        } else if (direction.y < 0.0f) {            yDistance = (y - position.y) / direction.y;        }        if (direction.z > 0.0f) {            zDistance = (z + 1.0f - position.z) / direction.z;        } else if (direction.z < 0.0f) {            zDistance = (z - position.z) / direction.z;        }        float minimumDistance = qMin(xDistance, qMin(yDistance, zDistance));        if (minimumDistance == xDistance) {            if (direction.x > 0.0f) {                if (x++ == max) {                    return false;                }            } else if (x-- == 0) {                return false;            }        }        if (minimumDistance == yDistance) {            if (direction.y > 0.0f) {                if (y++ == max) {                    return false;                }            } else if (y-- == 0) {                return false;            }        }        if (minimumDistance == zDistance) {            if (direction.z > 0.0f) {                if (z++ == max) {                    return false;                }            } else if (z-- == 0) {                return false;            }        }        position += direction * minimumDistance;    }    return false;} void VoxelBuffer::render(bool cursor) {    if (!_vertexBuffer.isCreated()) {        _vertexBuffer.create();        _vertexBuffer.bind();        _vertexBuffer.allocate(_vertices.constData(), _vertices.size() * sizeof(VoxelPoint));        _vertexBuffer.release();                _indexBuffer.create();        _indexBuffer.bind();        _indexBuffer.allocate(_indices.constData(), _indices.size() * sizeof(int));        _indexBuffer.release();                if (!_materials.isEmpty()) {            _networkTextures.resize(_materials.size());            for (int i = 0; i < _materials.size(); i++) {                const SharedObjectPointer material = _materials.at(i);                if (material) {                    _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture(                        static_cast<MaterialObject*>(material.data())->getDiffuse(), SPLAT_TEXTURE);                }            }        }    }        if (cursor) {        _vertexBuffer.bind();        _indexBuffer.bind();                VoxelPoint* point = 0;        glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex);        glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color);        glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal);                glDrawRangeElements(GL_QUADS, 0, _vertexCount - 1, _indexCount, GL_UNSIGNED_INT, 0);                _vertexBuffer.release();        _indexBuffer.release();        return;    }        VoxelBatch baseBatch;    baseBatch.vertexBuffer = &_vertexBuffer;    baseBatch.indexBuffer = &_indexBuffer;    baseBatch.vertexCount = _vertexCount;    baseBatch.indexCount = _indexCount;    Application::getInstance()->getMetavoxels()->addVoxelBaseBatch(baseBatch);        if (!_materials.isEmpty()) {        VoxelSplatBatch splatBatch;        splatBatch.vertexBuffer = &_vertexBuffer;        splatBatch.indexBuffer = &_indexBuffer;        splatBatch.vertexCount = _vertexCount;        splatBatch.indexCount = _indexCount;            for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) {            for (int j = 0; j < SPLAT_COUNT; j++) {                int index = i + j;                if (index < _networkTextures.size()) {                    const NetworkTexturePointer& texture = _networkTextures.at(index);                    if (texture) {                        MaterialObject* material = static_cast<MaterialObject*>(_materials.at(index).data());                        splatBatch.splatTextureScalesS[j] = 1.0f / material->getScaleS();                        splatBatch.splatTextureScalesT[j] = 1.0f / material->getScaleT();                        splatBatch.splatTextureIDs[j] = texture->getID();                                               } else {                        splatBatch.splatTextureIDs[j] = 0;                    }                } else {                    splatBatch.splatTextureIDs[j] = 0;                }            }            splatBatch.materialIndex = i;            Application::getInstance()->getMetavoxels()->addVoxelSplatBatch(splatBatch);        }    }        if (_hermiteCount > 0) {        if (!_hermiteBuffer.isCreated()) {            _hermiteBuffer.create();            _hermiteBuffer.bind();            _hermiteBuffer.allocate(_hermite.constData(), _hermite.size() * sizeof(glm::vec3));                _hermiteBuffer.release();            _hermite.clear();        }        HermiteBatch hermiteBatch;        hermiteBatch.vertexBuffer = &_hermiteBuffer;        hermiteBatch.vertexCount = _hermiteCount;        Application::getInstance()->getMetavoxels()->addHermiteBatch(hermiteBatch);    }} BufferDataAttribute::BufferDataAttribute(const QString& name) :    InlineAttribute<BufferDataPointer>(name) {} bool BufferDataAttribute::merge(void*& parent, void* children[], bool postRead) const {    *(BufferDataPointer*)&parent = _defaultValue;    for (int i = 0; i < MERGE_COUNT; i++) {        if (decodeInline<BufferDataPointer>(children[i])) {            return false;        }    }    return true;} AttributeValue BufferDataAttribute::inherit(const AttributeValue& parentValue) const {    return AttributeValue(parentValue.getAttribute());} DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {} class VoxelAugmentVisitor : public MetavoxelVisitor {public:     VoxelAugmentVisitor(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);}; VoxelAugmentVisitor::VoxelAugmentVisitor(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getVoxelColorAttribute() <<        AttributeRegistry::getInstance()->getVoxelMaterialAttribute() <<            AttributeRegistry::getInstance()->getVoxelHermiteAttribute(), QVector<AttributePointer>() <<                Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), lod) {} class EdgeCrossing {public:    glm::vec3 point;    glm::vec3 normal;    QRgb color;    char material;}; const int MAX_NORMALS_PER_VERTEX = 4; class NormalIndex {public:    int indices[MAX_NORMALS_PER_VERTEX];        int getClosestIndex(const glm::vec3& normal, QVector<VoxelPoint>& vertices) const;}; int NormalIndex::getClosestIndex(const glm::vec3& normal, QVector<VoxelPoint>& vertices) const {    int firstIndex = indices[0];    int closestIndex = firstIndex;    const VoxelPoint& firstVertex = vertices.at(firstIndex);    float closest = normal.x * firstVertex.normal[0] + normal.y * firstVertex.normal[1] + normal.z * firstVertex.normal[2];    for (int i = 1; i < MAX_NORMALS_PER_VERTEX; i++) {        int index = indices[i];        if (index == firstIndex) {            break;        }        const VoxelPoint& vertex = vertices.at(index);        float product = normal.x * vertex.normal[0] + normal.y * vertex.normal[1] + normal.z * vertex.normal[2];        if (product > closest) {            closest = product;            closestIndex = index;        }    }    return closestIndex;} static glm::vec3 safeNormalize(const glm::vec3& vector) {    float length = glm::length(vector);    return (length > 0.0f) ? (vector / length) : vector;} int VoxelAugmentVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    BufferData* buffer = NULL;    VoxelColorDataPointer color = info.inputValues.at(0).getInlineValue<VoxelColorDataPointer>();    VoxelMaterialDataPointer material = info.inputValues.at(1).getInlineValue<VoxelMaterialDataPointer>();    VoxelHermiteDataPointer hermite = info.inputValues.at(2).getInlineValue<VoxelHermiteDataPointer>();        if (color && hermite) {        QVector<VoxelPoint> vertices;        QVector<int> indices;        QVector<glm::vec3> hermiteSegments;        QMultiHash<VoxelCoord, int> quadIndices;                // see http://www.frankpetterson.com/publications/dualcontour/dualcontour.pdf for a description of the        // dual contour algorithm for generating meshes from voxel data using Hermite-tagged edges        const QVector<QRgb>& colorContents = color->getContents();        const QVector<QRgb>& hermiteContents = hermite->getContents();        int size = color->getSize();        int area = size * size;                // number variables such as offset3 and alpha0 in this function correspond to cube corners, where the x, y, and z        // components are represented as bits in the 0, 1, and 2 position, respectively; hence, alpha0 is the value at        // the minimum x, y, and z corner and alpha7 is the value at the maximum x, y, and z        int offset3 = size + 1;        int offset5 = area + 1;        int offset6 = area + size;        int offset7 = area + size + 1;                const QRgb* colorZ = colorContents.constData();        const QRgb* hermiteData = hermiteContents.constData();        int hermiteStride = hermite->getSize() * VoxelHermiteData::EDGE_COUNT;        int hermiteArea = hermiteStride * hermite->getSize();                const char* materialData = material ? material->getContents().constData() : NULL;                // as we scan down the cube generating vertices between grid points, we remember the indices of the last        // (element, line, section--x, y, z) so that we can connect generated vertices as quads        int expanded = size + 1;        QVector<NormalIndex> lineIndices(expanded);        QVector<NormalIndex> lastLineIndices(expanded);        QVector<NormalIndex> planeIndices(expanded * expanded);        QVector<NormalIndex> lastPlaneIndices(expanded * expanded);                const int EDGES_PER_CUBE = 12;        EdgeCrossing crossings[EDGES_PER_CUBE];                float highest = size - 1.0f;        float scale = info.size / highest;        const int ALPHA_OFFSET = 24;        bool displayHermite = Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData);        for (int z = 0; z < expanded; z++) {            const QRgb* colorY = colorZ;            for (int y = 0; y < expanded; y++) {                NormalIndex lastIndex;                const QRgb* colorX = colorY;                for (int x = 0; x < expanded; x++) {                    int alpha0 = colorX[0] >> ALPHA_OFFSET;                    int alpha1 = alpha0, alpha2 = alpha0, alpha4 = alpha0;                    int alphaTotal = alpha0;                    int possibleTotal = EIGHT_BIT_MAXIMUM;                                        // cubes on the edge are two-dimensional: this ensures that their vertices will be shared between                    // neighboring blocks, which share only one layer of points                    bool middleX = (x != 0 && x != size);                    bool middleY = (y != 0 && y != size);                    bool middleZ = (z != 0 && z != size);                    if (middleZ) {                        alphaTotal += (alpha4 = colorX[area] >> ALPHA_OFFSET);                        possibleTotal += EIGHT_BIT_MAXIMUM;                    }                                        int alpha5 = alpha4, alpha6 = alpha4;                    if (middleY) {                        alphaTotal += (alpha2 = colorX[size] >> ALPHA_OFFSET);                        possibleTotal += EIGHT_BIT_MAXIMUM;                                                if (middleZ) {                            alphaTotal += (alpha6 = colorX[offset6] >> ALPHA_OFFSET);                            possibleTotal += EIGHT_BIT_MAXIMUM;                        }                    }                                        int alpha3 = alpha2, alpha7 = alpha6;                    if (middleX) {                        alphaTotal += (alpha1 = colorX[1] >> ALPHA_OFFSET);                        possibleTotal += EIGHT_BIT_MAXIMUM;                                                if (middleY) {                            alphaTotal += (alpha3 = colorX[offset3] >> ALPHA_OFFSET);                            possibleTotal += EIGHT_BIT_MAXIMUM;                                                        if (middleZ) {                                alphaTotal += (alpha7 = colorX[offset7] >> ALPHA_OFFSET);                                possibleTotal += EIGHT_BIT_MAXIMUM;                            }                        }                        if (middleZ) {                            alphaTotal += (alpha5 = colorX[offset5] >> ALPHA_OFFSET);                            possibleTotal += EIGHT_BIT_MAXIMUM;                        }                    }                    if (alphaTotal == 0 || alphaTotal == possibleTotal) {                        if (x != 0) {                            colorX++;                        }                        continue; // no corners set/all corners set                    }                    // the terrifying conditional code that follows checks each cube edge for a crossing, gathering                    // its properties (color, material, normal) if one is present; as before, boundary edges are excluded                    int clampedX = qMax(x - 1, 0), clampedY = qMax(y - 1, 0), clampedZ = qMax(z - 1, 0);                    const QRgb* hermiteBase = hermiteData + clampedZ * hermiteArea + clampedY * hermiteStride +                        clampedX * VoxelHermiteData::EDGE_COUNT;                    const char* materialBase = materialData ?                        (materialData + clampedZ * area + clampedY * size + clampedX) : NULL;                    int crossingCount = 0;                    if (middleX) {                        if (alpha0 != alpha1) {                            QRgb hermite = hermiteBase[0];                            EdgeCrossing& crossing = crossings[crossingCount++];                            crossing.normal = unpackNormal(hermite);                            if (alpha0 == 0) {                                crossing.color = colorX[1];                                crossing.material = materialBase ? materialBase[1] : 0;                            } else {                                crossing.color = colorX[0];                                crossing.material = materialBase ? materialBase[0] : 0;                            }                            crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 0.0f);                        }                        if (middleY) {                            if (alpha1 != alpha3) {                                QRgb hermite = hermiteBase[VoxelHermiteData::EDGE_COUNT + 1];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha1 == 0) {                                    crossing.color = colorX[offset3];                                    crossing.material = materialBase ? materialBase[offset3] : 0;                                } else {                                    crossing.color = colorX[1];                                    crossing.material = materialBase ? materialBase[1] : 0;

Lines 1001–1500 of 2352. Previous lines