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