3173 lines · 138.0 KB · C++
RawDownload
            for (int i = 0; i < SPLAT_COUNT; i++) {            glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);            glBindTexture(GL_TEXTURE_2D, 0);        }            glActiveTexture(GL_TEXTURE0);                glDisable(GL_POLYGON_OFFSET_FILL);        glEnable(GL_ALPHA_TEST);        glDisable(GL_BLEND);        glDepthMask(true);        glDepthFunc(GL_LESS);                Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);                DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materials);        DefaultMetavoxelRendererImplementation::getSplatVoxelProgram().disableAttributeArray(locations.materialWeights);                DefaultMetavoxelRendererImplementation::getBaseVoxelProgram().bind();    }        _vertexBuffer.release();    _indexBuffer.release();        if (_hermiteCount > 0 && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData) && !cursor) {        if (!_hermiteBuffer.isCreated()) {            _hermiteBuffer.create();            _hermiteBuffer.bind();            _hermiteBuffer.allocate(_hermite.constData(), _hermite.size() * sizeof(glm::vec3));            _hermite.clear();                } else {            _hermiteBuffer.bind();        }                glDisableClientState(GL_COLOR_ARRAY);        glDisableClientState(GL_NORMAL_ARRAY);                glVertexPointer(3, GL_FLOAT, 0, 0);                Application::getInstance()->getDeferredLightingEffect()->getSimpleProgram().bind();                glColor4f(1.0f, 1.0f, 1.0f, 1.0f);        glNormal3f(0.0f, 1.0f, 0.0f);                glLineWidth(1.0f);                glDrawArrays(GL_LINES, 0, _hermiteCount);                DefaultMetavoxelRendererImplementation::getBaseVoxelProgram().bind();                glEnableClientState(GL_COLOR_ARRAY);        glEnableClientState(GL_NORMAL_ARRAY);                _hermiteBuffer.release();    }} 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());} void DefaultMetavoxelRendererImplementation::init() {    if (!_pointProgram.isLinked()) {        _pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/metavoxel_point.vert");        _pointProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/metavoxel_voxel_base.frag");        _pointProgram.link();               _pointProgram.bind();        _pointScaleLocation = _pointProgram.uniformLocation("pointScale");        _pointProgram.release();                _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/metavoxel_heightfield_base.vert");        _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/metavoxel_heightfield_base.frag");        _baseHeightfieldProgram.link();                _baseHeightfieldProgram.bind();        _baseHeightfieldProgram.setUniformValue("heightMap", 0);        _baseHeightfieldProgram.setUniformValue("diffuseMap", 1);        _baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale");        _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale");        _baseHeightfieldProgram.release();                loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations);                _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/metavoxel_heightfield_cursor.vert");        _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/metavoxel_cursor.frag");        _heightfieldCursorProgram.link();                _heightfieldCursorProgram.bind();        _heightfieldCursorProgram.setUniformValue("heightMap", 0);        _heightfieldCursorProgram.release();                _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/metavoxel_voxel_base.vert");        _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/metavoxel_voxel_base.frag");        _baseVoxelProgram.link();                loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations);                _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() +            "shaders/metavoxel_voxel_cursor.vert");        _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +            "shaders/metavoxel_cursor.frag");        _voxelCursorProgram.link();    }} DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {} class PointAugmentVisitor : public MetavoxelVisitor {public:     PointAugmentVisitor(const MetavoxelLOD& lod);        virtual void prepare(MetavoxelData* data);    virtual int visit(MetavoxelInfo& info);    virtual bool postVisit(MetavoxelInfo& info); private:        BufferPointVector _points;    float _pointLeafSize;}; PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<        AttributeRegistry::getInstance()->getNormalAttribute(), QVector<AttributePointer>() <<            Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod) {} const int ALPHA_RENDER_THRESHOLD = 0; void PointAugmentVisitor::prepare(MetavoxelData* data) {    MetavoxelVisitor::prepare(data);    const float MAX_POINT_LEAF_SIZE = 64.0f;    _pointLeafSize = qMin(data->getSize(), MAX_POINT_LEAF_SIZE);} int PointAugmentVisitor::visit(MetavoxelInfo& info) {    if (!info.isLeaf) {        return (info.size > _pointLeafSize) ? DEFAULT_ORDER : (DEFAULT_ORDER | ALL_NODES_REST);        }    QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();    quint8 alpha = qAlpha(color);    if (alpha > ALPHA_RENDER_THRESHOLD) {        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);    }    if (info.size >= _pointLeafSize) {        PointBuffer* buffer = NULL;        if (!_points.isEmpty()) {             BufferPointVector swapPoints;            _points.swap(swapPoints);            buffer = new PointBuffer(swapPoints);        }        BufferDataPointer pointer(buffer);        info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));    }    return STOP_RECURSION;} bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) {    if (info.size != _pointLeafSize) {        return false;    }    PointBuffer* buffer = NULL;    if (!_points.isEmpty()) {        BufferPointVector swapPoints;        _points.swap(swapPoints);        buffer = new PointBuffer(swapPoints);    }    BufferDataPointer pointer(buffer);    info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));    return true;} class HeightfieldFetchVisitor : public MetavoxelVisitor {public:        HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);        void init(HeightfieldBuffer* buffer);        virtual int visit(MetavoxelInfo& info);    virtual bool postVisit(MetavoxelInfo& info); private:        const QVector<Box>& _intersections;    HeightfieldBuffer* _buffer;        QVector<int> _depthFlags;}; enum DepthFlags { HEIGHT_FLAG = 0x01, COLOR_FLAG = 0x02, MATERIAL_FLAG = 0x04 }; HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<        AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<        AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector<AttributePointer>(), lod),    _intersections(intersections) {} void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) {    _buffer = buffer;} int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {    if (!info.getBounds().intersects(_buffer->getHeightBounds())) {        return STOP_RECURSION;    }    if (_depthFlags.size() > _depth) {        _depthFlags[_depth] = 0;    } else {        _depthFlags.append(0);    }    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    postVisit(info);    return STOP_RECURSION;} bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) {    HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();    int flags = _depthFlags.at(_depth);    if (height) {        // to handle borders correctly, make sure we only sample nodes with resolution <= ours        int heightSize = glm::sqrt((float)height->getContents().size());        float heightIncrement = info.size / heightSize;        if (heightIncrement < _buffer->getHeightIncrement() || (flags & HEIGHT_FLAG)) {            height.reset();        } else {            flags |= HEIGHT_FLAG;        }    }    HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();    if (color) {        int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES);        float colorIncrement = info.size / colorSize;        if (colorIncrement < _buffer->getColorIncrement() || (flags & COLOR_FLAG)) {            color.reset();        } else {            flags |= COLOR_FLAG;        }    }    HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();    if (material) {        int materialSize = glm::sqrt((float)material->getContents().size());        float materialIncrement = info.size / materialSize;        if (materialIncrement < _buffer->getMaterialIncrement() || (flags & MATERIAL_FLAG)) {            material.reset();        } else {            flags |= MATERIAL_FLAG;        }    }    if (_depth > 0) {        _depthFlags[_depth - 1] |= flags;    }    if (!(height || color || material)) {        return false;    }    Box bounds = info.getBounds();    foreach (const Box& intersection, _intersections) {        Box overlap = intersection.getIntersection(bounds);        if (overlap.isEmpty()) {            continue;        }        if (height) {            float heightIncrement = _buffer->getHeightIncrement();            const Box& heightBounds = _buffer->getHeightBounds();            int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement;            int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement;            int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement);            int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement);            int heightSize = _buffer->getHeightSize();            char* dest = _buffer->getHeight().data() + destY * heightSize + destX;                        const QByteArray& srcHeight = height->getContents();            int srcSize = glm::sqrt((float)srcHeight.size());            float srcIncrement = info.size / srcSize;                        if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) {                // easy case: same resolution                int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;                int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;                                const char* src = srcHeight.constData() + srcY * srcSize + srcX;                for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) {                    memcpy(dest, src, destWidth);                }            } else {                // more difficult: different resolutions                float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;                float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;                float srcAdvance = heightIncrement / srcIncrement;                int shift = 0;                float size = _buffer->getScale();                while (size < info.size) {                    shift++;                    size *= 2.0f;                }                int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale();                for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) {                    const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize;                    float lineSrcX = srcX;                    for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {                        *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM);                    }                }            }        }        if (color) {            const Box& colorBounds = _buffer->getColorBounds();            overlap = colorBounds.getIntersection(overlap);            float colorIncrement = _buffer->getColorIncrement();            int destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement;            int destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement;            int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement);            int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement);            int colorSize = _buffer->getColorSize();            char* dest = _buffer->getColor().data() + (destY * colorSize + destX) * DataBlock::COLOR_BYTES;            int destStride = colorSize * DataBlock::COLOR_BYTES;            int destBytes = destWidth * DataBlock::COLOR_BYTES;                        const QByteArray& srcColor = color->getContents();            int srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES));            int srcStride = srcSize * DataBlock::COLOR_BYTES;            float srcIncrement = info.size / srcSize;                        if (srcIncrement == colorIncrement) {                // easy case: same resolution                int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;                int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;                                const char* src = srcColor.constData() + (srcY * srcSize + srcX) * DataBlock::COLOR_BYTES;                    for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) {                    memcpy(dest, src, destBytes);                }            } else {                // more difficult: different resolutions                float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;                float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;                float srcAdvance = colorIncrement / srcIncrement;                for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) {                    const char* src = srcColor.constData() + (int)srcY * srcStride;                    float lineSrcX = srcX;                    for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += DataBlock::COLOR_BYTES,                            lineSrcX += srcAdvance) {                        const char* lineSrc = src + (int)lineSrcX * DataBlock::COLOR_BYTES;                        lineDest[0] = lineSrc[0];                        lineDest[1] = lineSrc[1];                        lineDest[2] = lineSrc[2];                    }                }            }        }        if (material) {            const Box& materialBounds = _buffer->getMaterialBounds();            overlap = materialBounds.getIntersection(overlap);            float materialIncrement = _buffer->getMaterialIncrement();            int destX = (overlap.minimum.x - materialBounds.minimum.x) / materialIncrement;            int destY = (overlap.minimum.z - materialBounds.minimum.z) / materialIncrement;            int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / materialIncrement);            int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / materialIncrement);            int materialSize = _buffer->getMaterialSize();            char* dest = _buffer->getMaterial().data() + destY * materialSize + destX;                        const QByteArray& srcMaterial = material->getContents();            const QVector<SharedObjectPointer> srcMaterials = material->getMaterials();            int srcSize = glm::sqrt((float)srcMaterial.size());            float srcIncrement = info.size / srcSize;            QHash<int, int> materialMappings;                        if (srcIncrement == materialIncrement) {                // easy case: same resolution                int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;                int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;                                const uchar* src = (const uchar*)srcMaterial.constData() + srcY * srcSize + srcX;                for (int y = 0; y < destHeight; y++, src += srcSize, dest += materialSize) {                    const uchar* lineSrc = src;                    for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrc++) {                        int value = *lineSrc;                        if (value != 0) {                            int& mapping = materialMappings[value];                            if (mapping == 0) {                                mapping = getMaterialIndex(material->getMaterials().at(value - 1),                                    _buffer->getMaterials(), _buffer->getMaterial());                            }                            value = mapping;                        }                        *lineDest = value;                    }                }            } else {                // more difficult: different resolutions                float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;                float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;                float srcAdvance = materialIncrement / srcIncrement;                for (int y = 0; y < destHeight; y++, dest += materialSize, srcY += srcAdvance) {                    const uchar* src = (const uchar*)srcMaterial.constData() + (int)srcY * srcSize;                    float lineSrcX = srcX;                    for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {                        int value = src[(int)lineSrcX];                        if (value != 0) {                            int& mapping = materialMappings[value];                            if (mapping == 0) {                                mapping = getMaterialIndex(material->getMaterials().at(value - 1),                                    _buffer->getMaterials(), _buffer->getMaterial());                            }                            value = mapping;                        }                        *lineDest = value;                    }                }            }            clearUnusedMaterials(_buffer->getMaterials(), _buffer->getMaterial());        }    }    return false;} class HeightfieldRegionVisitor : public MetavoxelVisitor {public:        QVector<Box> regions;    Box regionBounds;     HeightfieldRegionVisitor(const MetavoxelLOD& lod);        virtual int visit(MetavoxelInfo& info);    virtual bool postVisit(MetavoxelInfo& info); private:        void addRegion(const Box& unextended, const Box& extended);        class DepthInfo {    public:        float minimumColorIncrement;        float minimumMaterialIncrement;                DepthInfo() : minimumColorIncrement(FLT_MAX), minimumMaterialIncrement(FLT_MAX) { }    };        QVector<DepthInfo> _depthInfo;        QVector<Box> _intersections;    HeightfieldFetchVisitor _fetchVisitor;}; HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :    MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<        AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<        AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute() <<        Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<            Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),    regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)),    _fetchVisitor(lod, _intersections) {} int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {    DepthInfo depthInfo;    HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();    if (color) {        int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES);        depthInfo.minimumColorIncrement = info.size / colorSize;     }    HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();    if (material) {        int materialSize = glm::sqrt((float)material->getContents().size());        depthInfo.minimumMaterialIncrement = info.size / materialSize;

Lines 1501–2000 of 3173. Previous lines