From 2c0f8ff57ec0b70fbe72ba97ddd12473c5ac90e8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 12 Aug 2014 10:56:15 -0700 Subject: [PATCH] Working on rejiggering the heightfield tiles. --- .../shaders/metavoxel_heightfield.vert | 7 +- .../shaders/metavoxel_heightfield_cursor.vert | 3 - interface/src/MetavoxelSystem.cpp | 100 +++++++++++++----- interface/src/MetavoxelSystem.h | 6 +- interface/src/ui/MetavoxelEditor.cpp | 30 +++--- 5 files changed, 100 insertions(+), 46 deletions(-) diff --git a/interface/resources/shaders/metavoxel_heightfield.vert b/interface/resources/shaders/metavoxel_heightfield.vert index cc4f68e9e0..4932ad1b2b 100644 --- a/interface/resources/shaders/metavoxel_heightfield.vert +++ b/interface/resources/shaders/metavoxel_heightfield.vert @@ -17,6 +17,9 @@ uniform sampler2D heightMap; // the distance between height points in texture space uniform float heightScale; +// the scale between height and color textures +uniform float colorScale; + // the interpolated normal varying vec4 normal; @@ -29,8 +32,8 @@ void main(void) { texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r; normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0)); - // pass along the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + // pass along the scaled/offset texture coordinates + gl_TexCoord[0] = (gl_MultiTexCoord0 - vec4(heightScale, heightScale, 0.0, 0.0)) * colorScale; // add the height to the position float height = texture2D(heightMap, heightCoord).r; diff --git a/interface/resources/shaders/metavoxel_heightfield_cursor.vert b/interface/resources/shaders/metavoxel_heightfield_cursor.vert index 20502fbdce..93ed36449e 100644 --- a/interface/resources/shaders/metavoxel_heightfield_cursor.vert +++ b/interface/resources/shaders/metavoxel_heightfield_cursor.vert @@ -14,9 +14,6 @@ // the height texture uniform sampler2D heightMap; -// the distance between height points in texture space -uniform float heightScale; - void main(void) { // compute the view space coordinates float height = texture2D(heightMap, gl_MultiTexCoord0.st).r; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 597542778a..7be3955de7 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -366,6 +366,7 @@ void HeightfieldBuffer::render(bool cursor) { if (_heightTextureID == 0) { glGenTextures(1, &_heightTextureID); glBindTexture(GL_TEXTURE_2D, _heightTextureID); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 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); @@ -385,7 +386,7 @@ void HeightfieldBuffer::render(bool cursor) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR); } else { - int colorSize = glm::sqrt(_color.size() / 3); + int colorSize = glm::sqrt(_color.size() / 3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData()); if (_clearAfterLoading) { _color.clear(); @@ -393,24 +394,27 @@ void HeightfieldBuffer::render(bool cursor) { } } // create the buffer objects lazily - int sizeWithSkirt = _heightSize + 2; - int vertexCount = sizeWithSkirt * sizeWithSkirt; - int rows = sizeWithSkirt - 1; + int innerSize = _heightSize - 2; + int vertexCount = _heightSize * _heightSize; + int rows = _heightSize - 1; int indexCount = rows * rows * 4; BufferPair& bufferPair = _bufferPairs[_heightSize]; if (!bufferPair.first.isCreated()) { QVector vertices(vertexCount); HeightfieldPoint* point = vertices.data(); - float step = 1.0f / (_heightSize - 1); - float z = -step; - for (int i = 0; i < sizeWithSkirt; i++, z += step) { - float x = -step; + float vertexStep = 1.0f / (innerSize - 1); + float z = -vertexStep; + float textureStep = 1.0f / _heightSize; + float t = textureStep / 2.0f; + for (int i = 0; i < _heightSize; i++, z += vertexStep, t += textureStep) { + float x = -vertexStep; + float s = textureStep / 2.0f; const float SKIRT_LENGTH = 0.25f; - float baseY = (i == 0 || i == sizeWithSkirt - 1) ? -SKIRT_LENGTH : 0.0f; - for (int j = 0; j < sizeWithSkirt; j++, point++, x += step) { - point->vertex = glm::vec3(x, (j == 0 || j == sizeWithSkirt - 1) ? -SKIRT_LENGTH : baseY, z); - point->textureCoord = glm::vec2(x, z); + float baseY = (i == 0 || i == _heightSize - 1) ? -SKIRT_LENGTH : 0.0f; + for (int j = 0; j < _heightSize; j++, point++, x += vertexStep, s += textureStep) { + point->vertex = glm::vec3(x, (j == 0 || j == _heightSize - 1) ? -SKIRT_LENGTH : baseY, z); + point->textureCoord = glm::vec2(s, t); } } @@ -422,8 +426,8 @@ void HeightfieldBuffer::render(bool cursor) { QVector indices(indexCount); int* index = indices.data(); for (int i = 0; i < rows; i++) { - int lineIndex = i * sizeWithSkirt; - int nextLineIndex = (i + 1) * sizeWithSkirt; + int lineIndex = i * _heightSize; + int nextLineIndex = (i + 1) * _heightSize; for (int j = 0; j < rows; j++) { *index++ = lineIndex + j; *index++ = nextLineIndex + j; @@ -452,17 +456,15 @@ void HeightfieldBuffer::render(bool cursor) { glBindTexture(GL_TEXTURE_2D, _heightTextureID); - int heightScaleLocation; - if (cursor) { - heightScaleLocation = DefaultMetavoxelRendererImplementation::getCursorHeightScaleLocation(); - } else { - heightScaleLocation = DefaultMetavoxelRendererImplementation::getHeightScaleLocation(); + if (!cursor) { + DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getHeightScaleLocation(), 1.0f / _heightSize); + DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getColorScaleLocation(), (float)_heightSize / innerSize); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _colorTextureID); } - DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(heightScaleLocation, 1.0f / _heightSize); - glDrawRangeElements(GL_QUADS, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); if (!cursor) { @@ -548,6 +550,7 @@ void DefaultMetavoxelRendererImplementation::init() { _heightfieldProgram.setUniformValue("heightMap", 0); _heightfieldProgram.setUniformValue("diffuseMap", 1); _heightScaleLocation = _heightfieldProgram.uniformLocation("heightScale"); + _colorScaleLocation = _heightfieldProgram.uniformLocation("colorScale"); _heightfieldProgram.release(); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + @@ -558,7 +561,6 @@ void DefaultMetavoxelRendererImplementation::init() { _heightfieldCursorProgram.bind(); _heightfieldCursorProgram.setUniformValue("heightMap", 0); - _cursorHeightScaleLocation = _heightfieldCursorProgram.uniformLocation("heightScale"); _heightfieldCursorProgram.release(); } } @@ -648,14 +650,62 @@ HeightfieldAugmentVisitor::HeightfieldAugmentVisitor(const MetavoxelLOD& lod) : Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod) { } +class BorderFetchVisitor : public MetavoxelVisitor { +public: + + BorderFetchVisitor(const MetavoxelLOD& lod, QByteArray& height); + + virtual int visit(MetavoxelInfo& info); + +private: + + QByteArray& _height; +}; + +BorderFetchVisitor::BorderFetchVisitor(const MetavoxelLOD& lod, QByteArray& height) : + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute(), + QVector(), lod), + _height(height) { +} + +int BorderFetchVisitor::visit(MetavoxelInfo& info) { + if (!info.isLeaf) { + return DEFAULT_ORDER; + } + return STOP_RECURSION; +} + int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) { if (info.isLeaf) { HeightfieldBuffer* buffer = NULL; HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue(); if (height) { + const QByteArray& heightContents = height->getContents(); + int size = glm::sqrt(heightContents.size()); + int extendedSize = size + 3; + QByteArray extendedHeightContents(extendedSize * extendedSize, 0); + char* dest = extendedHeightContents.data() + extendedSize + 1; + const char* src = heightContents.constData(); + for (int z = 0; z < size; z++, src += size, dest += extendedSize) { + memcpy(dest, src, size); + } + QByteArray extendedColorContents; HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue(); - buffer = new HeightfieldBuffer(info.minimum, info.size, height->getContents(), - color ? color->getContents() : QByteArray()); + if (color) { + const QByteArray& colorContents = color->getContents(); + const int BYTES_PER_PIXEL = 3; + int colorSize = glm::sqrt(colorContents.size() / BYTES_PER_PIXEL); + int extendedColorSize = colorSize + 1; + extendedColorContents = QByteArray(extendedColorSize * extendedColorSize * BYTES_PER_PIXEL, 0); + char* dest = extendedColorContents.data(); + const char* src = colorContents.constData(); + int srcStride = colorSize * BYTES_PER_PIXEL; + int destStride = extendedColorSize * BYTES_PER_PIXEL; + for (int z = 0; z < colorSize; z++, src += srcStride, dest += destStride) { + memcpy(dest, src, srcStride); + } + } + buffer = new HeightfieldBuffer(info.minimum, info.size, extendedHeightContents, extendedColorContents); } info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); return STOP_RECURSION; @@ -856,8 +906,8 @@ ProgramObject DefaultMetavoxelRendererImplementation::_pointProgram; int DefaultMetavoxelRendererImplementation::_pointScaleLocation; ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldProgram; int DefaultMetavoxelRendererImplementation::_heightScaleLocation; +int DefaultMetavoxelRendererImplementation::_colorScaleLocation; ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram; -int DefaultMetavoxelRendererImplementation::_cursorHeightScaleLocation; static void enableClipPlane(GLenum plane, float x, float y, float z, float w) { GLdouble coefficients[] = { x, y, z, w }; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 7b681ff3a9..0940ea4d19 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -194,9 +194,9 @@ public: static ProgramObject& getHeightfieldProgram() { return _heightfieldProgram; } static int getHeightScaleLocation() { return _heightScaleLocation; } - + static int getColorScaleLocation() { return _colorScaleLocation; } + static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; } - static int getCursorHeightScaleLocation() { return _cursorHeightScaleLocation; } Q_INVOKABLE DefaultMetavoxelRendererImplementation(); @@ -211,9 +211,9 @@ private: static ProgramObject _heightfieldProgram; static int _heightScaleLocation; + static int _colorScaleLocation; static ProgramObject _heightfieldCursorProgram; - static int _cursorHeightScaleLocation; }; /// Base class for spanner renderers; provides clipping. diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index d35ed93f1b..260d3c2b3b 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1003,30 +1003,34 @@ void ImportHeightfieldTool::updatePreview() { if (_heightImage.width() > 0 && _heightImage.height() > 0) { float z = 0.0f; int blockSize = pow(2.0, _blockSize->value()); - int blockAdvancement = blockSize - 1; - for (int i = 0; i < _heightImage.height(); i += blockAdvancement, z++) { + int heightSize = blockSize + 3; + int colorSize = blockSize + 1; + for (int i = 0; i < _heightImage.height(); i += blockSize, z++) { float x = 0.0f; - for (int j = 0; j < _heightImage.width(); j += blockAdvancement, x++) { - QByteArray height(blockSize * blockSize, 0); - int rows = qMin(blockSize, _heightImage.height() - i); - int columns = qMin(blockSize, _heightImage.width() - j); + for (int j = 0; j < _heightImage.width(); j += blockSize, x++) { + QByteArray height(heightSize * heightSize, 0); + int extendedI = qMax(i - 1, 0); + int extendedJ = qMax(j - 1, 0); + int offsetY = extendedI - i + 1; + int offsetX = extendedJ - j + 1; + int rows = qMin(heightSize - offsetY, _heightImage.height() - extendedI); + int columns = qMin(heightSize - offsetX, _heightImage.width() - extendedJ); const int BYTES_PER_COLOR = 3; for (int y = 0; y < rows; y++) { - uchar* src = _heightImage.scanLine(i + y) + j * BYTES_PER_COLOR; - char* dest = height.data() + y * blockSize; + uchar* src = _heightImage.scanLine(extendedI + y) + extendedJ * BYTES_PER_COLOR; + char* dest = height.data() + (y + offsetY) * heightSize + offsetX; for (int x = 0; x < columns; x++) { *dest++ = *src; src += BYTES_PER_COLOR; } } - QByteArray color; if (!_colorImage.isNull()) { - color = QByteArray(blockSize * blockSize * BYTES_PER_COLOR, 0); - rows = qMax(0, qMin(blockSize, _colorImage.height() - i)); - columns = qMax(0, qMin(blockSize, _colorImage.width() - j)); + color = QByteArray(colorSize * colorSize * BYTES_PER_COLOR, 0); + rows = qMax(0, qMin(colorSize, _colorImage.height() - i)); + columns = qMax(0, qMin(colorSize, _colorImage.width() - j)); for (int y = 0; y < rows; y++) { - memcpy(color.data() + y * blockSize * BYTES_PER_COLOR, + memcpy(color.data() + y * colorSize * BYTES_PER_COLOR, _colorImage.scanLine(i + y) + j * BYTES_PER_COLOR, columns * BYTES_PER_COLOR); } }