From 7cf7f188f8a2cf33243dec774af034931098f11e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 19 Aug 2014 18:55:18 -0700 Subject: [PATCH] Yet more texture bits. --- interface/src/MetavoxelSystem.cpp | 99 ++++++++++++++++++++++++---- interface/src/MetavoxelSystem.h | 19 +++++- interface/src/ui/MetavoxelEditor.cpp | 3 +- 3 files changed, 106 insertions(+), 15 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index db19901334..4cdd2498e6 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -449,9 +449,10 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r glDepthFunc(GL_LESS); } -void MetavoxelSystem::deleteTextures(int heightID, int colorID) { +void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) { glDeleteTextures(1, (GLuint*)&heightID); glDeleteTextures(1, (GLuint*)&colorID); + glDeleteTextures(1, (GLuint*)&textureID); } MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { @@ -601,19 +602,24 @@ const int HeightfieldBuffer::SHARED_EDGE = 1; const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE; HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, - const QByteArray& height, const QByteArray& color) : + const QByteArray& height, const QByteArray& color, const QByteArray& texture) : _translation(translation), _scale(scale), _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), _colorBounds(_heightBounds), + _textureBounds(_heightBounds), _height(height), _color(color), + _texture(texture), _heightTextureID(0), _colorTextureID(0), + _textureTextureID(0), _heightSize(glm::sqrt(height.size())), _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), _colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)), - _colorIncrement(scale / (_colorSize - SHARED_EDGE)) { + _colorIncrement(scale / (_colorSize - SHARED_EDGE)), + _textureSize(glm::sqrt(texture.size())), + _textureIncrement(scale / (_textureSize - SHARED_EDGE)) { _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER; @@ -622,16 +628,20 @@ HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; + + _textureBounds.maximum.x += _textureIncrement * SHARED_EDGE; + _textureBounds.maximum.z += _textureIncrement * SHARED_EDGE; } HeightfieldBuffer::~HeightfieldBuffer() { // the textures have to be deleted on the main thread (for its opengl context) if (QThread::currentThread() != Application::getInstance()->thread()) { QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", - Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID)); + Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID), Q_ARG(int, _textureTextureID)); } else { glDeleteTextures(1, &_heightTextureID); glDeleteTextures(1, &_colorTextureID); + glDeleteTextures(1, &_textureTextureID); } } @@ -692,6 +702,17 @@ void HeightfieldBuffer::render(bool cursor) { int colorSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData()); } + + if (!_texture.isEmpty()) { + glGenTextures(1, &_textureTextureID); + glBindTexture(GL_TEXTURE_2D, _textureTextureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + int textureSize = glm::sqrt(_texture.size()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, textureSize, textureSize, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, _texture.constData()); + } } // create the buffer objects lazily int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; @@ -998,7 +1019,8 @@ private: HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector& intersections) : MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << - AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector(), lod), + AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << + AttributeRegistry::getInstance()->getHeightfieldTextureAttribute(), QVector(), lod), _intersections(intersections) { } @@ -1065,11 +1087,11 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { int colorSize = _buffer->getColorSize(); if (colorSize == 0) { - return STOP_RECURSION; + continue; } HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue(); if (!color) { - return STOP_RECURSION; + continue; } const Box& colorBounds = _buffer->getColorBounds(); overlap = colorBounds.getIntersection(overlap); @@ -1113,6 +1135,50 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { } } } + + int textureSize = _buffer->getTextureSize(); + if (textureSize == 0) { + continue; + } + HeightfieldTextureDataPointer texture = info.inputValues.at(2).getInlineValue(); + if (!texture) { + continue; + } + const Box& textureBounds = _buffer->getTextureBounds(); + overlap = textureBounds.getIntersection(overlap); + float textureIncrement = _buffer->getTextureIncrement(); + destX = (overlap.minimum.x - textureBounds.minimum.x) / textureIncrement; + destY = (overlap.minimum.z - textureBounds.minimum.z) / textureIncrement; + destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / textureIncrement); + destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / textureIncrement); + dest = _buffer->getTexture().data() + destY * textureSize + destX; + + const QByteArray& srcTexture = texture->getContents(); + srcSize = glm::sqrt(srcTexture.size()); + srcIncrement = info.size / srcSize; + + if (srcIncrement == textureIncrement) { + // easy case: same resolution + int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; + int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; + + const char* src = srcTexture.constData() + srcY * srcSize + srcX; + for (int y = 0; y < destHeight; y++, src += srcSize, dest += textureSize) { + memcpy(dest, src, destWidth); + } + } else { + // more difficult: different resolutions + float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; + float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; + float srcAdvance = textureIncrement / srcIncrement; + for (int y = 0; y < destHeight; y++, dest += textureSize, srcY += srcAdvance) { + const char* src = srcTexture.constData() + (int)srcY * srcSize; + float lineSrcX = srcX; + for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { + *lineDest = src[(int)lineSrcX]; + } + } + } } return STOP_RECURSION; } @@ -1138,6 +1204,7 @@ private: HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << + AttributeRegistry::getInstance()->getHeightfieldTextureAttribute() << Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector() << Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)), @@ -1165,18 +1232,28 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) { colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES; } + HeightfieldTextureDataPointer texture = info.inputValues.at(2).getInlineValue(); + int textureContentsSize = 0; + if (texture) { + const QByteArray& textureContents = texture->getContents(); + int textureSize = glm::sqrt(textureContents.size()); + int extendedTextureSize = textureSize + HeightfieldBuffer::SHARED_EDGE; + textureContentsSize = extendedTextureSize * extendedTextureSize; + } + const HeightfieldBuffer* existingBuffer = static_cast( - info.inputValues.at(2).getInlineValue().data()); + info.inputValues.at(3).getInlineValue().data()); Box bounds = info.getBounds(); if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && - existingBuffer->getColor().size() == colorContentsSize) { + existingBuffer->getColor().size() == colorContentsSize && + existingBuffer->getTexture().size() == textureContentsSize) { // we already have a buffer of the correct resolution addRegion(bounds, existingBuffer->getHeightBounds()); return STOP_RECURSION; } // we must create a new buffer and update its borders buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), - QByteArray(colorContentsSize, 0)); + QByteArray(colorContentsSize, 0), QByteArray(textureContentsSize, 0)); const Box& heightBounds = buffer->getHeightBounds(); addRegion(bounds, heightBounds); @@ -1249,7 +1326,7 @@ int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { return STOP_RECURSION; } HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, - buffer->getHeight(), buffer->getColor()); + buffer->getHeight(), buffer->getColor(), buffer->getTexture()); _fetchVisitor.init(newBuffer); _data->guide(_fetchVisitor); info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 38d67bcaed..206c378fd1 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -49,7 +49,7 @@ public: Q_INVOKABLE float getHeightfieldHeight(const glm::vec3& location); - Q_INVOKABLE void deleteTextures(int heightID, int colorID); + Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID); protected: @@ -139,7 +139,8 @@ public: static const int SHARED_EDGE; static const int HEIGHT_EXTENSION; - HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, const QByteArray& color); + HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, + const QByteArray& color, const QByteArray& texture); ~HeightfieldBuffer(); const glm::vec3& getTranslation() const { return _translation; } @@ -147,6 +148,7 @@ public: const Box& getHeightBounds() const { return _heightBounds; } const Box& getColorBounds() const { return _colorBounds; } + const Box& getTextureBounds() const { return _textureBounds; } QByteArray& getHeight() { return _height; } const QByteArray& getHeight() const { return _height; } @@ -154,6 +156,9 @@ public: QByteArray& getColor() { return _color; } const QByteArray& getColor() const { return _color; } + QByteArray& getTexture() { return _texture; } + const QByteArray& getTexture() const { return _texture; } + QByteArray getUnextendedHeight() const; QByteArray getUnextendedColor() const; @@ -163,6 +168,9 @@ public: int getColorSize() const { return _colorSize; } float getColorIncrement() const { return _colorIncrement; } + int getTextureSize() const { return _textureSize; } + float getTextureIncrement() const { return _textureIncrement; } + virtual void render(bool cursor = false); private: @@ -171,15 +179,20 @@ private: float _scale; Box _heightBounds; Box _colorBounds; + Box _textureBounds; QByteArray _height; QByteArray _color; + QByteArray _texture; GLuint _heightTextureID; GLuint _colorTextureID; + GLuint _textureTextureID; int _heightSize; float _heightIncrement; int _colorSize; float _colorIncrement; - + int _textureSize; + float _textureIncrement; + typedef QPair BufferPair; static QHash _bufferPairs; }; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 6251448dce..2c99caf7d2 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1049,7 +1049,8 @@ void ImportHeightfieldTool::updatePreview() { columns * HeightfieldData::COLOR_BYTES); } } - buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, height, color))); + buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, + height, color, QByteArray()))); } } }