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 | class BorderFetchVisitor : public MetavoxelVisitor { | 672 | class BorderFetchVisitor : public MetavoxelVisitor { |
| 673 | public: | 673 | public: |
| 674 | 674 | ||
| 675 | BorderFetchVisitor(const MetavoxelLOD& lod, QByteArray& height); | 675 | BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer); |
| 676 | 676 | ||
| 677 | virtual int visit(MetavoxelInfo& info); | 677 | virtual int visit(MetavoxelInfo& info); |
| 678 | 678 | ||
| 679 | private: | 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) : | 690 | BorderFetchVisitor::BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer) : |
| 685 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute(), | 691 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << |
| 686 | QVector<AttributePointer>(), lod), | 692 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod), |
| 687 | _height(height) { | 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 | int BorderFetchVisitor::visit(MetavoxelInfo& info) { | 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 | return DEFAULT_ORDER; | 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 | return STOP_RECURSION; | 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 | buffer = new HeightfieldBuffer(info.minimum, info.size, extendedHeightContents, extendedColorContents); | 850 | buffer = new HeightfieldBuffer(info.minimum, info.size, extendedHeightContents, extendedColorContents); |
| 851 | BorderFetchVisitor visitor(_lod, buffer); | ||
| 852 | _data->guide(visitor); | ||
| 727 | } | 853 | } |
| 728 | info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); | 854 | info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); |
| 729 | return STOP_RECURSION; | 855 | return STOP_RECURSION; |