Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 2 files). Show all
Unified · Split
| @@ -58,11 +58,6 @@ void MetavoxelSystem::init() { · 57 unmodified lines | ||
| 58 | 58 | MetavoxelClientManager::init(); |
| 59 | 59 | DefaultMetavoxelRendererImplementation::init(); |
| 60 | 60 | |
| 61 | − _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( | |
| 62 | − new BufferDataAttribute("heightfieldBuffer")); | |
| 63 | − _heightfieldBufferAttribute->setLODThresholdMultiplier( | |
| 64 | − AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier()); | |
| 65 | − | |
| 66 | 61 | _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( |
| 67 | 62 | new BufferDataAttribute("voxelBuffer")); |
| 68 | 63 | _voxelBufferAttribute->setLODThresholdMultiplier( |
| @@ -375,12 +370,6 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) · 306 unmodified lines | ||
| 375 | 370 | glDepthFunc(GL_LESS); |
| 376 | 371 | } |
| 377 | 372 | |
| 378 | −void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) { | |
| 379 | − glDeleteTextures(1, (GLuint*)&heightID); | |
| 380 | − glDeleteTextures(1, (GLuint*)&colorID); | |
| 381 | − glDeleteTextures(1, (GLuint*)&textureID); | |
| 382 | −} | |
| 383 | − | |
| 384 | 373 | class MaterialEditApplier : public SignalHandler { |
| 385 | 374 | public: |
| 386 | 375 | |
| @@ -670,357 +659,12 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { · 283 unmodified lines | ||
| 670 | 659 | BufferData::~BufferData() { |
| 671 | 660 | } |
| 672 | 661 | |
| 673 | −const int HeightfieldBuffer::HEIGHT_BORDER = 1; | |
| 674 | −const int HeightfieldBuffer::SHARED_EDGE = 1; | |
| 675 | −const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE; | |
| 676 | − | |
| 677 | −HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, | |
| 678 | − const QByteArray& height, const QByteArray& color, const QByteArray& material, | |
| 679 | − const QVector<SharedObjectPointer>& materials) : | |
| 680 | − _translation(translation), | |
| 681 | − _scale(scale), | |
| 682 | − _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), | |
| 683 | − _colorBounds(_heightBounds), | |
| 684 | − _materialBounds(_heightBounds), | |
| 685 | − _height(height), | |
| 686 | − _color(color), | |
| 687 | − _material(material), | |
| 688 | − _materials(materials), | |
| 689 | − _heightTextureID(0), | |
| 690 | − _colorTextureID(0), | |
| 691 | − _materialTextureID(0), | |
| 692 | − _heightSize(glm::sqrt((float)height.size())), | |
| 693 | − _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), | |
| 694 | − _colorSize(glm::sqrt((float)color.size() / DataBlock::COLOR_BYTES)), | |
| 695 | − _colorIncrement(scale / (_colorSize - SHARED_EDGE)), | |
| 696 | − _materialSize(glm::sqrt((float)material.size())), | |
| 697 | − _materialIncrement(scale / (_materialSize - SHARED_EDGE)) { | |
| 698 | − | |
| 699 | − _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; | |
| 700 | − _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER; | |
| 701 | − _heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER); | |
| 702 | − _heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER); | |
| 703 | − | |
| 704 | − _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; | |
| 705 | − _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; | |
| 706 | − | |
| 707 | − _materialBounds.maximum.x += _materialIncrement * SHARED_EDGE; | |
| 708 | − _materialBounds.maximum.z += _materialIncrement * SHARED_EDGE; | |
| 709 | −} | |
| 710 | − | |
| 711 | −HeightfieldBuffer::~HeightfieldBuffer() { | |
| 712 | − // the textures have to be deleted on the main thread (for its opengl context) | |
| 713 | − if (QThread::currentThread() != Application::getInstance()->thread()) { | |
| 714 | − QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", | |
| 715 | − Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID)); | |
| 716 | − } else { | |
| 717 | − glDeleteTextures(1, &_heightTextureID); | |
| 718 | − glDeleteTextures(1, &_colorTextureID); | |
| 719 | − glDeleteTextures(1, &_materialTextureID); | |
| 720 | − } | |
| 721 | −} | |
| 722 | − | |
| 723 | −QByteArray HeightfieldBuffer::getUnextendedHeight() const { | |
| 724 | − int srcSize = glm::sqrt(float(_height.size())); | |
| 725 | − int destSize = srcSize - 3; | |
| 726 | − QByteArray unextended(destSize * destSize, 0); | |
| 727 | − const char* src = _height.constData() + srcSize + 1; | |
| 728 | − char* dest = unextended.data(); | |
| 729 | − for (int z = 0; z < destSize; z++, src += srcSize, dest += destSize) { | |
| 730 | − memcpy(dest, src, destSize); | |
| 731 | − } | |
| 732 | − return unextended; | |
| 733 | −} | |
| 734 | − | |
| 735 | −QByteArray HeightfieldBuffer::getUnextendedColor(int x, int y) const { | |
| 736 | − int unextendedSize = _heightSize - HEIGHT_EXTENSION; | |
| 737 | − QByteArray unextended(unextendedSize * unextendedSize * DataBlock::COLOR_BYTES, 0); | |
| 738 | − char* dest = unextended.data(); | |
| 739 | − const char* src = _color.constData() + (y * _colorSize + x) * unextendedSize * DataBlock::COLOR_BYTES; | |
| 740 | − for (int z = 0; z < unextendedSize; z++, dest += unextendedSize * DataBlock::COLOR_BYTES, | |
| 741 | − src += _colorSize * DataBlock::COLOR_BYTES) { | |
| 742 | − memcpy(dest, src, unextendedSize * DataBlock::COLOR_BYTES); | |
| 743 | − } | |
| 744 | − return unextended; | |
| 745 | −} | |
| 746 | − | |
| 747 | −class HeightfieldPoint { | |
| 748 | −public: | |
| 749 | − glm::vec2 textureCoord; | |
| 750 | − glm::vec3 vertex; | |
| 751 | −}; | |
| 752 | − | |
| 753 | 662 | const int SPLAT_COUNT = 4; |
| 754 | 663 | const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; |
| 755 | 664 | |
| 756 | 665 | static const int EIGHT_BIT_MAXIMUM = 255; |
| 757 | 666 | static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; |
| 758 | 667 | |
| 759 | −void HeightfieldBuffer::render(bool cursor) { | |
| 760 | − // initialize textures, etc. on first render | |
| 761 | − if (_heightTextureID == 0) { | |
| 762 | − glGenTextures(1, &_heightTextureID); | |
| 763 | − glBindTexture(GL_TEXTURE_2D, _heightTextureID); | |
| 764 | − glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |
| 765 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 766 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 767 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 768 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 769 | − glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, _heightSize, _heightSize, 0, | |
| 770 | − GL_LUMINANCE, GL_UNSIGNED_BYTE, _height.constData()); | |
| 771 | − | |
| 772 | − glGenTextures(1, &_colorTextureID); | |
| 773 | − glBindTexture(GL_TEXTURE_2D, _colorTextureID); | |
| 774 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 775 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 776 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 777 | − if (_color.isEmpty()) { | |
| 778 | − const quint8 WHITE_COLOR[] = { 255, 255, 255 }; | |
| 779 | − glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR); | |
| 780 | − | |
| 781 | − } else { | |
| 782 | − int colorSize = glm::sqrt(float(_color.size() / DataBlock::COLOR_BYTES)); | |
| 783 | − glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData()); | |
| 784 | − } | |
| 785 | − | |
| 786 | − if (!_material.isEmpty()) { | |
| 787 | − glGenTextures(1, &_materialTextureID); | |
| 788 | − glBindTexture(GL_TEXTURE_2D, _materialTextureID); | |
| 789 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 790 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 791 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 792 | − glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 793 | − int materialSize = glm::sqrt(float(_material.size())); | |
| 794 | − glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, materialSize, materialSize, 0, | |
| 795 | − GL_LUMINANCE, GL_UNSIGNED_BYTE, _material.constData()); | |
| 796 | − | |
| 797 | − _networkTextures.resize(_materials.size()); | |
| 798 | − for (int i = 0; i < _materials.size(); i++) { | |
| 799 | − const SharedObjectPointer material = _materials.at(i); | |
| 800 | − if (material) { | |
| 801 | − _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( | |
| 802 | − static_cast<MaterialObject*>(material.data())->getDiffuse(), SPLAT_TEXTURE); | |
| 803 | − } | |
| 804 | − } | |
| 805 | − } | |
| 806 | − } | |
| 807 | − // create the buffer objects lazily | |
| 808 | − int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; | |
| 809 | − int vertexCount = _heightSize * _heightSize; | |
| 810 | − int rows = _heightSize - 1; | |
| 811 | − int indexCount = rows * rows * 3 * 2; | |
| 812 | − BufferPair& bufferPair = _bufferPairs[_heightSize]; | |
| 813 | − if (!bufferPair.first.isCreated()) { | |
| 814 | − QVector<HeightfieldPoint> vertices(vertexCount); | |
| 815 | − HeightfieldPoint* point = vertices.data(); | |
| 816 | − | |
| 817 | − float vertexStep = 1.0f / (innerSize - 1); | |
| 818 | − float z = -vertexStep; | |
| 819 | − float textureStep = 1.0f / _heightSize; | |
| 820 | − float t = textureStep / 2.0f; | |
| 821 | − for (int i = 0; i < _heightSize; i++, z += vertexStep, t += textureStep) { | |
| 822 | − float x = -vertexStep; | |
| 823 | − float s = textureStep / 2.0f; | |
| 824 | − const float SKIRT_LENGTH = 0.25f; | |
| 825 | − float baseY = (i == 0 || i == _heightSize - 1) ? -SKIRT_LENGTH : 0.0f; | |
| 826 | − for (int j = 0; j < _heightSize; j++, point++, x += vertexStep, s += textureStep) { | |
| 827 | − point->vertex = glm::vec3(x, (j == 0 || j == _heightSize - 1) ? -SKIRT_LENGTH : baseY, z); | |
| 828 | − point->textureCoord = glm::vec2(s, t); | |
| 829 | − } | |
| 830 | − } | |
| 831 | − | |
| 832 | − bufferPair.first.setUsagePattern(QOpenGLBuffer::StaticDraw); | |
| 833 | − bufferPair.first.create(); | |
| 834 | − bufferPair.first.bind(); | |
| 835 | − bufferPair.first.allocate(vertices.constData(), vertexCount * sizeof(HeightfieldPoint)); | |
| 836 | − | |
| 837 | − QVector<int> indices(indexCount); | |
| 838 | − int* index = indices.data(); | |
| 839 | − for (int i = 0; i < rows; i++) { | |
| 840 | − int lineIndex = i * _heightSize; | |
| 841 | − int nextLineIndex = (i + 1) * _heightSize; | |
| 842 | − for (int j = 0; j < rows; j++) { | |
| 843 | − *index++ = lineIndex + j; | |
| 844 | − *index++ = nextLineIndex + j; | |
| 845 | − *index++ = nextLineIndex + j + 1; | |
| 846 | − | |
| 847 | − *index++ = nextLineIndex + j + 1; | |
| 848 | − *index++ = lineIndex + j + 1; | |
| 849 | − *index++ = lineIndex + j; | |
| 850 | − } | |
| 851 | − } | |
| 852 | − | |
| 853 | − bufferPair.second = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); | |
| 854 | − bufferPair.second.create(); | |
| 855 | − bufferPair.second.bind(); | |
| 856 | − bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int)); | |
| 857 | − | |
| 858 | − } else { | |
| 859 | − bufferPair.first.bind(); | |
| 860 | − bufferPair.second.bind(); | |
| 861 | − } | |
| 862 | − | |
| 863 | − HeightfieldPoint* point = 0; | |
| 864 | − glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); | |
| 865 | − glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); | |
| 866 | − | |
| 867 | − glPushMatrix(); | |
| 868 | − glTranslatef(_translation.x, _translation.y, _translation.z); | |
| 869 | − glScalef(_scale, _scale, _scale); | |
| 870 | − | |
| 871 | − glBindTexture(GL_TEXTURE_2D, _heightTextureID); | |
| 872 | − | |
| 873 | − if (cursor) { | |
| 874 | − glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); | |
| 875 | − | |
| 876 | − } else if (!_materials.isEmpty()) { | |
| 877 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( | |
| 878 | − DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); | |
| 879 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( | |
| 880 | − DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize); | |
| 881 | − glActiveTexture(GL_TEXTURE1); | |
| 882 | − glBindTexture(GL_TEXTURE_2D, _colorTextureID); | |
| 883 | − | |
| 884 | − glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); | |
| 885 | − | |
| 886 | − Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); | |
| 887 | − | |
| 888 | − glDepthFunc(GL_LEQUAL); | |
| 889 | − glDepthMask(false); | |
| 890 | − glEnable(GL_BLEND); | |
| 891 | − glDisable(GL_ALPHA_TEST); | |
| 892 | − glEnable(GL_POLYGON_OFFSET_FILL); | |
| 893 | − glPolygonOffset(-1.0f, -1.0f); | |
| 894 | − | |
| 895 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind(); | |
| 896 | − const DefaultMetavoxelRendererImplementation::SplatLocations& locations = | |
| 897 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations(); | |
| 898 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 899 | − locations.heightScale, 1.0f / _heightSize); | |
| 900 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 901 | − locations.textureScale, (float)_heightSize / innerSize); | |
| 902 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 903 | − locations.splatTextureOffset, _translation.x / _scale, _translation.z / _scale); | |
| 904 | − | |
| 905 | − glBindTexture(GL_TEXTURE_2D, _materialTextureID); | |
| 906 | − | |
| 907 | − for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) { | |
| 908 | − QVector4D scalesS, scalesT; | |
| 909 | − | |
| 910 | − for (int j = 0; j < SPLAT_COUNT; j++) { | |
| 911 | − glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]); | |
| 912 | − int index = i + j; | |
| 913 | − if (index < _networkTextures.size()) { | |
| 914 | − const NetworkTexturePointer& texture = _networkTextures.at(index); | |
| 915 | − if (texture) { | |
| 916 | − MaterialObject* material = static_cast<MaterialObject*>(_materials.at(index).data()); | |
| 917 | − scalesS[j] = _scale / material->getScaleS(); | |
| 918 | − scalesT[j] = _scale / material->getScaleT(); | |
| 919 | − glBindTexture(GL_TEXTURE_2D, texture->getID()); | |
| 920 | − } else { | |
| 921 | − glBindTexture(GL_TEXTURE_2D, 0); | |
| 922 | − } | |
| 923 | − } else { | |
| 924 | − glBindTexture(GL_TEXTURE_2D, 0); | |
| 925 | − } | |
| 926 | − } | |
| 927 | − const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; | |
| 928 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 929 | − locations.splatTextureScalesS, scalesS); | |
| 930 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 931 | − locations.splatTextureScalesT, scalesT); | |
| 932 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 933 | − locations.textureValueMinima, | |
| 934 | − (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, | |
| 935 | − (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); | |
| 936 | − DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( | |
| 937 | − locations.textureValueMaxima, | |
| 938 | − (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, | |
| 939 | − (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); | |
| 940 | − glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); | |
| 941 | − } | |
| 942 | − | |
| 943 | − for (int i = 0; i < SPLAT_COUNT; i++) { | |
| 944 | − glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); | |
| 945 | − glBindTexture(GL_TEXTURE_2D, 0); | |
| 946 | − } | |
| 947 | − | |
| 948 | − glActiveTexture(GL_TEXTURE1); | |
| 949 | − glBindTexture(GL_TEXTURE_2D, 0); | |
| 950 | − | |
| 951 | − glActiveTexture(GL_TEXTURE0); | |
| 952 | − | |
| 953 | − glDisable(GL_POLYGON_OFFSET_FILL); | |
| 954 | − glEnable(GL_ALPHA_TEST); | |
| 955 | − glDisable(GL_BLEND); | |
| 956 | − glDepthMask(true); | |
| 957 | − glDepthFunc(GL_LESS); | |
| 958 | − | |
| 959 | − Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); | |
| 960 | − | |
| 961 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); | |
| 962 | − | |
| 963 | − } else { | |
| 964 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( | |
| 965 | − DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); | |
| 966 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( | |
| 967 | − DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize); | |
| 968 | − glActiveTexture(GL_TEXTURE1); | |
| 969 | − glBindTexture(GL_TEXTURE_2D, _colorTextureID); | |
| 970 | − | |
| 971 | − glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); | |
| 972 | − | |
| 973 | − glBindTexture(GL_TEXTURE_2D, 0); | |
| 974 | − glActiveTexture(GL_TEXTURE0); | |
| 975 | − } | |
| 976 | − | |
| 977 | − glBindTexture(GL_TEXTURE_2D, 0); | |
| 978 | − | |
| 979 | − glPopMatrix(); | |
| 980 | − | |
| 981 | − bufferPair.first.release(); | |
| 982 | − bufferPair.second.release(); | |
| 983 | −} | |
| 984 | − | |
| 985 | −QHash<int, HeightfieldBuffer::BufferPair> HeightfieldBuffer::_bufferPairs; | |
| 986 | − | |
| 987 | −void HeightfieldPreview::render(const glm::vec3& translation, float scale) const { | |
| 988 | − Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); | |
| 989 | − | |
| 990 | − glDisable(GL_BLEND); | |
| 991 | − glEnable(GL_CULL_FACE); | |
| 992 | − glEnable(GL_ALPHA_TEST); | |
| 993 | − glAlphaFunc(GL_EQUAL, 0.0f); | |
| 994 | − | |
| 995 | − glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |
| 996 | − | |
| 997 | − glEnableClientState(GL_VERTEX_ARRAY); | |
| 998 | − glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |
| 999 | − | |
| 1000 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); | |
| 1001 | − | |
| 1002 | − glPushMatrix(); | |
| 1003 | − glTranslatef(translation.x, translation.y, translation.z); | |
| 1004 | − glScalef(scale, scale, scale); | |
| 1005 | − | |
| 1006 | − foreach (const BufferDataPointer& buffer, _buffers) { | |
| 1007 | − buffer->render(); | |
| 1008 | − } | |
| 1009 | − | |
| 1010 | − glPopMatrix(); | |
| 1011 | − | |
| 1012 | − DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release(); | |
| 1013 | − | |
| 1014 | − glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |
| 1015 | − glDisableClientState(GL_VERTEX_ARRAY); | |
| 1016 | − | |
| 1017 | − glDisable(GL_ALPHA_TEST); | |
| 1018 | − glDisable(GL_CULL_FACE); | |
| 1019 | − glEnable(GL_BLEND); | |
| 1020 | − | |
| 1021 | − Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); | |
| 1022 | −} | |
| 1023 | − | |
| 1024 | 668 | void VoxelPoint::setNormal(const glm::vec3& normal) { |
| 1025 | 669 | this->normal[0] = (char)(normal.x * 127.0f); |
| 1026 | 670 | this->normal[1] = (char)(normal.y * 127.0f); |
| @@ -1344,446 +988,6 @@ void DefaultMetavoxelRendererImplementation::init() { · 317 unmodified lines | ||
| 1344 | 988 | DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() { |
| 1345 | 989 | } |
| 1346 | 990 | |
| 1347 | −class HeightfieldFetchVisitor : public MetavoxelVisitor { | |
| 1348 | −public: | |
| 1349 | − | |
| 1350 | − HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections); | |
| 1351 | − | |
| 1352 | − void init(HeightfieldBuffer* buffer); | |
| 1353 | − | |
| 1354 | − virtual int visit(MetavoxelInfo& info); | |
| 1355 | − virtual bool postVisit(MetavoxelInfo& info); | |
| 1356 | − | |
| 1357 | −private: | |
| 1358 | − | |
| 1359 | − const QVector<Box>& _intersections; | |
| 1360 | − HeightfieldBuffer* _buffer; | |
| 1361 | − | |
| 1362 | − QVector<int> _depthFlags; | |
| 1363 | −}; | |
| 1364 | − | |
| 1365 | −enum DepthFlags { HEIGHT_FLAG = 0x01, COLOR_FLAG = 0x02, MATERIAL_FLAG = 0x04 }; | |
| 1366 | − | |
| 1367 | −HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) : | |
| 1368 | − MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | |
| 1369 | − AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << | |
| 1370 | − AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector<AttributePointer>(), lod), | |
| 1371 | − _intersections(intersections) { | |
| 1372 | −} | |
| 1373 | − | |
| 1374 | −void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) { | |
| 1375 | − _buffer = buffer; | |
| 1376 | −} | |
| 1377 | − | |
| 1378 | −int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { | |
| 1379 | − if (!info.getBounds().intersects(_buffer->getHeightBounds())) { | |
| 1380 | − return STOP_RECURSION; | |
| 1381 | − } | |
| 1382 | − if (_depthFlags.size() > _depth) { | |
| 1383 | − _depthFlags[_depth] = 0; | |
| 1384 | − } else { | |
| 1385 | − _depthFlags.append(0); | |
| 1386 | − } | |
| 1387 | − if (!info.isLeaf) { | |
| 1388 | − return DEFAULT_ORDER; | |
| 1389 | − } | |
| 1390 | − postVisit(info); | |
| 1391 | − return STOP_RECURSION; | |
| 1392 | −} | |
| 1393 | − | |
| 1394 | −bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) { | |
| 1395 | − HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>(); | |
| 1396 | − int flags = _depthFlags.at(_depth); | |
| 1397 | − if (height) { | |
| 1398 | − // to handle borders correctly, make sure we only sample nodes with resolution <= ours | |
| 1399 | − int heightSize = glm::sqrt((float)height->getContents().size()); | |
| 1400 | − float heightIncrement = info.size / heightSize; | |
| 1401 | − if (heightIncrement < _buffer->getHeightIncrement() || (flags & HEIGHT_FLAG)) { | |
| 1402 | − height.reset(); | |
| 1403 | − } else { | |
| 1404 | − flags |= HEIGHT_FLAG; | |
| 1405 | − } | |
| 1406 | − } | |
| 1407 | − HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>(); | |
| 1408 | − if (color) { | |
| 1409 | − int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES); | |
| 1410 | − float colorIncrement = info.size / colorSize; | |
| 1411 | − if (colorIncrement < _buffer->getColorIncrement() || (flags & COLOR_FLAG)) { | |
| 1412 | − color.reset(); | |
| 1413 | − } else { | |
| 1414 | − flags |= COLOR_FLAG; | |
| 1415 | − } | |
| 1416 | − } | |
| 1417 | − HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>(); | |
| 1418 | − if (material) { | |
| 1419 | − int materialSize = glm::sqrt((float)material->getContents().size()); | |
| 1420 | − float materialIncrement = info.size / materialSize; | |
| 1421 | − if (materialIncrement < _buffer->getMaterialIncrement() || (flags & MATERIAL_FLAG)) { | |
| 1422 | − material.reset(); | |
| 1423 | − } else { | |
| 1424 | − flags |= MATERIAL_FLAG; | |
| 1425 | − } | |
| 1426 | − } | |
| 1427 | − if (_depth > 0) { | |
| 1428 | − _depthFlags[_depth - 1] |= flags; | |
| 1429 | − } | |
| 1430 | − if (!(height || color || material)) { | |
| 1431 | − return false; | |
| 1432 | − } | |
| 1433 | − Box bounds = info.getBounds(); | |
| 1434 | − foreach (const Box& intersection, _intersections) { | |
| 1435 | − Box overlap = intersection.getIntersection(bounds); | |
| 1436 | − if (overlap.isEmpty()) { | |
| 1437 | − continue; | |
| 1438 | − } | |
| 1439 | − if (height) { | |
| 1440 | − float heightIncrement = _buffer->getHeightIncrement(); | |
| 1441 | − const Box& heightBounds = _buffer->getHeightBounds(); | |
| 1442 | − int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement; | |
| 1443 | − int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement; | |
| 1444 | − int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement); | |
| 1445 | − int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement); | |
| 1446 | − int heightSize = _buffer->getHeightSize(); | |
| 1447 | − char* dest = _buffer->getHeight().data() + destY * heightSize + destX; | |
| 1448 | − | |
| 1449 | − const QByteArray& srcHeight = height->getContents(); | |
| 1450 | − int srcSize = glm::sqrt((float)srcHeight.size()); | |
| 1451 | − float srcIncrement = info.size / srcSize; | |
| 1452 | − | |
| 1453 | − if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) { | |
| 1454 | − // easy case: same resolution | |
| 1455 | − int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1456 | − int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1457 | − | |
| 1458 | − const char* src = srcHeight.constData() + srcY * srcSize + srcX; | |
| 1459 | − for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) { | |
| 1460 | − memcpy(dest, src, destWidth); | |
| 1461 | − } | |
| 1462 | − } else { | |
| 1463 | − // more difficult: different resolutions | |
| 1464 | − float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1465 | − float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1466 | − float srcAdvance = heightIncrement / srcIncrement; | |
| 1467 | − int shift = 0; | |
| 1468 | − float size = _buffer->getScale(); | |
| 1469 | − while (size < info.size) { | |
| 1470 | − shift++; | |
| 1471 | − size *= 2.0f; | |
| 1472 | − } | |
| 1473 | − int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale(); | |
| 1474 | − for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) { | |
| 1475 | − const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize; | |
| 1476 | − float lineSrcX = srcX; | |
| 1477 | − for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { | |
| 1478 | − *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM); | |
| 1479 | − } | |
| 1480 | − } | |
| 1481 | − } | |
| 1482 | − } | |
| 1483 | − if (color) { | |
| 1484 | − const Box& colorBounds = _buffer->getColorBounds(); | |
| 1485 | − overlap = colorBounds.getIntersection(overlap); | |
| 1486 | − float colorIncrement = _buffer->getColorIncrement(); | |
| 1487 | − int destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement; | |
| 1488 | − int destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement; | |
| 1489 | − int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement); | |
| 1490 | − int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement); | |
| 1491 | − int colorSize = _buffer->getColorSize(); | |
| 1492 | − char* dest = _buffer->getColor().data() + (destY * colorSize + destX) * DataBlock::COLOR_BYTES; | |
| 1493 | − int destStride = colorSize * DataBlock::COLOR_BYTES; | |
| 1494 | − int destBytes = destWidth * DataBlock::COLOR_BYTES; | |
| 1495 | − | |
| 1496 | − const QByteArray& srcColor = color->getContents(); | |
| 1497 | − int srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES)); | |
| 1498 | − int srcStride = srcSize * DataBlock::COLOR_BYTES; | |
| 1499 | − float srcIncrement = info.size / srcSize; | |
| 1500 | − | |
| 1501 | − if (srcIncrement == colorIncrement) { | |
| 1502 | − // easy case: same resolution | |
| 1503 | − int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1504 | − int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1505 | − | |
| 1506 | − const char* src = srcColor.constData() + (srcY * srcSize + srcX) * DataBlock::COLOR_BYTES; | |
| 1507 | − for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) { | |
| 1508 | − memcpy(dest, src, destBytes); | |
| 1509 | − } | |
| 1510 | − } else { | |
| 1511 | − // more difficult: different resolutions | |
| 1512 | − float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1513 | − float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1514 | − float srcAdvance = colorIncrement / srcIncrement; | |
| 1515 | − for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) { | |
| 1516 | − const char* src = srcColor.constData() + (int)srcY * srcStride; | |
| 1517 | − float lineSrcX = srcX; | |
| 1518 | − for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += DataBlock::COLOR_BYTES, | |
| 1519 | − lineSrcX += srcAdvance) { | |
| 1520 | − const char* lineSrc = src + (int)lineSrcX * DataBlock::COLOR_BYTES; | |
| 1521 | − lineDest[0] = lineSrc[0]; | |
| 1522 | − lineDest[1] = lineSrc[1]; | |
| 1523 | − lineDest[2] = lineSrc[2]; | |
| 1524 | − } | |
| 1525 | − } | |
| 1526 | − } | |
| 1527 | − } | |
| 1528 | − if (material) { | |
| 1529 | − const Box& materialBounds = _buffer->getMaterialBounds(); | |
| 1530 | − overlap = materialBounds.getIntersection(overlap); | |
| 1531 | − float materialIncrement = _buffer->getMaterialIncrement(); | |
| 1532 | − int destX = (overlap.minimum.x - materialBounds.minimum.x) / materialIncrement; | |
| 1533 | − int destY = (overlap.minimum.z - materialBounds.minimum.z) / materialIncrement; | |
| 1534 | − int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / materialIncrement); | |
| 1535 | − int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / materialIncrement); | |
| 1536 | − int materialSize = _buffer->getMaterialSize(); | |
| 1537 | − char* dest = _buffer->getMaterial().data() + destY * materialSize + destX; | |
| 1538 | − | |
| 1539 | − const QByteArray& srcMaterial = material->getContents(); | |
| 1540 | − const QVector<SharedObjectPointer> srcMaterials = material->getMaterials(); | |
| 1541 | − int srcSize = glm::sqrt((float)srcMaterial.size()); | |
| 1542 | − float srcIncrement = info.size / srcSize; | |
| 1543 | − QHash<int, int> materialMappings; | |
| 1544 | − | |
| 1545 | − if (srcIncrement == materialIncrement) { | |
| 1546 | − // easy case: same resolution | |
| 1547 | − int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1548 | − int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1549 | − | |
| 1550 | − const uchar* src = (const uchar*)srcMaterial.constData() + srcY * srcSize + srcX; | |
| 1551 | − for (int y = 0; y < destHeight; y++, src += srcSize, dest += materialSize) { | |
| 1552 | − const uchar* lineSrc = src; | |
| 1553 | − for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrc++) { | |
| 1554 | − int value = *lineSrc; | |
| 1555 | − if (value != 0) { | |
| 1556 | − int& mapping = materialMappings[value]; | |
| 1557 | − if (mapping == 0) { | |
| 1558 | − mapping = getMaterialIndex(material->getMaterials().at(value - 1), | |
| 1559 | − _buffer->getMaterials(), _buffer->getMaterial()); | |
| 1560 | − } | |
| 1561 | − value = mapping; | |
| 1562 | − } | |
| 1563 | − *lineDest = value; | |
| 1564 | − } | |
| 1565 | − } | |
| 1566 | − } else { | |
| 1567 | − // more difficult: different resolutions | |
| 1568 | − float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | |
| 1569 | − float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | |
| 1570 | − float srcAdvance = materialIncrement / srcIncrement; | |
| 1571 | − for (int y = 0; y < destHeight; y++, dest += materialSize, srcY += srcAdvance) { | |
| 1572 | − const uchar* src = (const uchar*)srcMaterial.constData() + (int)srcY * srcSize; | |
| 1573 | − float lineSrcX = srcX; | |
| 1574 | − for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { | |
| 1575 | − int value = src[(int)lineSrcX]; | |
| 1576 | − if (value != 0) { | |
| 1577 | − int& mapping = materialMappings[value]; | |
| 1578 | − if (mapping == 0) { | |
| 1579 | − mapping = getMaterialIndex(material->getMaterials().at(value - 1), | |
| 1580 | − _buffer->getMaterials(), _buffer->getMaterial()); | |
| 1581 | − } | |
| 1582 | − value = mapping; | |
| 1583 | − } | |
| 1584 | − *lineDest = value; | |
| 1585 | − } | |
| 1586 | − } | |
| 1587 | − } | |
| 1588 | − clearUnusedMaterials(_buffer->getMaterials(), _buffer->getMaterial()); | |
| 1589 | − } | |
| 1590 | − } | |
| 1591 | − return false; | |
| 1592 | −} | |
| 1593 | − | |
| 1594 | −class HeightfieldRegionVisitor : public MetavoxelVisitor { | |
| 1595 | −public: | |
| 1596 | − | |
| 1597 | − QVector<Box> regions; | |
| 1598 | − Box regionBounds; | |
| 1599 | − | |
| 1600 | − HeightfieldRegionVisitor(const MetavoxelLOD& lod); | |
| 1601 | − | |
| 1602 | − virtual int visit(MetavoxelInfo& info); | |
| 1603 | − virtual bool postVisit(MetavoxelInfo& info); | |
| 1604 | − | |
| 1605 | −private: | |
| 1606 | − | |
| 1607 | − void addRegion(const Box& unextended, const Box& extended); | |
| 1608 | − | |
| 1609 | − class DepthInfo { | |
| 1610 | − public: | |
| 1611 | − float minimumColorIncrement; | |
| 1612 | − float minimumMaterialIncrement; | |
| 1613 | − | |
| 1614 | − DepthInfo() : minimumColorIncrement(FLT_MAX), minimumMaterialIncrement(FLT_MAX) { } | |
| 1615 | − }; | |
| 1616 | − | |
| 1617 | − QVector<DepthInfo> _depthInfo; | |
| 1618 | − | |
| 1619 | − QVector<Box> _intersections; | |
| 1620 | − HeightfieldFetchVisitor _fetchVisitor; | |
| 1621 | −}; | |
| 1622 | − | |
| 1623 | −HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : | |
| 1624 | − MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | |
| 1625 | − AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << | |
| 1626 | − AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute() << | |
| 1627 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << | |
| 1628 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), | |
| 1629 | − regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)), | |
| 1630 | − _fetchVisitor(lod, _intersections) { | |
| 1631 | −} | |
| 1632 | − | |
| 1633 | −int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) { | |
| 1634 | − DepthInfo depthInfo; | |
| 1635 | − HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>(); | |
| 1636 | − if (color) { | |
| 1637 | − int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES); | |
| 1638 | − depthInfo.minimumColorIncrement = info.size / colorSize; | |
| 1639 | − } | |
| 1640 | − HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>(); | |
| 1641 | − if (material) { | |
| 1642 | − int materialSize = glm::sqrt((float)material->getContents().size()); | |
| 1643 | − depthInfo.minimumMaterialIncrement = info.size / materialSize; | |
| 1644 | − } | |
| 1645 | − if (_depth < _depthInfo.size()) { | |
| 1646 | − _depthInfo[_depth] = depthInfo; | |
| 1647 | − } else { | |
| 1648 | − _depthInfo.append(depthInfo); | |
| 1649 | − } | |
| 1650 | − if (!info.isLeaf) { | |
| 1651 | − return _visitations.at(_depth).isInputLeaf(0) ? (DEFAULT_ORDER | ALL_NODES_REST) : DEFAULT_ORDER; | |
| 1652 | − } | |
| 1653 | − postVisit(info); | |
| 1654 | − return STOP_RECURSION; | |
| 1655 | −} | |
| 1656 | − | |
| 1657 | −bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) { | |
| 1658 | − const DepthInfo& depthInfo = _depthInfo.at(_depth); | |
| 1659 | − if (_depth > 0) { | |
| 1660 | − DepthInfo& parentDepthInfo = _depthInfo[_depth - 1]; | |
| 1661 | − parentDepthInfo.minimumColorIncrement = qMin(parentDepthInfo.minimumColorIncrement, depthInfo.minimumColorIncrement); | |
| 1662 | − parentDepthInfo.minimumMaterialIncrement = qMin(parentDepthInfo.minimumMaterialIncrement, | |
| 1663 | − depthInfo.minimumMaterialIncrement); | |
| 1664 | − } | |
| 1665 | − if (_visitations.at(_depth).isInputLeaf(0)) { | |
| 1666 | − HeightfieldBuffer* buffer = NULL; | |
| 1667 | − HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>(); | |
| 1668 | − if (height) { | |
| 1669 | − int heightSize = glm::sqrt((float)height->getContents().size()); | |
| 1670 | − int extendedHeightSize = heightSize + HeightfieldBuffer::HEIGHT_EXTENSION; | |
| 1671 | − int heightContentsSize = extendedHeightSize * extendedHeightSize; | |
| 1672 | − float minimumColorIncrement = depthInfo.minimumColorIncrement; | |
| 1673 | − float minimumMaterialIncrement = depthInfo.minimumMaterialIncrement; | |
| 1674 | − for (int i = _depth - 1; i >= 0 && qMax(minimumColorIncrement, minimumMaterialIncrement) == FLT_MAX; i--) { | |
| 1675 | − const DepthInfo& ancestorDepthInfo = _depthInfo.at(i); | |
| 1676 | − minimumColorIncrement = qMin(minimumColorIncrement, ancestorDepthInfo.minimumColorIncrement); | |
| 1677 | − minimumMaterialIncrement = qMin(minimumMaterialIncrement, ancestorDepthInfo.minimumMaterialIncrement); | |
| 1678 | − } | |
| 1679 | − int colorContentsSize = 0; | |
| 1680 | − if (minimumColorIncrement != FLT_MAX) { | |
| 1681 | − int colorSize = (int)glm::round(info.size / minimumColorIncrement) + HeightfieldBuffer::SHARED_EDGE; | |
| 1682 | − colorContentsSize = colorSize * colorSize * DataBlock::COLOR_BYTES; | |
| 1683 | − } | |
| 1684 | − int materialContentsSize = 0; | |
| 1685 | − if (minimumMaterialIncrement != FLT_MAX) { | |
| 1686 | − int materialSize = (int)glm::round(info.size / minimumMaterialIncrement) + HeightfieldBuffer::SHARED_EDGE; | |
| 1687 | − materialContentsSize = materialSize * materialSize; | |
| 1688 | − } | |
| 1689 | − const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>( | |
| 1690 | − info.inputValues.at(3).getInlineValue<BufferDataPointer>().data()); | |
| 1691 | − Box bounds = info.getBounds(); | |
| 1692 | − if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && | |
| 1693 | − existingBuffer->getColor().size() == colorContentsSize && | |
| 1694 | − existingBuffer->getMaterial().size() == materialContentsSize) { | |
| 1695 | − // we already have a buffer of the correct resolution | |
| 1696 | − addRegion(bounds, existingBuffer->getHeightBounds()); | |
| 1697 | − buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(), | |
| 1698 | − existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials()); | |
| 1699 | − | |
| 1700 | − } else { | |
| 1701 | − // we must create a new buffer and update its borders | |
| 1702 | − buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), | |
| 1703 | − QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0)); | |
| 1704 | − const Box& heightBounds = buffer->getHeightBounds(); | |
| 1705 | − addRegion(bounds, heightBounds); | |
| 1706 | − | |
| 1707 | − _intersections.clear(); | |
| 1708 | − _intersections.append(Box(heightBounds.minimum, | |
| 1709 | − glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z))); | |
| 1710 | − _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z), | |
| 1711 | − glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z))); | |
| 1712 | − _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z), | |
| 1713 | − heightBounds.maximum)); | |
| 1714 | − _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z), | |
| 1715 | − glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z))); | |
| 1716 | − | |
| 1717 | − _fetchVisitor.init(buffer); | |
| 1718 | − _data->guide(_fetchVisitor); | |
| 1719 | − } | |
| 1720 | − } | |
| 1721 | − BufferDataPointer pointer(buffer); | |
| 1722 | − info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); | |
| 1723 | − } | |
| 1724 | − return true; | |
| 1725 | −} | |
| 1726 | − | |
| 1727 | −void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) { | |
| 1728 | − regions.append(unextended); | |
| 1729 | − regionBounds.add(extended); | |
| 1730 | −} | |
| 1731 | − | |
| 1732 | −class HeightfieldUpdateVisitor : public MetavoxelVisitor { | |
| 1733 | −public: | |
| 1734 | − | |
| 1735 | − HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, const Box& regionBounds); | |
| 1736 | − | |
| 1737 | − virtual int visit(MetavoxelInfo& info); | |
| 1738 | − | |
| 1739 | −private: | |
| 1740 | − | |
| 1741 | − const QVector<Box>& _regions; | |
| 1742 | − const Box& _regionBounds; | |
| 1743 | − QVector<Box> _intersections; | |
| 1744 | − HeightfieldFetchVisitor _fetchVisitor; | |
| 1745 | −}; | |
| 1746 | − | |
| 1747 | −HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, | |
| 1748 | − const Box& regionBounds) : | |
| 1749 | − MetavoxelVisitor(QVector<AttributePointer>() << | |
| 1750 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << | |
| 1751 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), | |
| 1752 | − _regions(regions), | |
| 1753 | − _regionBounds(regionBounds), | |
| 1754 | − _fetchVisitor(lod, _intersections) { | |
| 1755 | −} | |
| 1756 | − | |
| 1757 | −int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { | |
| 1758 | − if (!info.getBounds().intersects(_regionBounds)) { | |
| 1759 | − return STOP_RECURSION; | |
| 1760 | − } | |
| 1761 | − if (!info.isLeaf) { | |
| 1762 | − return DEFAULT_ORDER; | |
| 1763 | − } | |
| 1764 | − const HeightfieldBuffer* buffer = static_cast<const HeightfieldBuffer*>( | |
| 1765 | − info.inputValues.at(0).getInlineValue<BufferDataPointer>().data()); | |
| 1766 | − if (!buffer) { | |
| 1767 | − return STOP_RECURSION; | |
| 1768 | − } | |
| 1769 | − _intersections.clear(); | |
| 1770 | − foreach (const Box& region, _regions) { | |
| 1771 | − if (region.intersects(buffer->getHeightBounds())) { | |
| 1772 | − _intersections.append(region.getIntersection(buffer->getHeightBounds())); | |
| 1773 | − } | |
| 1774 | − } | |
| 1775 | − if (_intersections.isEmpty()) { | |
| 1776 | − return STOP_RECURSION; | |
| 1777 | − } | |
| 1778 | − HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, | |
| 1779 | − buffer->getHeight(), buffer->getColor(), buffer->getMaterial(), buffer->getMaterials()); | |
| 1780 | − _fetchVisitor.init(newBuffer); | |
| 1781 | − _data->guide(_fetchVisitor); | |
| 1782 | − BufferDataPointer pointer(newBuffer); | |
| 1783 | − info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); | |
| 1784 | − return STOP_RECURSION; | |
| 1785 | −} | |
| 1786 | − | |
| 1787 | 991 | class VoxelAugmentVisitor : public MetavoxelVisitor { |
| 1788 | 992 | public: |
| 1789 | 993 | |
| @@ -2392,27 +1596,13 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const · 602 unmodified lines | ||
| 2392 | 1596 | while (expandedPrevious.getSize() < data.getSize()) { |
| 2393 | 1597 | expandedPrevious.expand(); |
| 2394 | 1598 | } |
| 2395 | − const AttributePointer& heightfieldBufferAttribute = | |
| 2396 | − Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(); | |
| 2397 | − MetavoxelNode* root = expandedPrevious.getRoot(heightfieldBufferAttribute); | |
| 2398 | − if (root) { | |
| 2399 | − data.setRoot(heightfieldBufferAttribute, root); | |
| 2400 | − root->incrementReferenceCount(); | |
| 2401 | − } | |
| 2402 | 1599 | const AttributePointer& voxelBufferAttribute = |
| 2403 | 1600 | Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(); |
| 2404 | − root = expandedPrevious.getRoot(voxelBufferAttribute); | |
| 1601 | + MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute); | |
| 2405 | 1602 | if (root) { |
| 2406 | 1603 | data.setRoot(voxelBufferAttribute, root); |
| 2407 | 1604 | root->incrementReferenceCount(); |
| 2408 | 1605 | } |
| 2409 | − HeightfieldRegionVisitor heightfieldRegionVisitor(lod); | |
| 2410 | − data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor); | |
| 2411 | − | |
| 2412 | − HeightfieldUpdateVisitor heightfieldUpdateVisitor(lod, heightfieldRegionVisitor.regions, | |
| 2413 | − heightfieldRegionVisitor.regionBounds); | |
| 2414 | − data.guide(heightfieldUpdateVisitor); | |
| 2415 | − | |
| 2416 | 1606 | VoxelAugmentVisitor voxelAugmentVisitor(lod); |
| 2417 | 1607 | data.guideToDifferent(expandedPrevious, voxelAugmentVisitor); |
| 2418 | 1608 | } |
| @@ -2535,19 +1725,6 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox · 116 unmodified lines | ||
| 2535 | 1725 | |
| 2536 | 1726 | glColor4f(1.0f, 1.0f, 1.0f, 1.0f); |
| 2537 | 1727 | |
| 2538 | − if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) { | |
| 2539 | − _baseHeightfieldProgram.bind(); | |
| 2540 | − | |
| 2541 | − glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |
| 2542 | − | |
| 2543 | − BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()); | |
| 2544 | − data.guide(heightfieldRenderVisitor); | |
| 2545 | − | |
| 2546 | − glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |
| 2547 | − | |
| 2548 | − _baseHeightfieldProgram.release(); | |
| 2549 | − } | |
| 2550 | − | |
| 2551 | 1728 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) { |
| 2552 | 1729 | glEnableClientState(GL_COLOR_ARRAY); |
| 2553 | 1730 | glEnableClientState(GL_NORMAL_ARRAY); |
| @@ -2756,6 +1933,12 @@ void HeightfieldRenderer::init(Spanner* spanner) { · 202 unmodified lines | ||
| 2756 | 1933 | connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial); |
| 2757 | 1934 | } |
| 2758 | 1935 | |
| 1936 | +class HeightfieldPoint { | |
| 1937 | +public: | |
| 1938 | + glm::vec3 vertex; | |
| 1939 | + glm::vec2 textureCoord; | |
| 1940 | +}; | |
| 1941 | + | |
| 2759 | 1942 | void HeightfieldRenderer::render(bool cursor) { |
| 2760 | 1943 | // create the buffer objects lazily |
| 2761 | 1944 | Heightfield* heightfield = static_cast<Heightfield*>(_spanner); |
| @@ -2765,8 +1948,8 @@ void HeightfieldRenderer::render(bool cursor) { · 3 unmodified lines | ||
| 2765 | 1948 | int width = heightfield->getHeight()->getWidth(); |
| 2766 | 1949 | int height = heightfield->getHeight()->getContents().size() / width; |
| 2767 | 1950 | |
| 2768 | − int innerWidth = width - 2 * HeightfieldBuffer::HEIGHT_BORDER; | |
| 2769 | − int innerHeight = height - 2 * HeightfieldBuffer::HEIGHT_BORDER; | |
| 1951 | + int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER; | |
| 1952 | + int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER; | |
| 2770 | 1953 | int vertexCount = width * height; |
| 2771 | 1954 | int rows = height - 1; |
| 2772 | 1955 | int columns = width - 1; |