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 | MetavoxelClientManager::init(); | 58 | MetavoxelClientManager::init(); |
| 59 | DefaultMetavoxelRendererImplementation::init(); | 59 | DefaultMetavoxelRendererImplementation::init(); |
| 60 | 60 | ||
| 61 | _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( | ||
| 62 | new BufferDataAttribute("heightfieldBuffer")); | ||
| 63 | _heightfieldBufferAttribute->setLODThresholdMultiplier( | ||
| 64 | AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier()); | ||
| 65 | |||
| 66 | _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( | 61 | _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( |
| 67 | new BufferDataAttribute("voxelBuffer")); | 62 | new BufferDataAttribute("voxelBuffer")); |
| 68 | _voxelBufferAttribute->setLODThresholdMultiplier( | 63 | _voxelBufferAttribute->setLODThresholdMultiplier( |
| @@ -375,12 +370,6 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) · 306 unmodified lines | |||
| 375 | glDepthFunc(GL_LESS); | 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 | class MaterialEditApplier : public SignalHandler { | 373 | class MaterialEditApplier : public SignalHandler { |
| 385 | public: | 374 | public: |
| 386 | 375 | ||
| @@ -670,357 +659,12 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { · 283 unmodified lines | |||
| 670 | BufferData::~BufferData() { | 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 | const int SPLAT_COUNT = 4; | 662 | const int SPLAT_COUNT = 4; |
| 754 | const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; | 663 | const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; |
| 755 | 664 | ||
| 756 | static const int EIGHT_BIT_MAXIMUM = 255; | 665 | static const int EIGHT_BIT_MAXIMUM = 255; |
| 757 | static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; | 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 | void VoxelPoint::setNormal(const glm::vec3& normal) { | 668 | void VoxelPoint::setNormal(const glm::vec3& normal) { |
| 1025 | this->normal[0] = (char)(normal.x * 127.0f); | 669 | this->normal[0] = (char)(normal.x * 127.0f); |
| 1026 | this->normal[1] = (char)(normal.y * 127.0f); | 670 | this->normal[1] = (char)(normal.y * 127.0f); |
| @@ -1344,446 +988,6 @@ void DefaultMetavoxelRendererImplementation::init() { · 317 unmodified lines | |||
| 1344 | DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() { | 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 | class VoxelAugmentVisitor : public MetavoxelVisitor { | 991 | class VoxelAugmentVisitor : public MetavoxelVisitor { |
| 1788 | public: | 992 | public: |
| 1789 | 993 | ||
| @@ -2392,27 +1596,13 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const · 602 unmodified lines | |||
| 2392 | while (expandedPrevious.getSize() < data.getSize()) { | 1596 | while (expandedPrevious.getSize() < data.getSize()) { |
| 2393 | expandedPrevious.expand(); | 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 | const AttributePointer& voxelBufferAttribute = | 1599 | const AttributePointer& voxelBufferAttribute = |
| 2403 | Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(); | 1600 | Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(); |
| 2404 | root = expandedPrevious.getRoot(voxelBufferAttribute); | 1601 | MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute); |
| 2405 | if (root) { | 1602 | if (root) { |
| 2406 | data.setRoot(voxelBufferAttribute, root); | 1603 | data.setRoot(voxelBufferAttribute, root); |
| 2407 | root->incrementReferenceCount(); | 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 | VoxelAugmentVisitor voxelAugmentVisitor(lod); | 1606 | VoxelAugmentVisitor voxelAugmentVisitor(lod); |
| 2417 | data.guideToDifferent(expandedPrevious, voxelAugmentVisitor); | 1607 | data.guideToDifferent(expandedPrevious, voxelAugmentVisitor); |
| 2418 | } | 1608 | } |
| @@ -2535,19 +1725,6 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox · 116 unmodified lines | |||
| 2535 | 1725 | ||
| 2536 | glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | 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 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) { | 1728 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) { |
| 2552 | glEnableClientState(GL_COLOR_ARRAY); | 1729 | glEnableClientState(GL_COLOR_ARRAY); |
| 2553 | glEnableClientState(GL_NORMAL_ARRAY); | 1730 | glEnableClientState(GL_NORMAL_ARRAY); |
| @@ -2756,6 +1933,12 @@ void HeightfieldRenderer::init(Spanner* spanner) { · 202 unmodified lines | |||
| 2756 | connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial); | 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 | void HeightfieldRenderer::render(bool cursor) { | 1942 | void HeightfieldRenderer::render(bool cursor) { |
| 2760 | // create the buffer objects lazily | 1943 | // create the buffer objects lazily |
| 2761 | Heightfield* heightfield = static_cast<Heightfield*>(_spanner); | 1944 | Heightfield* heightfield = static_cast<Heightfield*>(_spanner); |
| @@ -2765,8 +1948,8 @@ void HeightfieldRenderer::render(bool cursor) { · 3 unmodified lines | |||
| 2765 | int width = heightfield->getHeight()->getWidth(); | 1948 | int width = heightfield->getHeight()->getWidth(); |
| 2766 | int height = heightfield->getHeight()->getContents().size() / width; | 1949 | int height = heightfield->getHeight()->getContents().size() / width; |
| 2767 | 1950 | ||
| 2768 | int innerWidth = width - 2 * HeightfieldBuffer::HEIGHT_BORDER; | 1951 | int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER; |
| 2769 | int innerHeight = height - 2 * HeightfieldBuffer::HEIGHT_BORDER; | 1952 | int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER; |
| 2770 | int vertexCount = width * height; | 1953 | int vertexCount = width * height; |
| 2771 | int rows = height - 1; | 1954 | int rows = height - 1; |
| 2772 | int columns = width - 1; | 1955 | int columns = width - 1; |