Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 4 files). Show all
Unified · Split
| @@ -672,25 +672,149 @@ HeightfieldAugmentVisitor::HeightfieldAugmentVisitor(const MetavoxelLOD& lod) : · 671 unmodified lines | ||
| 672 | 672 | class BorderFetchVisitor : public MetavoxelVisitor { |
| 673 | 673 | public: |
| 674 | 674 | |
| 675 | − BorderFetchVisitor(const MetavoxelLOD& lod, QByteArray& height); | |
| 675 | + BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer); | |
| 676 | 676 | |
| 677 | 677 | virtual int visit(MetavoxelInfo& info); |
| 678 | 678 | |
| 679 | 679 | private: |
| 680 | 680 | |
| 681 | − QByteArray& _height; | |
| 681 | + HeightfieldBuffer* _buffer; | |
| 682 | + Box _expandedBounds; | |
| 683 | + int _heightSize; | |
| 684 | + float _heightExtension; | |
| 685 | + int _colorSize; | |
| 686 | + float _colorExtension; | |
| 687 | + Box _colorBounds; | |
| 682 | 688 | }; |
| 683 | 689 | |
| 684 | −BorderFetchVisitor::BorderFetchVisitor(const MetavoxelLOD& lod, QByteArray& height) : | |
| 685 | − MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute(), | |
| 686 | − QVector<AttributePointer>(), lod), | |
| 687 | − _height(height) { | |
| 690 | +BorderFetchVisitor::BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer) : | |
| 691 | + MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | |
| 692 | + AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod), | |
| 693 | + _buffer(buffer), | |
| 694 | + _expandedBounds(_buffer->getTranslation(), _buffer->getTranslation() + | |
| 695 | + glm::vec3(_buffer->getScale(), _buffer->getScale(), _buffer->getScale())), | |
| 696 | + _heightSize(glm::sqrt(buffer->getHeight().size())), | |
| 697 | + _heightExtension(_buffer->getScale() / (_heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)), | |
| 698 | + _colorSize(glm::sqrt(buffer->getColor().size() / HeightfieldData::COLOR_BYTES)), | |
| 699 | + _colorBounds(_expandedBounds) { | |
| 700 | + | |
| 701 | + _expandedBounds.minimum.x -= _heightExtension * HeightfieldBuffer::HEIGHT_BORDER; | |
| 702 | + _expandedBounds.minimum.z -= _heightExtension * HeightfieldBuffer::HEIGHT_BORDER; | |
| 703 | + _expandedBounds.maximum.x += _heightExtension * (HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE); | |
| 704 | + _expandedBounds.maximum.z += _heightExtension * (HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE); | |
| 705 | + | |
| 706 | + if (_colorSize > 0) { | |
| 707 | + _colorExtension = buffer->getScale() / (_colorSize - HeightfieldBuffer::SHARED_EDGE); | |
| 708 | + _colorBounds.maximum.x += _colorExtension * HeightfieldBuffer::SHARED_EDGE; | |
| 709 | + _colorBounds.maximum.z += _colorExtension * HeightfieldBuffer::SHARED_EDGE; | |
| 710 | + } | |
| 688 | 711 | } |
| 689 | 712 | |
| 690 | 713 | int BorderFetchVisitor::visit(MetavoxelInfo& info) { |
| 691 | − if (!info.isLeaf) { | |
| 714 | + Box bounds = info.getBounds(); | |
| 715 | + if (!bounds.intersects(_expandedBounds)) { | |
| 716 | + return STOP_RECURSION; | |
| 717 | + } | |
| 718 | + if (!info.isLeaf && info.size > _buffer->getScale()) { | |
| 692 | 719 | return DEFAULT_ORDER; |
| 693 | 720 | } |
| 721 | + if (_expandedBounds.contains(bounds)) { | |
| 722 | + return STOP_RECURSION; // this is the principal, which we've already filled in | |
| 723 | + } | |
| 724 | + HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>(); | |
| 725 | + if (!height) { | |
| 726 | + return STOP_RECURSION; | |
| 727 | + } | |
| 728 | + Box intersection = bounds.getIntersection(_expandedBounds); | |
| 729 | + int destX = glm::round((intersection.minimum.x - _expandedBounds.minimum.x) / _heightExtension); | |
| 730 | + int destY = glm::round((intersection.minimum.z - _expandedBounds.minimum.z) / _heightExtension); | |
| 731 | + int destWidth = glm::round((intersection.maximum.x - intersection.minimum.x) / _heightExtension); | |
| 732 | + int destHeight = glm::round((intersection.maximum.z - intersection.minimum.z) / _heightExtension); | |
| 733 | + char* dest = _buffer->getHeight().data() + destY * _heightSize + destX; | |
| 734 | + | |
| 735 | + const QByteArray& srcHeight = height->getContents(); | |
| 736 | + int srcSize = glm::sqrt(srcHeight.size()); | |
| 737 | + float srcExtension = info.size / srcSize; | |
| 738 | + | |
| 739 | + if (info.size == _buffer->getScale() && srcSize == (_heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) { | |
| 740 | + // easy case: same resolution | |
| 741 | + int srcX = glm::round((intersection.minimum.x - info.minimum.x) / srcExtension); | |
| 742 | + int srcY = glm::round((intersection.minimum.z - info.minimum.z) / srcExtension); | |
| 743 | + | |
| 744 | + const char* src = srcHeight.constData() + srcY * srcSize + srcX; | |
| 745 | + for (int y = 0; y < destHeight; y++, src += srcSize, dest += _heightSize) { | |
| 746 | + memcpy(dest, src, destWidth); | |
| 747 | + } | |
| 748 | + } else { | |
| 749 | + // more difficult: different resolutions | |
| 750 | + float srcX = (intersection.minimum.x - info.minimum.x) / srcExtension; | |
| 751 | + float srcY = (intersection.minimum.z - info.minimum.z) / srcExtension; | |
| 752 | + float srcIncrement = _heightExtension / srcExtension; | |
| 753 | + int shift = 0; | |
| 754 | + float size = _buffer->getScale(); | |
| 755 | + while (size < info.size) { | |
| 756 | + shift++; | |
| 757 | + size *= 2.0f; | |
| 758 | + } | |
| 759 | + const int EIGHT_BIT_MAXIMUM = 255; | |
| 760 | + int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale(); | |
| 761 | + for (int y = 0; y < destHeight; y++, dest += _heightSize, srcY += srcIncrement) { | |
| 762 | + const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize; | |
| 763 | + float lineSrcX = srcX; | |
| 764 | + for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcIncrement) { | |
| 765 | + *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM); | |
| 766 | + } | |
| 767 | + } | |
| 768 | + } | |
| 769 | + | |
| 770 | + if (_colorSize == 0) { | |
| 771 | + return STOP_RECURSION; | |
| 772 | + } | |
| 773 | + HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>(); | |
| 774 | + if (!color) { | |
| 775 | + return STOP_RECURSION; | |
| 776 | + } | |
| 777 | + intersection = bounds.getIntersection(_colorBounds); | |
| 778 | + destX = glm::round((intersection.minimum.x - _colorBounds.minimum.x) / _colorExtension); | |
| 779 | + destY = glm::round((intersection.minimum.z - _colorBounds.minimum.z) / _colorExtension); | |
| 780 | + destWidth = glm::round((intersection.maximum.x - intersection.minimum.x) / _colorExtension); | |
| 781 | + destHeight = glm::round((intersection.maximum.z - intersection.minimum.z) / _colorExtension); | |
| 782 | + dest = _buffer->getColor().data() + (destY * _colorSize + destX) * HeightfieldData::COLOR_BYTES; | |
| 783 | + int destStride = _colorSize * HeightfieldData::COLOR_BYTES; | |
| 784 | + int destBytes = destWidth * HeightfieldData::COLOR_BYTES; | |
| 785 | + | |
| 786 | + const QByteArray& srcColor = color->getContents(); | |
| 787 | + srcSize = glm::sqrt(srcColor.size() / HeightfieldData::COLOR_BYTES); | |
| 788 | + int srcStride = srcSize * HeightfieldData::COLOR_BYTES; | |
| 789 | + srcExtension = info.size / srcSize; | |
| 790 | + | |
| 791 | + if (srcExtension == _colorExtension) { | |
| 792 | + // easy case: same resolution | |
| 793 | + int srcX = glm::round((intersection.minimum.x - info.minimum.x) / srcExtension); | |
| 794 | + int srcY = glm::round((intersection.minimum.z - info.minimum.z) / srcExtension); | |
| 795 | + | |
| 796 | + const char* src = srcColor.constData() + (srcY * srcSize + srcX) * HeightfieldData::COLOR_BYTES; | |
| 797 | + for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) { | |
| 798 | + memcpy(dest, src, destBytes); | |
| 799 | + } | |
| 800 | + } else { | |
| 801 | + // more difficult: different resolutions | |
| 802 | + float srcX = (intersection.minimum.x - info.minimum.x) / srcExtension; | |
| 803 | + float srcY = (intersection.minimum.z - info.minimum.z) / srcExtension; | |
| 804 | + float srcIncrement = _colorExtension / srcExtension; | |
| 805 | + for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcIncrement) { | |
| 806 | + const char* src = srcColor.constData() + (int)srcY * srcStride; | |
| 807 | + float lineSrcX = srcX; | |
| 808 | + for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += HeightfieldData::COLOR_BYTES, | |
| 809 | + lineSrcX += srcIncrement) { | |
| 810 | + const char* lineSrc = src + (int)lineSrcX * HeightfieldData::COLOR_BYTES; | |
| 811 | + lineDest[0] = lineSrc[0]; | |
| 812 | + lineDest[1] = lineSrc[1]; | |
| 813 | + lineDest[2] = lineSrc[2]; | |
| 814 | + } | |
| 815 | + } | |
| 816 | + } | |
| 817 | + | |
| 694 | 818 | return STOP_RECURSION; |
| 695 | 819 | } |
| 696 | 820 | |
| @@ -724,6 +848,8 @@ int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) { · 27 unmodified lines | ||
| 724 | 848 | } |
| 725 | 849 | } |
| 726 | 850 | buffer = new HeightfieldBuffer(info.minimum, info.size, extendedHeightContents, extendedColorContents); |
| 851 | + BorderFetchVisitor visitor(_lod, buffer); | |
| 852 | + _data->guide(visitor); | |
| 727 | 853 | } |
| 728 | 854 | info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); |
| 729 | 855 | return STOP_RECURSION; |