Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 5 files). Show all
Unified · Split
| @@ -37,6 +37,9 @@ void MetavoxelSystem::init() { · 36 unmodified lines | ||
| 37 | 37 | _pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new BufferDataAttribute("pointBuffer")); |
| 38 | 38 | _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( |
| 39 | 39 | new BufferDataAttribute("heightfieldBuffer")); |
| 40 | + | |
| 41 | + _heightfieldBufferAttribute->setLODThresholdMultiplier( | |
| 42 | + AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier()); | |
| 40 | 43 | } |
| 41 | 44 | |
| 42 | 45 | MetavoxelLOD MetavoxelSystem::getLOD() { |
| @@ -382,7 +385,7 @@ float MetavoxelSystem::getHeightfieldHeight(const glm::vec3& location) { · 339 unmodified lines | ||
| 382 | 385 | class HeightfieldCursorRenderVisitor : public MetavoxelVisitor { |
| 383 | 386 | public: |
| 384 | 387 | |
| 385 | − HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds); | |
| 388 | + HeightfieldCursorRenderVisitor(const Box& bounds); | |
| 386 | 389 | |
| 387 | 390 | virtual int visit(MetavoxelInfo& info); |
| 388 | 391 | |
| @@ -391,9 +394,9 @@ private: · 2 unmodified lines | ||
| 391 | 394 | Box _bounds; |
| 392 | 395 | }; |
| 393 | 396 | |
| 394 | −HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) : | |
| 397 | +HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const Box& bounds) : | |
| 395 | 398 | MetavoxelVisitor(QVector<AttributePointer>() << |
| 396 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>(), lod), | |
| 399 | + Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()), | |
| 397 | 400 | _bounds(bounds) { |
| 398 | 401 | } |
| 399 | 402 | |
| @@ -433,7 +436,7 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r · 33 unmodified lines | ||
| 433 | 436 | glActiveTexture(GL_TEXTURE0); |
| 434 | 437 | |
| 435 | 438 | glm::vec3 extents(radius, radius, radius); |
| 436 | − HeightfieldCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents)); | |
| 439 | + HeightfieldCursorRenderVisitor visitor(Box(position - extents, position + extents)); | |
| 437 | 440 | guideToAugmented(visitor); |
| 438 | 441 | |
| 439 | 442 | DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release(); |
| @@ -601,11 +604,24 @@ HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, · 161 unmodified lines | ||
| 601 | 604 | const QByteArray& height, const QByteArray& color) : |
| 602 | 605 | _translation(translation), |
| 603 | 606 | _scale(scale), |
| 607 | + _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), | |
| 608 | + _colorBounds(_heightBounds), | |
| 604 | 609 | _height(height), |
| 605 | 610 | _color(color), |
| 606 | 611 | _heightTextureID(0), |
| 607 | 612 | _colorTextureID(0), |
| 608 | − _heightSize(glm::sqrt(height.size())) { | |
| 613 | + _heightSize(glm::sqrt(height.size())), | |
| 614 | + _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), | |
| 615 | + _colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)), | |
| 616 | + _colorIncrement(scale / (_colorSize - SHARED_EDGE)) { | |
| 617 | + | |
| 618 | + _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; | |
| 619 | + _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER; | |
| 620 | + _heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER); | |
| 621 | + _heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER); | |
| 622 | + | |
| 623 | + _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; | |
| 624 | + _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; | |
| 609 | 625 | } |
| 610 | 626 | |
| 611 | 627 | HeightfieldBuffer::~HeightfieldBuffer() { |
| @@ -807,17 +823,19 @@ BufferDataAttribute::BufferDataAttribute(const QString& name) : · 195 unmodified lines | ||
| 807 | 823 | } |
| 808 | 824 | |
| 809 | 825 | bool BufferDataAttribute::merge(void*& parent, void* children[], bool postRead) const { |
| 810 | − BufferDataPointer firstChild = decodeInline<BufferDataPointer>(children[0]); | |
| 811 | − for (int i = 1; i < MERGE_COUNT; i++) { | |
| 812 | − if (firstChild != decodeInline<BufferDataPointer>(children[i])) { | |
| 813 | − *(BufferDataPointer*)&parent = _defaultValue; | |
| 826 | + *(BufferDataPointer*)&parent = _defaultValue; | |
| 827 | + for (int i = 0; i < MERGE_COUNT; i++) { | |
| 828 | + if (decodeInline<BufferDataPointer>(children[i])) { | |
| 814 | 829 | return false; |
| 815 | 830 | } |
| 816 | 831 | } |
| 817 | − *(BufferDataPointer*)&parent = firstChild; | |
| 818 | 832 | return true; |
| 819 | 833 | } |
| 820 | 834 | |
| 835 | +AttributeValue BufferDataAttribute::inherit(const AttributeValue& parentValue) const { | |
| 836 | + return AttributeValue(parentValue.getAttribute()); | |
| 837 | +} | |
| 838 | + | |
| 821 | 839 | void DefaultMetavoxelRendererImplementation::init() { |
| 822 | 840 | if (!_pointProgram.isLinked()) { |
| 823 | 841 | _pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert"); |
| @@ -923,206 +941,279 @@ bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) { · 99 unmodified lines | ||
| 923 | 941 | return true; |
| 924 | 942 | } |
| 925 | 943 | |
| 926 | −class HeightfieldAugmentVisitor : public MetavoxelVisitor { | |
| 944 | +class HeightfieldFetchVisitor : public MetavoxelVisitor { | |
| 927 | 945 | public: |
| 928 | − | |
| 929 | − HeightfieldAugmentVisitor(const MetavoxelLOD& lod); | |
| 930 | 946 | |
| 931 | − virtual int visit(MetavoxelInfo& info); | |
| 932 | −}; | |
| 933 | − | |
| 934 | −HeightfieldAugmentVisitor::HeightfieldAugmentVisitor(const MetavoxelLOD& lod) : | |
| 935 | − MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | |
| 936 | − AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>() << | |
| 937 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod) { | |
| 938 | −} | |
| 939 | − | |
| 940 | −class BorderFetchVisitor : public MetavoxelVisitor { | |
| 941 | −public: | |
| 947 | + HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections); | |
| 942 | 948 | |
| 943 | − BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer); | |
| 949 | + void init(HeightfieldBuffer* buffer) { _buffer = buffer; } | |
| 944 | 950 | |
| 945 | 951 | virtual int visit(MetavoxelInfo& info); |
| 946 | 952 | |
| 947 | 953 | private: |
| 948 | 954 | |
| 955 | + const QVector<Box>& _intersections; | |
| 949 | 956 | HeightfieldBuffer* _buffer; |
| 950 | − Box _expandedBounds; | |
| 951 | − int _heightSize; | |
| 952 | − float _heightExtension; | |
| 953 | − int _colorSize; | |
| 954 | − float _colorExtension; | |
| 955 | − Box _colorBounds; | |
| 956 | 957 | }; |
| 957 | 958 | |
| 958 | −BorderFetchVisitor::BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer) : | |
| 959 | +HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) : | |
| 959 | 960 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << |
| 960 | 961 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod), |
| 961 | − _buffer(buffer), | |
| 962 | − _expandedBounds(_buffer->getTranslation(), _buffer->getTranslation() + | |
| 963 | − glm::vec3(_buffer->getScale(), _buffer->getScale(), _buffer->getScale())), | |
| 964 | − _heightSize(glm::sqrt(buffer->getHeight().size())), | |
| 965 | − _heightExtension(_buffer->getScale() / (_heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)), | |
| 966 | − _colorSize(glm::sqrt(buffer->getColor().size() / HeightfieldData::COLOR_BYTES)), | |
| 967 | − _colorBounds(_expandedBounds) { | |
| 968 | − | |
| 969 | − _expandedBounds.minimum.x -= _heightExtension * HeightfieldBuffer::HEIGHT_BORDER; | |
| 970 | − _expandedBounds.minimum.z -= _heightExtension * HeightfieldBuffer::HEIGHT_BORDER; | |
| 971 | − _expandedBounds.maximum.x += _heightExtension * (HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE); | |
| 972 | − _expandedBounds.maximum.z += _heightExtension * (HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE); | |
| 973 | − | |
| 974 | − if (_colorSize > 0) { | |
| 975 | − _colorExtension = buffer->getScale() / (_colorSize - HeightfieldBuffer::SHARED_EDGE); | |
| 976 | − _colorBounds.maximum.x += _colorExtension * HeightfieldBuffer::SHARED_EDGE; | |
| 977 | − _colorBounds.maximum.z += _colorExtension * HeightfieldBuffer::SHARED_EDGE; | |
| 978 | − } | |
| 962 | + _intersections(intersections) { | |
| 979 | 963 | } |
| 980 | 964 | |
| 981 | −int BorderFetchVisitor::visit(MetavoxelInfo& info) { | |
| 965 | +int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { | |
| 982 | 966 | Box bounds = info.getBounds(); |
| 983 | − if (!bounds.intersects(_expandedBounds)) { | |
| 967 | + const Box& heightBounds = _buffer->getHeightBounds(); | |
| 968 | + if (!bounds.intersects(heightBounds)) { | |
| 984 | 969 | return STOP_RECURSION; |
| 985 | 970 | } |
| 986 | 971 | if (!info.isLeaf && info.size > _buffer->getScale()) { |
| 987 | 972 | return DEFAULT_ORDER; |
| 988 | 973 | } |
| 989 | − if (_expandedBounds.contains(bounds)) { | |
| 990 | − return STOP_RECURSION; // this is the principal, which we've already filled in | |
| 991 | − } | |
| 992 | 974 | HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>(); |
| 993 | 975 | if (!height) { |
| 994 | 976 | return STOP_RECURSION; |
| 995 | 977 | } |
| 996 | − Box intersection = bounds.getIntersection(_expandedBounds); | |
| 997 | − int destX = glm::round((intersection.minimum.x - _expandedBounds.minimum.x) / _heightExtension); | |
| 998 | − int destY = glm::round((intersection.minimum.z - _expandedBounds.minimum.z) / _heightExtension); | |
| 999 | − int destWidth = glm::round((intersection.maximum.x - intersection.minimum.x) / _heightExtension); | |
| 1000 | − int destHeight = glm::round((intersection.maximum.z - intersection.minimum.z) / _heightExtension); | |
| 1001 | − char* dest = _buffer->getHeight().data() + destY * _heightSize + destX; | |
| 1002 | − | |
| 1003 | − const QByteArray& srcHeight = height->getContents(); | |
| 1004 | − int srcSize = glm::sqrt(srcHeight.size()); | |
| 1005 | − float srcExtension = info.size / srcSize; | |
| 1006 | − | |
| 1007 | − if (info.size == _buffer->getScale() && srcSize == (_heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) { | |
| 1008 | − // easy case: same resolution | |
| 1009 | − int srcX = glm::round((intersection.minimum.x - info.minimum.x) / srcExtension); | |
| 1010 | − int srcY = glm::round((intersection.minimum.z - info.minimum.z) / srcExtension); | |
| 978 | + foreach (const Box& intersection, _intersections) { | |
| 979 | + Box overlap = intersection.getIntersection(bounds); | |
| 980 | + if (overlap.isEmpty()) { | |
| 981 | + continue; | |
| 982 | + } | |
| 983 | + float heightIncrement = _buffer->getHeightIncrement(); | |
| 984 | + int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement; | |
| 985 | + int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement; | |
| 986 | + int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement); | |
| 987 | + int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement); | |
| 988 | + int heightSize = _buffer->getHeightSize(); | |
| 989 | + char* dest = _buffer->getHeight().data() + destY * heightSize + destX; | |
| 1011 | 990 | |
| 1012 | − const char* src = srcHeight.constData() + srcY * srcSize + srcX; | |
| 1013 | − for (int y = 0; y < destHeight; y++, src += srcSize, dest += _heightSize) { | |
| 1014 | − memcpy(dest, src, destWidth); | |
| 991 | + const QByteArray& srcHeight = height->getContents(); | |
| 992 | + int srcSize = glm::sqrt(srcHeight.size()); | |
| 993 | + float srcIncrement = info.size / srcSize; | |
| 994 | + | |
| 995 | + if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) { | |
| 996 | + // easy case: same resolution | |
| 997 | + int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 998 | + int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 999 | + | |
| 1000 | + const char* src = srcHeight.constData() + srcY * srcSize + srcX; | |
| 1001 | + for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) { | |
| 1002 | + memcpy(dest, src, destWidth); | |
| 1003 | + } | |
| 1004 | + } else { | |
| 1005 | + // more difficult: different resolutions | |
| 1006 | + float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1007 | + float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1008 | + float srcAdvance = heightIncrement / srcIncrement; | |
| 1009 | + int shift = 0; | |
| 1010 | + float size = _buffer->getScale(); | |
| 1011 | + while (size < info.size) { | |
| 1012 | + shift++; | |
| 1013 | + size *= 2.0f; | |
| 1014 | + } | |
| 1015 | + const int EIGHT_BIT_MAXIMUM = 255; | |
| 1016 | + int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale(); | |
| 1017 | + for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) { | |
| 1018 | + const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize; | |
| 1019 | + float lineSrcX = srcX; | |
| 1020 | + for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { | |
| 1021 | + *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM); | |
| 1022 | + } | |
| 1023 | + } | |
| 1015 | 1024 | } |
| 1016 | − } else { | |
| 1017 | − // more difficult: different resolutions | |
| 1018 | − float srcX = (intersection.minimum.x - info.minimum.x) / srcExtension; | |
| 1019 | − float srcY = (intersection.minimum.z - info.minimum.z) / srcExtension; | |
| 1020 | − float srcIncrement = _heightExtension / srcExtension; | |
| 1021 | − int shift = 0; | |
| 1022 | − float size = _buffer->getScale(); | |
| 1023 | − while (size < info.size) { | |
| 1024 | − shift++; | |
| 1025 | − size *= 2.0f; | |
| 1025 | + | |
| 1026 | + int colorSize = _buffer->getColorSize(); | |
| 1027 | + if (colorSize == 0) { | |
| 1028 | + return STOP_RECURSION; | |
| 1029 | + } | |
| 1030 | + HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>(); | |
| 1031 | + if (!color) { | |
| 1032 | + return STOP_RECURSION; | |
| 1026 | 1033 | } |
| 1027 | − const int EIGHT_BIT_MAXIMUM = 255; | |
| 1028 | − int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale(); | |
| 1029 | − for (int y = 0; y < destHeight; y++, dest += _heightSize, srcY += srcIncrement) { | |
| 1030 | − const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize; | |
| 1031 | − float lineSrcX = srcX; | |
| 1032 | − for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcIncrement) { | |
| 1033 | − *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM); | |
| 1034 | + const Box& colorBounds = _buffer->getColorBounds(); | |
| 1035 | + overlap = colorBounds.getIntersection(overlap); | |
| 1036 | + float colorIncrement = _buffer->getColorIncrement(); | |
| 1037 | + destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement; | |
| 1038 | + destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement; | |
| 1039 | + destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement); | |
| 1040 | + destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement); | |
| 1041 | + dest = _buffer->getColor().data() + (destY * colorSize + destX) * HeightfieldData::COLOR_BYTES; | |
| 1042 | + int destStride = colorSize * HeightfieldData::COLOR_BYTES; | |
| 1043 | + int destBytes = destWidth * HeightfieldData::COLOR_BYTES; | |
| 1044 | + | |
| 1045 | + const QByteArray& srcColor = color->getContents(); | |
| 1046 | + srcSize = glm::sqrt(srcColor.size() / HeightfieldData::COLOR_BYTES); | |
| 1047 | + int srcStride = srcSize * HeightfieldData::COLOR_BYTES; | |
| 1048 | + srcIncrement = info.size / srcSize; | |
| 1049 | + | |
| 1050 | + if (srcIncrement == colorIncrement) { | |
| 1051 | + // easy case: same resolution | |
| 1052 | + int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1053 | + int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1054 | + | |
| 1055 | + const char* src = srcColor.constData() + (srcY * srcSize + srcX) * HeightfieldData::COLOR_BYTES; | |
| 1056 | + for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) { | |
| 1057 | + memcpy(dest, src, destBytes); | |
| 1058 | + } | |
| 1059 | + } else { | |
| 1060 | + // more difficult: different resolutions | |
| 1061 | + float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1062 | + float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1063 | + float srcAdvance = colorIncrement / srcIncrement; | |
| 1064 | + for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) { | |
| 1065 | + const char* src = srcColor.constData() + (int)srcY * srcStride; | |
| 1066 | + float lineSrcX = srcX; | |
| 1067 | + for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += HeightfieldData::COLOR_BYTES, | |
| 1068 | + lineSrcX += srcAdvance) { | |
| 1069 | + const char* lineSrc = src + (int)lineSrcX * HeightfieldData::COLOR_BYTES; | |
| 1070 | + lineDest[0] = lineSrc[0]; | |
| 1071 | + lineDest[1] = lineSrc[1]; | |
| 1072 | + lineDest[2] = lineSrc[2]; | |
| 1073 | + } | |
| 1034 | 1074 | } |
| 1035 | 1075 | } |
| 1036 | 1076 | } |
| 1077 | + return STOP_RECURSION; | |
| 1078 | +} | |
| 1079 | + | |
| 1080 | +class HeightfieldRegionVisitor : public MetavoxelVisitor { | |
| 1081 | +public: | |
| 1037 | 1082 | |
| 1038 | − if (_colorSize == 0) { | |
| 1039 | − return STOP_RECURSION; | |
| 1040 | − } | |
| 1041 | − HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>(); | |
| 1042 | − if (!color) { | |
| 1043 | − return STOP_RECURSION; | |
| 1044 | − } | |
| 1045 | − intersection = bounds.getIntersection(_colorBounds); | |
| 1046 | − destX = glm::round((intersection.minimum.x - _colorBounds.minimum.x) / _colorExtension); | |
| 1047 | − destY = glm::round((intersection.minimum.z - _colorBounds.minimum.z) / _colorExtension); | |
| 1048 | − destWidth = glm::round((intersection.maximum.x - intersection.minimum.x) / _colorExtension); | |
| 1049 | − destHeight = glm::round((intersection.maximum.z - intersection.minimum.z) / _colorExtension); | |
| 1050 | − dest = _buffer->getColor().data() + (destY * _colorSize + destX) * HeightfieldData::COLOR_BYTES; | |
| 1051 | − int destStride = _colorSize * HeightfieldData::COLOR_BYTES; | |
| 1052 | − int destBytes = destWidth * HeightfieldData::COLOR_BYTES; | |
| 1053 | − | |
| 1054 | − const QByteArray& srcColor = color->getContents(); | |
| 1055 | − srcSize = glm::sqrt(srcColor.size() / HeightfieldData::COLOR_BYTES); | |
| 1056 | − int srcStride = srcSize * HeightfieldData::COLOR_BYTES; | |
| 1057 | − srcExtension = info.size / srcSize; | |
| 1083 | + QVector<Box> regions; | |
| 1084 | + Box regionBounds; | |
| 1085 | + | |
| 1086 | + HeightfieldRegionVisitor(const MetavoxelLOD& lod); | |
| 1058 | 1087 | |
| 1059 | − if (srcExtension == _colorExtension) { | |
| 1060 | − // easy case: same resolution | |
| 1061 | − int srcX = glm::round((intersection.minimum.x - info.minimum.x) / srcExtension); | |
| 1062 | − int srcY = glm::round((intersection.minimum.z - info.minimum.z) / srcExtension); | |
| 1088 | + virtual int visit(MetavoxelInfo& info); | |
| 1089 | + | |
| 1090 | +private: | |
| 1091 | + | |
| 1092 | + void addRegion(const Box& unextended, const Box& extended); | |
| 1093 | + | |
| 1094 | + QVector<Box> _intersections; | |
| 1095 | + HeightfieldFetchVisitor _fetchVisitor; | |
| 1096 | +}; | |
| 1097 | + | |
| 1098 | +HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : | |
| 1099 | + MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | |
| 1100 | + AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << | |
| 1101 | + Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << | |
| 1102 | + Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), | |
| 1103 | + regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)), | |
| 1104 | + _fetchVisitor(lod, _intersections) { | |
| 1105 | +} | |
| 1106 | + | |
| 1107 | +int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) { | |
| 1108 | + if (!info.isLeaf) { | |
| 1109 | + return DEFAULT_ORDER; | |
| 1110 | + } | |
| 1111 | + HeightfieldBuffer* buffer = NULL; | |
| 1112 | + HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>(); | |
| 1113 | + if (height) { | |
| 1114 | + const QByteArray& heightContents = height->getContents(); | |
| 1115 | + int size = glm::sqrt(heightContents.size()); | |
| 1116 | + int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION; | |
| 1117 | + int heightContentsSize = extendedSize * extendedSize; | |
| 1063 | 1118 | |
| 1064 | − const char* src = srcColor.constData() + (srcY * srcSize + srcX) * HeightfieldData::COLOR_BYTES; | |
| 1065 | − for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) { | |
| 1066 | − memcpy(dest, src, destBytes); | |
| 1119 | + HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>(); | |
| 1120 | + int colorContentsSize = 0; | |
| 1121 | + if (color) { | |
| 1122 | + const QByteArray& colorContents = color->getContents(); | |
| 1123 | + int colorSize = glm::sqrt(colorContents.size() / HeightfieldData::COLOR_BYTES); | |
| 1124 | + int extendedColorSize = colorSize + HeightfieldBuffer::SHARED_EDGE; | |
| 1125 | + colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES; | |
| 1067 | 1126 | } |
| 1068 | − } else { | |
| 1069 | − // more difficult: different resolutions | |
| 1070 | − float srcX = (intersection.minimum.x - info.minimum.x) / srcExtension; | |
| 1071 | − float srcY = (intersection.minimum.z - info.minimum.z) / srcExtension; | |
| 1072 | − float srcIncrement = _colorExtension / srcExtension; | |
| 1073 | − for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcIncrement) { | |
| 1074 | − const char* src = srcColor.constData() + (int)srcY * srcStride; | |
| 1075 | − float lineSrcX = srcX; | |
| 1076 | − for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += HeightfieldData::COLOR_BYTES, | |
| 1077 | − lineSrcX += srcIncrement) { | |
| 1078 | − const char* lineSrc = src + (int)lineSrcX * HeightfieldData::COLOR_BYTES; | |
| 1079 | − lineDest[0] = lineSrc[0]; | |
| 1080 | − lineDest[1] = lineSrc[1]; | |
| 1081 | − lineDest[2] = lineSrc[2]; | |
| 1082 | − } | |
| 1127 | + | |
| 1128 | + const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>( | |
| 1129 | + info.inputValues.at(2).getInlineValue<BufferDataPointer>().data()); | |
| 1130 | + Box bounds = info.getBounds(); | |
| 1131 | + if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && | |
| 1132 | + existingBuffer->getColor().size() == colorContentsSize) { | |
| 1133 | + // we already have a buffer of the correct resolution | |
| 1134 | + addRegion(bounds, existingBuffer->getHeightBounds()); | |
| 1135 | + return STOP_RECURSION; | |
| 1083 | 1136 | } |
| 1137 | + // we must create a new buffer and update its borders | |
| 1138 | + buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), | |
| 1139 | + QByteArray(colorContentsSize, 0)); | |
| 1140 | + const Box& heightBounds = buffer->getHeightBounds(); | |
| 1141 | + addRegion(bounds, heightBounds); | |
| 1142 | + | |
| 1143 | + _intersections.clear(); | |
| 1144 | + _intersections.append(Box(heightBounds.minimum, | |
| 1145 | + glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z))); | |
| 1146 | + _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z), | |
| 1147 | + glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z))); | |
| 1148 | + _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z), | |
| 1149 | + heightBounds.maximum)); | |
| 1150 | + _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z), | |
| 1151 | + glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z))); | |
| 1152 | + | |
| 1153 | + _fetchVisitor.init(buffer); | |
| 1154 | + _data->guide(_fetchVisitor); | |
| 1084 | 1155 | } |
| 1085 | − | |
| 1156 | + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); | |
| 1086 | 1157 | return STOP_RECURSION; |
| 1087 | 1158 | } |
| 1088 | 1159 | |
| 1089 | −int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) { | |
| 1090 | − if (info.isLeaf) { | |
| 1091 | − HeightfieldBuffer* buffer = NULL; | |
| 1092 | − HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>(); | |
| 1093 | − if (height) { | |
| 1094 | − const QByteArray& heightContents = height->getContents(); | |
| 1095 | − int size = glm::sqrt(heightContents.size()); | |
| 1096 | − int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION; | |
| 1097 | − QByteArray extendedHeightContents(extendedSize * extendedSize, 0); | |
| 1098 | − char* dest = extendedHeightContents.data() + (extendedSize + 1) * HeightfieldBuffer::HEIGHT_BORDER; | |
| 1099 | − const char* src = heightContents.constData(); | |
| 1100 | − for (int z = 0; z < size; z++, src += size, dest += extendedSize) { | |
| 1101 | − memcpy(dest, src, size); | |
| 1102 | − } | |
| 1103 | − QByteArray extendedColorContents; | |
| 1104 | − HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>(); | |
| 1105 | − if (color) { | |
| 1106 | − const QByteArray& colorContents = color->getContents(); | |
| 1107 | − int colorSize = glm::sqrt(colorContents.size() / HeightfieldData::COLOR_BYTES); | |
| 1108 | − int extendedColorSize = colorSize + HeightfieldBuffer::SHARED_EDGE; | |
| 1109 | − extendedColorContents = QByteArray(extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES, 0); | |
| 1110 | − char* dest = extendedColorContents.data(); | |
| 1111 | − const char* src = colorContents.constData(); | |
| 1112 | − int srcStride = colorSize * HeightfieldData::COLOR_BYTES; | |
| 1113 | − int destStride = extendedColorSize * HeightfieldData::COLOR_BYTES; | |
| 1114 | − for (int z = 0; z < colorSize; z++, src += srcStride, dest += destStride) { | |
| 1115 | − memcpy(dest, src, srcStride); | |
| 1116 | − } | |
| 1117 | − } | |
| 1118 | − buffer = new HeightfieldBuffer(info.minimum, info.size, extendedHeightContents, extendedColorContents); | |
| 1119 | − BorderFetchVisitor visitor(_lod, buffer); | |
| 1120 | − _data->guide(visitor); | |
| 1160 | +void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) { | |
| 1161 | + regions.append(unextended); | |
| 1162 | + regionBounds.add(extended); | |
| 1163 | +} | |
| 1164 | + | |
| 1165 | +class HeightfieldUpdateVisitor : public MetavoxelVisitor { | |
| 1166 | +public: | |
| 1167 | + | |
| 1168 | + HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, const Box& regionBounds); | |
| 1169 | + | |
| 1170 | + virtual int visit(MetavoxelInfo& info); | |
| 1171 | + | |
| 1172 | +private: | |
| 1173 | + | |
| 1174 | + const QVector<Box>& _regions; | |
| 1175 | + const Box& _regionBounds; | |
| 1176 | + QVector<Box> _intersections; | |
| 1177 | + HeightfieldFetchVisitor _fetchVisitor; | |
| 1178 | +}; | |
| 1179 | + | |
| 1180 | +HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, | |
| 1181 | + const Box& regionBounds) : | |
| 1182 | + MetavoxelVisitor(QVector<AttributePointer>() << | |
| 1183 | + Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << | |
| 1184 | + Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), | |
| 1185 | + _regions(regions), | |
| 1186 | + _regionBounds(regionBounds), | |
| 1187 | + _fetchVisitor(lod, _intersections) { | |
| 1188 | +} | |
| 1189 | + | |
| 1190 | +int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { | |
| 1191 | + if (!info.getBounds().intersects(_regionBounds)) { | |
| 1192 | + return STOP_RECURSION; | |
| 1193 | + } | |
| 1194 | + if (!info.isLeaf) { | |
| 1195 | + return DEFAULT_ORDER; | |
| 1196 | + } | |
| 1197 | + const HeightfieldBuffer* buffer = static_cast<const HeightfieldBuffer*>( | |
| 1198 | + info.inputValues.at(0).getInlineValue<BufferDataPointer>().data()); | |
| 1199 | + if (!buffer) { | |
| 1200 | + return STOP_RECURSION; | |
| 1201 | + } | |
| 1202 | + _intersections.clear(); | |
| 1203 | + foreach (const Box& region, _regions) { | |
| 1204 | + if (region.intersects(buffer->getHeightBounds())) { | |
| 1205 | + _intersections.append(region.getIntersection(buffer->getHeightBounds())); | |
| 1121 | 1206 | } |
| 1122 | − info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); | |
| 1207 | + } | |
| 1208 | + if (_intersections.isEmpty()) { | |
| 1123 | 1209 | return STOP_RECURSION; |
| 1124 | 1210 | } |
| 1125 | − return DEFAULT_ORDER; | |
| 1211 | + HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, | |
| 1212 | + buffer->getHeight(), buffer->getColor()); | |
| 1213 | + _fetchVisitor.init(newBuffer); | |
| 1214 | + _data->guide(_fetchVisitor); | |
| 1215 | + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); | |
| 1216 | + return STOP_RECURSION; | |
| 1126 | 1217 | } |
| 1127 | 1218 | |
| 1128 | 1219 | void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous, |
| @@ -1149,8 +1240,12 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const · 20 unmodified lines | ||
| 1149 | 1240 | PointAugmentVisitor pointAugmentVisitor(lod); |
| 1150 | 1241 | data.guideToDifferent(expandedPrevious, pointAugmentVisitor); |
| 1151 | 1242 | |
| 1152 | − HeightfieldAugmentVisitor heightfieldAugmentVisitor(lod); | |
| 1153 | − data.guideToDifferent(expandedPrevious, heightfieldAugmentVisitor); | |
| 1243 | + HeightfieldRegionVisitor heightfieldRegionVisitor(lod); | |
| 1244 | + data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor); | |
| 1245 | + | |
| 1246 | + HeightfieldUpdateVisitor heightfieldUpdateVisitor(lod, heightfieldRegionVisitor.regions, | |
| 1247 | + heightfieldRegionVisitor.regionBounds); | |
| 1248 | + data.guide(heightfieldUpdateVisitor); | |
| 1154 | 1249 | } |
| 1155 | 1250 | |
| 1156 | 1251 | class SpannerSimulateVisitor : public SpannerVisitor { |
| @@ -1222,7 +1317,7 @@ bool SpannerRenderVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, · 65 unmodified lines | ||
| 1222 | 1317 | class BufferRenderVisitor : public MetavoxelVisitor { |
| 1223 | 1318 | public: |
| 1224 | 1319 | |
| 1225 | − BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod); | |
| 1320 | + BufferRenderVisitor(const AttributePointer& attribute); | |
| 1226 | 1321 | |
| 1227 | 1322 | virtual int visit(MetavoxelInfo& info); |
| 1228 | 1323 | |
| @@ -1232,8 +1327,8 @@ private: · 3 unmodified lines | ||
| 1232 | 1327 | int _containmentDepth; |
| 1233 | 1328 | }; |
| 1234 | 1329 | |
| 1235 | −BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod) : | |
| 1236 | − MetavoxelVisitor(QVector<AttributePointer>() << attribute, QVector<AttributePointer>(), lod), | |
| 1330 | +BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : | |
| 1331 | + MetavoxelVisitor(QVector<AttributePointer>() << attribute), | |
| 1237 | 1332 | _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), |
| 1238 | 1333 | _containmentDepth(INT_MAX) { |
| 1239 | 1334 | } |
| @@ -1247,11 +1342,14 @@ int BufferRenderVisitor::visit(MetavoxelInfo& info) { · 7 unmodified lines | ||
| 1247 | 1342 | } |
| 1248 | 1343 | _containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX; |
| 1249 | 1344 | } |
| 1345 | + if (!info.isLeaf) { | |
| 1346 | + return _order; | |
| 1347 | + } | |
| 1250 | 1348 | BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>(); |
| 1251 | 1349 | if (buffer) { |
| 1252 | 1350 | buffer->render(); |
| 1253 | 1351 | } |
| 1254 | − return info.isLeaf ? STOP_RECURSION : _order; | |
| 1352 | + return STOP_RECURSION; | |
| 1255 | 1353 | } |
| 1256 | 1354 | |
| 1257 | 1355 | void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod) { |
| @@ -1280,7 +1378,7 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox · 22 unmodified lines | ||
| 1280 | 1378 | |
| 1281 | 1379 | glDisable(GL_BLEND); |
| 1282 | 1380 | |
| 1283 | − BufferRenderVisitor pointRenderVisitor(Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod); | |
| 1381 | + BufferRenderVisitor pointRenderVisitor(Application::getInstance()->getMetavoxels()->getPointBufferAttribute()); | |
| 1284 | 1382 | data.guide(pointRenderVisitor); |
| 1285 | 1383 | |
| 1286 | 1384 | glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB); |
| @@ -1300,8 +1398,7 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox · 13 unmodified lines | ||
| 1300 | 1398 | |
| 1301 | 1399 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
| 1302 | 1400 | |
| 1303 | − BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), | |
| 1304 | − lod); | |
| 1401 | + BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()); | |
| 1305 | 1402 | data.guide(heightfieldRenderVisitor); |
| 1306 | 1403 | |
| 1307 | 1404 | _heightfieldProgram.release(); |