3173 lines · 138.0 KB · C++
RawDownload
    }    if (_depth < _depthInfo.size()) {        _depthInfo[_depth] = depthInfo;    } else {        _depthInfo.append(depthInfo);    }    if (!info.isLeaf) {        return _visitations.at(_depth).isInputLeaf(0) ? (DEFAULT_ORDER | ALL_NODES_REST) : DEFAULT_ORDER;    }    postVisit(info);    return STOP_RECURSION;} bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) {    const DepthInfo& depthInfo = _depthInfo.at(_depth);    if (_depth > 0) {        DepthInfo& parentDepthInfo = _depthInfo[_depth - 1];        parentDepthInfo.minimumColorIncrement = qMin(parentDepthInfo.minimumColorIncrement, depthInfo.minimumColorIncrement);        parentDepthInfo.minimumMaterialIncrement = qMin(parentDepthInfo.minimumMaterialIncrement,            depthInfo.minimumMaterialIncrement);    }    if (_visitations.at(_depth).isInputLeaf(0)) {        HeightfieldBuffer* buffer = NULL;        HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();        if (height) {            int heightSize = glm::sqrt((float)height->getContents().size());            int extendedHeightSize = heightSize + HeightfieldBuffer::HEIGHT_EXTENSION;            int heightContentsSize = extendedHeightSize * extendedHeightSize;            float minimumColorIncrement = depthInfo.minimumColorIncrement;            float minimumMaterialIncrement = depthInfo.minimumMaterialIncrement;            for (int i = _depth - 1; i >= 0 && qMax(minimumColorIncrement, minimumMaterialIncrement) == FLT_MAX; i--) {                const DepthInfo& ancestorDepthInfo = _depthInfo.at(i);                minimumColorIncrement = qMin(minimumColorIncrement, ancestorDepthInfo.minimumColorIncrement);                minimumMaterialIncrement = qMin(minimumMaterialIncrement, ancestorDepthInfo.minimumMaterialIncrement);            }            int colorContentsSize = 0;            if (minimumColorIncrement != FLT_MAX) {                int colorSize = (int)glm::round(info.size / minimumColorIncrement) + HeightfieldBuffer::SHARED_EDGE;                colorContentsSize = colorSize * colorSize * DataBlock::COLOR_BYTES;            }            int materialContentsSize = 0;            if (minimumMaterialIncrement != FLT_MAX) {                int materialSize = (int)glm::round(info.size / minimumMaterialIncrement) + HeightfieldBuffer::SHARED_EDGE;                materialContentsSize = materialSize * materialSize;            }            const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>(                info.inputValues.at(3).getInlineValue<BufferDataPointer>().data());            Box bounds = info.getBounds();            if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize &&                    existingBuffer->getColor().size() == colorContentsSize &&                    existingBuffer->getMaterial().size() == materialContentsSize) {                // we already have a buffer of the correct resolution                addRegion(bounds, existingBuffer->getHeightBounds());                buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(),                    existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials());                        } else {                // we must create a new buffer and update its borders                buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0),                    QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0));                const Box& heightBounds = buffer->getHeightBounds();                addRegion(bounds, heightBounds);                                _intersections.clear();                _intersections.append(Box(heightBounds.minimum,                    glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z)));                _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z),                    glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z)));                _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z),                    heightBounds.maximum));                _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z),                    glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z)));                                _fetchVisitor.init(buffer);                _data->guide(_fetchVisitor);            }            }        BufferDataPointer pointer(buffer);        info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));    }    return true;} void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {    regions.append(unextended);    regionBounds.add(extended);} class HeightfieldUpdateVisitor : public MetavoxelVisitor {public:        HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, const Box& regionBounds);     virtual int visit(MetavoxelInfo& info);    private:        const QVector<Box>& _regions;        const Box& _regionBounds;    QVector<Box> _intersections;    HeightfieldFetchVisitor _fetchVisitor;}; HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions,        const Box& regionBounds) :    MetavoxelVisitor(QVector<AttributePointer>() <<        Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<            Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),    _regions(regions),    _regionBounds(regionBounds),    _fetchVisitor(lod, _intersections) {} int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) {    if (!info.getBounds().intersects(_regionBounds)) {        return STOP_RECURSION;    }    if (!info.isLeaf) {        return DEFAULT_ORDER;    }    const HeightfieldBuffer* buffer = static_cast<const HeightfieldBuffer*>(        info.inputValues.at(0).getInlineValue<BufferDataPointer>().data());    if (!buffer) {        return STOP_RECURSION;    }    _intersections.clear();    foreach (const Box& region, _regions) {        if (region.intersects(buffer->getHeightBounds())) {            _intersections.append(region.getIntersection(buffer->getHeightBounds()));        }    }    if (_intersections.isEmpty()) {        return STOP_RECURSION;    }    HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size,        buffer->getHeight(), buffer->getColor(), buffer->getMaterial(), buffer->getMaterials());    _fetchVisitor.init(newBuffer);    _data->guide(_fetchVisitor);    BufferDataPointer pointer(newBuffer);    info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));    return STOP_RECURSION;} 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;    int axis;}; class AxisIndex {public:    int x, y, z;        AxisIndex(int x = -1, int y = -1, int z = -1) : x(x), y(y), z(z) { }}; 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<QRgb, 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<AxisIndex> lineIndices(expanded);        QVector<AxisIndex> lastLineIndices(expanded);        QVector<AxisIndex> planeIndices(expanded * expanded);        QVector<AxisIndex> 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++) {                AxisIndex 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);                            crossing.axis = 0;                        }                        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;                                }                                crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f);                                crossing.axis = 1;                            }                            if (alpha2 != alpha3) {                                QRgb hermite = hermiteBase[hermiteStride];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha2 == 0) {                                    crossing.color = colorX[offset3];                                    crossing.material = materialBase ? materialBase[offset3] : 0;                                } else {                                    crossing.color = colorX[size];                                    crossing.material = materialBase ? materialBase[size] : 0;                                }                                crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 0.0f);                                crossing.axis = 0;                            }                            if (middleZ) {                                if (alpha3 != alpha7) {                                    QRgb hermite = hermiteBase[hermiteStride + VoxelHermiteData::EDGE_COUNT + 2];                                    EdgeCrossing& crossing = crossings[crossingCount++];                                    crossing.normal = unpackNormal(hermite);                                    if (alpha3 == 0) {                                        crossing.color = colorX[offset7];                                        crossing.material = materialBase ? materialBase[offset7] : 0;                                    } else {                                        crossing.color = colorX[offset3];                                        crossing.material = materialBase ? materialBase[offset3] : 0;                                    }                                    crossing.point = glm::vec3(1.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                                    crossing.axis = 2;                                }                                if (alpha5 != alpha7) {                                    QRgb hermite = hermiteBase[hermiteArea + VoxelHermiteData::EDGE_COUNT + 1];                                    EdgeCrossing& crossing = crossings[crossingCount++];                                    crossing.normal = unpackNormal(hermite);                                    if (alpha5 == 0) {                                        crossing.color = colorX[offset7];                                        crossing.material = materialBase ? materialBase[offset7] : 0;                                    } else {                                        crossing.color = colorX[offset5];                                        crossing.material = materialBase ? materialBase[offset5] : 0;                                    }                                    crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f);                                    crossing.axis = 1;                                }                                if (alpha6 != alpha7) {                                    QRgb hermite = hermiteBase[hermiteArea + hermiteStride];                                    EdgeCrossing& crossing = crossings[crossingCount++];                                    crossing.normal = unpackNormal(hermite);                                    if (alpha6 == 0) {                                        crossing.color = colorX[offset7];                                        crossing.material = materialBase ? materialBase[offset7] : 0;                                    } else {                                        crossing.color = colorX[offset6];                                        crossing.material = materialBase ? materialBase[offset6] : 0;                                    }                                    crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 1.0f);                                    crossing.axis = 0;                                }                            }                        }                        if (middleZ) {                            if (alpha1 != alpha5) {                                QRgb hermite = hermiteBase[VoxelHermiteData::EDGE_COUNT + 2];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha1 == 0) {                                    crossing.color = colorX[offset5];                                    crossing.material = materialBase ? materialBase[offset5] : 0;                                } else {                                    crossing.color = colorX[1];                                    crossing.material = materialBase ? materialBase[1] : 0;                                }                                crossing.point = glm::vec3(1.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                                crossing.axis = 2;                            }                            if (alpha4 != alpha5) {                                QRgb hermite = hermiteBase[hermiteArea];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha4 == 0) {                                    crossing.color = colorX[offset5];                                    crossing.material = materialBase ? materialBase[offset5] : 0;                                } else {                                    crossing.color = colorX[area];                                    crossing.material = materialBase ? materialBase[area] : 0;                                }                                crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 1.0f);                                crossing.axis = 0;                            }                        }                    }                    if (middleY) {                        if (alpha0 != alpha2) {                            QRgb hermite = hermiteBase[1];                            EdgeCrossing& crossing = crossings[crossingCount++];                            crossing.normal = unpackNormal(hermite);                            if (alpha0 == 0) {                                crossing.color = colorX[size];                                crossing.material = materialBase ? materialBase[size] : 0;                            } else {                                crossing.color = colorX[0];                                crossing.material = materialBase ? materialBase[0] : 0;                            }                            crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f);                            crossing.axis = 1;                        }                        if (middleZ) {                            if (alpha2 != alpha6) {                                QRgb hermite = hermiteBase[hermiteStride + 2];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha2 == 0) {                                    crossing.color = colorX[offset6];                                    crossing.material = materialBase ? materialBase[offset6] : 0;                                } else {                                    crossing.color = colorX[size];                                    crossing.material = materialBase ? materialBase[size] : 0;                                }                                crossing.point = glm::vec3(0.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                                crossing.axis = 2;                            }                            if (alpha4 != alpha6) {                                QRgb hermite = hermiteBase[hermiteArea + 1];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha4 == 0) {                                    crossing.color = colorX[offset6];                                    crossing.material = materialBase ? materialBase[offset6] : 0;                                } else {                                    crossing.color = colorX[area];                                    crossing.material = materialBase ? materialBase[area] : 0;                                }                                crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f);                                crossing.axis = 1;                            }                        }                    }                    if (middleZ && alpha0 != alpha4) {                        QRgb hermite = hermiteBase[2];                        EdgeCrossing& crossing = crossings[crossingCount++];                        crossing.normal = unpackNormal(hermite);                        if (alpha0 == 0) {                            crossing.color = colorX[area];                            crossing.material = materialBase ? materialBase[area] : 0;                        } else {                            crossing.color = colorX[0];                            crossing.material = materialBase ? materialBase[0] : 0;                        }                        crossing.point = glm::vec3(0.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                        crossing.axis = 2;                    }                    // at present, we simply average the properties of each crossing as opposed to finding the vertex that                    // minimizes the quadratic error function as described in the reference paper                    glm::vec3 center;                    glm::vec3 axisNormals[3];                    const int MAX_MATERIALS_PER_VERTEX = 4;                    quint8 materials[] = { 0, 0, 0, 0 };                    glm::vec4 materialWeights;                    float totalWeight = 0.0f;                    int red = 0, green = 0, blue = 0;                    for (int i = 0; i < crossingCount; i++) {                        const EdgeCrossing& crossing = crossings[i];                        center += crossing.point;                        axisNormals[crossing.axis] += crossing.normal;                         red += qRed(crossing.color);                        green += qGreen(crossing.color);                        blue += qBlue(crossing.color);                                                if (displayHermite) {                            glm::vec3 start = info.minimum + (glm::vec3(clampedX, clampedY, clampedZ) +                                crossing.point) * scale;                            hermiteSegments.append(start);                            hermiteSegments.append(start + crossing.normal * scale);                        }                        

Lines 2001–2500 of 3173. Previous lines