From 479bea1eb2bb0be2cebc3b5a7811775089040551 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 14 Nov 2014 17:18:34 -0800 Subject: [PATCH] Removed heightfield buffer code. --- interface/src/MetavoxelSystem.cpp | 835 +----------------------------- interface/src/MetavoxelSystem.h | 88 ---- 2 files changed, 9 insertions(+), 914 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 5ff179765e..7edf96d1c6 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -58,11 +58,6 @@ void MetavoxelSystem::init() { MetavoxelClientManager::init(); DefaultMetavoxelRendererImplementation::init(); - _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( - new BufferDataAttribute("heightfieldBuffer")); - _heightfieldBufferAttribute->setLODThresholdMultiplier( - AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier()); - _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( new BufferDataAttribute("voxelBuffer")); _voxelBufferAttribute->setLODThresholdMultiplier( @@ -375,12 +370,6 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) glDepthFunc(GL_LESS); } -void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) { - glDeleteTextures(1, (GLuint*)&heightID); - glDeleteTextures(1, (GLuint*)&colorID); - glDeleteTextures(1, (GLuint*)&textureID); -} - class MaterialEditApplier : public SignalHandler { public: @@ -670,357 +659,12 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { BufferData::~BufferData() { } -const int HeightfieldBuffer::HEIGHT_BORDER = 1; -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& material, - const QVector& materials) : - _translation(translation), - _scale(scale), - _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), - _colorBounds(_heightBounds), - _materialBounds(_heightBounds), - _height(height), - _color(color), - _material(material), - _materials(materials), - _heightTextureID(0), - _colorTextureID(0), - _materialTextureID(0), - _heightSize(glm::sqrt((float)height.size())), - _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), - _colorSize(glm::sqrt((float)color.size() / DataBlock::COLOR_BYTES)), - _colorIncrement(scale / (_colorSize - SHARED_EDGE)), - _materialSize(glm::sqrt((float)material.size())), - _materialIncrement(scale / (_materialSize - SHARED_EDGE)) { - - _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; - _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER; - _heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER); - _heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER); - - _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; - _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; - - _materialBounds.maximum.x += _materialIncrement * SHARED_EDGE; - _materialBounds.maximum.z += _materialIncrement * 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, _materialTextureID)); - } else { - glDeleteTextures(1, &_heightTextureID); - glDeleteTextures(1, &_colorTextureID); - glDeleteTextures(1, &_materialTextureID); - } -} - -QByteArray HeightfieldBuffer::getUnextendedHeight() const { - int srcSize = glm::sqrt(float(_height.size())); - int destSize = srcSize - 3; - QByteArray unextended(destSize * destSize, 0); - const char* src = _height.constData() + srcSize + 1; - char* dest = unextended.data(); - for (int z = 0; z < destSize; z++, src += srcSize, dest += destSize) { - memcpy(dest, src, destSize); - } - return unextended; -} - -QByteArray HeightfieldBuffer::getUnextendedColor(int x, int y) const { - int unextendedSize = _heightSize - HEIGHT_EXTENSION; - QByteArray unextended(unextendedSize * unextendedSize * DataBlock::COLOR_BYTES, 0); - char* dest = unextended.data(); - const char* src = _color.constData() + (y * _colorSize + x) * unextendedSize * DataBlock::COLOR_BYTES; - for (int z = 0; z < unextendedSize; z++, dest += unextendedSize * DataBlock::COLOR_BYTES, - src += _colorSize * DataBlock::COLOR_BYTES) { - memcpy(dest, src, unextendedSize * DataBlock::COLOR_BYTES); - } - return unextended; -} - -class HeightfieldPoint { -public: - glm::vec2 textureCoord; - glm::vec3 vertex; -}; - const int SPLAT_COUNT = 4; const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; static const int EIGHT_BIT_MAXIMUM = 255; static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; -void HeightfieldBuffer::render(bool cursor) { - // initialize textures, etc. on first render - 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_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, _heightSize, _heightSize, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, _height.constData()); - - glGenTextures(1, &_colorTextureID); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - 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); - if (_color.isEmpty()) { - const quint8 WHITE_COLOR[] = { 255, 255, 255 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR); - - } else { - int colorSize = glm::sqrt(float(_color.size() / DataBlock::COLOR_BYTES)); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData()); - } - - if (!_material.isEmpty()) { - glGenTextures(1, &_materialTextureID); - glBindTexture(GL_TEXTURE_2D, _materialTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - 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 materialSize = glm::sqrt(float(_material.size())); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, materialSize, materialSize, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, _material.constData()); - - _networkTextures.resize(_materials.size()); - for (int i = 0; i < _materials.size(); i++) { - const SharedObjectPointer material = _materials.at(i); - if (material) { - _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture( - static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); - } - } - } - } - // create the buffer objects lazily - int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; - int vertexCount = _heightSize * _heightSize; - int rows = _heightSize - 1; - int indexCount = rows * rows * 3 * 2; - BufferPair& bufferPair = _bufferPairs[_heightSize]; - if (!bufferPair.first.isCreated()) { - QVector vertices(vertexCount); - HeightfieldPoint* point = vertices.data(); - - 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 == _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); - } - } - - bufferPair.first.setUsagePattern(QOpenGLBuffer::StaticDraw); - bufferPair.first.create(); - bufferPair.first.bind(); - bufferPair.first.allocate(vertices.constData(), vertexCount * sizeof(HeightfieldPoint)); - - QVector indices(indexCount); - int* index = indices.data(); - for (int i = 0; i < rows; i++) { - int lineIndex = i * _heightSize; - int nextLineIndex = (i + 1) * _heightSize; - for (int j = 0; j < rows; j++) { - *index++ = lineIndex + j; - *index++ = nextLineIndex + j; - *index++ = nextLineIndex + j + 1; - - *index++ = nextLineIndex + j + 1; - *index++ = lineIndex + j + 1; - *index++ = lineIndex + j; - } - } - - bufferPair.second = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); - bufferPair.second.create(); - bufferPair.second.bind(); - bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int)); - - } else { - bufferPair.first.bind(); - bufferPair.second.bind(); - } - - HeightfieldPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); - glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); - - glPushMatrix(); - glTranslatef(_translation.x, _translation.y, _translation.z); - glScalef(_scale, _scale, _scale); - - glBindTexture(GL_TEXTURE_2D, _heightTextureID); - - if (cursor) { - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - - } else if (!_materials.isEmpty()) { - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); - - glDepthFunc(GL_LEQUAL); - glDepthMask(false); - glEnable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind(); - const DefaultMetavoxelRendererImplementation::SplatLocations& locations = - DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations(); - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.heightScale, 1.0f / _heightSize); - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.textureScale, (float)_heightSize / innerSize); - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.splatTextureOffset, _translation.x / _scale, _translation.z / _scale); - - glBindTexture(GL_TEXTURE_2D, _materialTextureID); - - for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) { - QVector4D scalesS, scalesT; - - for (int j = 0; j < SPLAT_COUNT; j++) { - glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]); - int index = i + j; - if (index < _networkTextures.size()) { - const NetworkTexturePointer& texture = _networkTextures.at(index); - if (texture) { - MaterialObject* material = static_cast(_materials.at(index).data()); - scalesS[j] = _scale / material->getScaleS(); - scalesT[j] = _scale / material->getScaleT(); - glBindTexture(GL_TEXTURE_2D, texture->getID()); - } else { - glBindTexture(GL_TEXTURE_2D, 0); - } - } else { - glBindTexture(GL_TEXTURE_2D, 0); - } - } - const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.splatTextureScalesS, scalesS); - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.splatTextureScalesT, scalesT); - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.textureValueMinima, - (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); - DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( - locations.textureValueMaxima, - (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - } - - for (int i = 0; i < SPLAT_COUNT; i++) { - glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); - glBindTexture(GL_TEXTURE_2D, 0); - } - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture(GL_TEXTURE0); - - glDisable(GL_POLYGON_OFFSET_FILL); - glEnable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glDepthMask(true); - glDepthFunc(GL_LESS); - - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); - - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); - - } else { - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize); - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - - glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - } - - glBindTexture(GL_TEXTURE_2D, 0); - - glPopMatrix(); - - bufferPair.first.release(); - bufferPair.second.release(); -} - -QHash HeightfieldBuffer::_bufferPairs; - -void HeightfieldPreview::render(const glm::vec3& translation, float scale) const { - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true); - - glDisable(GL_BLEND); - glEnable(GL_CULL_FACE); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_EQUAL, 0.0f); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind(); - - glPushMatrix(); - glTranslatef(translation.x, translation.y, translation.z); - glScalef(scale, scale, scale); - - foreach (const BufferDataPointer& buffer, _buffers) { - buffer->render(); - } - - glPopMatrix(); - - DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release(); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); -} - void VoxelPoint::setNormal(const glm::vec3& normal) { this->normal[0] = (char)(normal.x * 127.0f); this->normal[1] = (char)(normal.y * 127.0f); @@ -1344,446 +988,6 @@ void DefaultMetavoxelRendererImplementation::init() { DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() { } -class HeightfieldFetchVisitor : public MetavoxelVisitor { -public: - - HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector& intersections); - - void init(HeightfieldBuffer* buffer); - - virtual int visit(MetavoxelInfo& info); - virtual bool postVisit(MetavoxelInfo& info); - -private: - - const QVector& _intersections; - HeightfieldBuffer* _buffer; - - QVector _depthFlags; -}; - -enum DepthFlags { HEIGHT_FLAG = 0x01, COLOR_FLAG = 0x02, MATERIAL_FLAG = 0x04 }; - -HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector& intersections) : - MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << - AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << - AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector(), lod), - _intersections(intersections) { -} - -void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) { - _buffer = buffer; -} - -int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { - if (!info.getBounds().intersects(_buffer->getHeightBounds())) { - return STOP_RECURSION; - } - if (_depthFlags.size() > _depth) { - _depthFlags[_depth] = 0; - } else { - _depthFlags.append(0); - } - if (!info.isLeaf) { - return DEFAULT_ORDER; - } - postVisit(info); - return STOP_RECURSION; -} - -bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) { - HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue(); - int flags = _depthFlags.at(_depth); - if (height) { - // to handle borders correctly, make sure we only sample nodes with resolution <= ours - int heightSize = glm::sqrt((float)height->getContents().size()); - float heightIncrement = info.size / heightSize; - if (heightIncrement < _buffer->getHeightIncrement() || (flags & HEIGHT_FLAG)) { - height.reset(); - } else { - flags |= HEIGHT_FLAG; - } - } - HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue(); - if (color) { - int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES); - float colorIncrement = info.size / colorSize; - if (colorIncrement < _buffer->getColorIncrement() || (flags & COLOR_FLAG)) { - color.reset(); - } else { - flags |= COLOR_FLAG; - } - } - HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue(); - if (material) { - int materialSize = glm::sqrt((float)material->getContents().size()); - float materialIncrement = info.size / materialSize; - if (materialIncrement < _buffer->getMaterialIncrement() || (flags & MATERIAL_FLAG)) { - material.reset(); - } else { - flags |= MATERIAL_FLAG; - } - } - if (_depth > 0) { - _depthFlags[_depth - 1] |= flags; - } - if (!(height || color || material)) { - return false; - } - Box bounds = info.getBounds(); - foreach (const Box& intersection, _intersections) { - Box overlap = intersection.getIntersection(bounds); - if (overlap.isEmpty()) { - continue; - } - if (height) { - float heightIncrement = _buffer->getHeightIncrement(); - const Box& heightBounds = _buffer->getHeightBounds(); - int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement; - int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement; - int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement); - int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement); - int heightSize = _buffer->getHeightSize(); - char* dest = _buffer->getHeight().data() + destY * heightSize + destX; - - const QByteArray& srcHeight = height->getContents(); - int srcSize = glm::sqrt((float)srcHeight.size()); - float srcIncrement = info.size / srcSize; - - if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) { - // 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 = srcHeight.constData() + srcY * srcSize + srcX; - for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) { - 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 = heightIncrement / srcIncrement; - int shift = 0; - float size = _buffer->getScale(); - while (size < info.size) { - shift++; - size *= 2.0f; - } - int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale(); - for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) { - const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize; - float lineSrcX = srcX; - for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { - *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM); - } - } - } - } - if (color) { - const Box& colorBounds = _buffer->getColorBounds(); - overlap = colorBounds.getIntersection(overlap); - float colorIncrement = _buffer->getColorIncrement(); - int destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement; - int destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement; - int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement); - int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement); - int colorSize = _buffer->getColorSize(); - char* dest = _buffer->getColor().data() + (destY * colorSize + destX) * DataBlock::COLOR_BYTES; - int destStride = colorSize * DataBlock::COLOR_BYTES; - int destBytes = destWidth * DataBlock::COLOR_BYTES; - - const QByteArray& srcColor = color->getContents(); - int srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES)); - int srcStride = srcSize * DataBlock::COLOR_BYTES; - float srcIncrement = info.size / srcSize; - - if (srcIncrement == colorIncrement) { - // 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 = srcColor.constData() + (srcY * srcSize + srcX) * DataBlock::COLOR_BYTES; - for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) { - memcpy(dest, src, destBytes); - } - } 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 = colorIncrement / srcIncrement; - for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) { - const char* src = srcColor.constData() + (int)srcY * srcStride; - float lineSrcX = srcX; - for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += DataBlock::COLOR_BYTES, - lineSrcX += srcAdvance) { - const char* lineSrc = src + (int)lineSrcX * DataBlock::COLOR_BYTES; - lineDest[0] = lineSrc[0]; - lineDest[1] = lineSrc[1]; - lineDest[2] = lineSrc[2]; - } - } - } - } - if (material) { - const Box& materialBounds = _buffer->getMaterialBounds(); - overlap = materialBounds.getIntersection(overlap); - float materialIncrement = _buffer->getMaterialIncrement(); - int destX = (overlap.minimum.x - materialBounds.minimum.x) / materialIncrement; - int destY = (overlap.minimum.z - materialBounds.minimum.z) / materialIncrement; - int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / materialIncrement); - int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / materialIncrement); - int materialSize = _buffer->getMaterialSize(); - char* dest = _buffer->getMaterial().data() + destY * materialSize + destX; - - const QByteArray& srcMaterial = material->getContents(); - const QVector srcMaterials = material->getMaterials(); - int srcSize = glm::sqrt((float)srcMaterial.size()); - float srcIncrement = info.size / srcSize; - QHash materialMappings; - - if (srcIncrement == materialIncrement) { - // easy case: same resolution - int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; - int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; - - const uchar* src = (const uchar*)srcMaterial.constData() + srcY * srcSize + srcX; - for (int y = 0; y < destHeight; y++, src += srcSize, dest += materialSize) { - const uchar* lineSrc = src; - for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrc++) { - int value = *lineSrc; - if (value != 0) { - int& mapping = materialMappings[value]; - if (mapping == 0) { - mapping = getMaterialIndex(material->getMaterials().at(value - 1), - _buffer->getMaterials(), _buffer->getMaterial()); - } - value = mapping; - } - *lineDest = value; - } - } - } 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 = materialIncrement / srcIncrement; - for (int y = 0; y < destHeight; y++, dest += materialSize, srcY += srcAdvance) { - const uchar* src = (const uchar*)srcMaterial.constData() + (int)srcY * srcSize; - float lineSrcX = srcX; - for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { - int value = src[(int)lineSrcX]; - if (value != 0) { - int& mapping = materialMappings[value]; - if (mapping == 0) { - mapping = getMaterialIndex(material->getMaterials().at(value - 1), - _buffer->getMaterials(), _buffer->getMaterial()); - } - value = mapping; - } - *lineDest = value; - } - } - } - clearUnusedMaterials(_buffer->getMaterials(), _buffer->getMaterial()); - } - } - return false; -} - -class HeightfieldRegionVisitor : public MetavoxelVisitor { -public: - - QVector regions; - Box regionBounds; - - HeightfieldRegionVisitor(const MetavoxelLOD& lod); - - virtual int visit(MetavoxelInfo& info); - virtual bool postVisit(MetavoxelInfo& info); - -private: - - void addRegion(const Box& unextended, const Box& extended); - - class DepthInfo { - public: - float minimumColorIncrement; - float minimumMaterialIncrement; - - DepthInfo() : minimumColorIncrement(FLT_MAX), minimumMaterialIncrement(FLT_MAX) { } - }; - - QVector _depthInfo; - - QVector _intersections; - HeightfieldFetchVisitor _fetchVisitor; -}; - -HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : - MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << - AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << - AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute() << - 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)), - _fetchVisitor(lod, _intersections) { -} - -int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) { - DepthInfo depthInfo; - HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue(); - if (color) { - int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES); - depthInfo.minimumColorIncrement = info.size / colorSize; - } - HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue(); - if (material) { - int materialSize = glm::sqrt((float)material->getContents().size()); - depthInfo.minimumMaterialIncrement = info.size / materialSize; - } - if (_depth < _depthInfo.size()) { - _depthInfo[_depth] = depthInfo; - } else { - _depthInfo.append(depthInfo); - } - if (!info.isLeaf) { - return _visitations.at(_depth).isInputLeaf(0) ? (DEFAULT_ORDER | ALL_NODES_REST) : DEFAULT_ORDER; - } - postVisit(info); - return STOP_RECURSION; -} - -bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) { - const DepthInfo& depthInfo = _depthInfo.at(_depth); - if (_depth > 0) { - DepthInfo& parentDepthInfo = _depthInfo[_depth - 1]; - parentDepthInfo.minimumColorIncrement = qMin(parentDepthInfo.minimumColorIncrement, depthInfo.minimumColorIncrement); - parentDepthInfo.minimumMaterialIncrement = qMin(parentDepthInfo.minimumMaterialIncrement, - depthInfo.minimumMaterialIncrement); - } - if (_visitations.at(_depth).isInputLeaf(0)) { - HeightfieldBuffer* buffer = NULL; - HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue(); - if (height) { - int heightSize = glm::sqrt((float)height->getContents().size()); - int extendedHeightSize = heightSize + HeightfieldBuffer::HEIGHT_EXTENSION; - int heightContentsSize = extendedHeightSize * extendedHeightSize; - float minimumColorIncrement = depthInfo.minimumColorIncrement; - float minimumMaterialIncrement = depthInfo.minimumMaterialIncrement; - for (int i = _depth - 1; i >= 0 && qMax(minimumColorIncrement, minimumMaterialIncrement) == FLT_MAX; i--) { - const DepthInfo& ancestorDepthInfo = _depthInfo.at(i); - minimumColorIncrement = qMin(minimumColorIncrement, ancestorDepthInfo.minimumColorIncrement); - minimumMaterialIncrement = qMin(minimumMaterialIncrement, ancestorDepthInfo.minimumMaterialIncrement); - } - int colorContentsSize = 0; - if (minimumColorIncrement != FLT_MAX) { - int colorSize = (int)glm::round(info.size / minimumColorIncrement) + HeightfieldBuffer::SHARED_EDGE; - colorContentsSize = colorSize * colorSize * DataBlock::COLOR_BYTES; - } - int materialContentsSize = 0; - if (minimumMaterialIncrement != FLT_MAX) { - int materialSize = (int)glm::round(info.size / minimumMaterialIncrement) + HeightfieldBuffer::SHARED_EDGE; - materialContentsSize = materialSize * materialSize; - } - const HeightfieldBuffer* existingBuffer = static_cast( - info.inputValues.at(3).getInlineValue().data()); - Box bounds = info.getBounds(); - if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && - existingBuffer->getColor().size() == colorContentsSize && - existingBuffer->getMaterial().size() == materialContentsSize) { - // we already have a buffer of the correct resolution - addRegion(bounds, existingBuffer->getHeightBounds()); - buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(), - existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials()); - - } else { - // we must create a new buffer and update its borders - buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), - QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0)); - const Box& heightBounds = buffer->getHeightBounds(); - addRegion(bounds, heightBounds); - - _intersections.clear(); - _intersections.append(Box(heightBounds.minimum, - glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z))); - _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z), - glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z))); - _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z), - heightBounds.maximum)); - _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z), - glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z))); - - _fetchVisitor.init(buffer); - _data->guide(_fetchVisitor); - } - } - BufferDataPointer pointer(buffer); - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); - } - return true; -} - -void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) { - regions.append(unextended); - regionBounds.add(extended); -} - -class HeightfieldUpdateVisitor : public MetavoxelVisitor { -public: - - HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector& regions, const Box& regionBounds); - - virtual int visit(MetavoxelInfo& info); - -private: - - const QVector& _regions; - const Box& _regionBounds; - QVector _intersections; - HeightfieldFetchVisitor _fetchVisitor; -}; - -HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector& regions, - const Box& regionBounds) : - MetavoxelVisitor(QVector() << - Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector() << - Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), - _regions(regions), - _regionBounds(regionBounds), - _fetchVisitor(lod, _intersections) { -} - -int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { - if (!info.getBounds().intersects(_regionBounds)) { - return STOP_RECURSION; - } - if (!info.isLeaf) { - return DEFAULT_ORDER; - } - const HeightfieldBuffer* buffer = static_cast( - info.inputValues.at(0).getInlineValue().data()); - if (!buffer) { - return STOP_RECURSION; - } - _intersections.clear(); - foreach (const Box& region, _regions) { - if (region.intersects(buffer->getHeightBounds())) { - _intersections.append(region.getIntersection(buffer->getHeightBounds())); - } - } - if (_intersections.isEmpty()) { - return STOP_RECURSION; - } - HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, - buffer->getHeight(), buffer->getColor(), buffer->getMaterial(), buffer->getMaterials()); - _fetchVisitor.init(newBuffer); - _data->guide(_fetchVisitor); - BufferDataPointer pointer(newBuffer); - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); - return STOP_RECURSION; -} - class VoxelAugmentVisitor : public MetavoxelVisitor { public: @@ -2392,27 +1596,13 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const while (expandedPrevious.getSize() < data.getSize()) { expandedPrevious.expand(); } - const AttributePointer& heightfieldBufferAttribute = - Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(); - MetavoxelNode* root = expandedPrevious.getRoot(heightfieldBufferAttribute); - if (root) { - data.setRoot(heightfieldBufferAttribute, root); - root->incrementReferenceCount(); - } const AttributePointer& voxelBufferAttribute = Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(); - root = expandedPrevious.getRoot(voxelBufferAttribute); + MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute); if (root) { data.setRoot(voxelBufferAttribute, root); root->incrementReferenceCount(); } - HeightfieldRegionVisitor heightfieldRegionVisitor(lod); - data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor); - - HeightfieldUpdateVisitor heightfieldUpdateVisitor(lod, heightfieldRegionVisitor.regions, - heightfieldRegionVisitor.regionBounds); - data.guide(heightfieldUpdateVisitor); - VoxelAugmentVisitor voxelAugmentVisitor(lod); data.guideToDifferent(expandedPrevious, voxelAugmentVisitor); } @@ -2535,19 +1725,6 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) { - _baseHeightfieldProgram.bind(); - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()); - data.guide(heightfieldRenderVisitor); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - _baseHeightfieldProgram.release(); - } - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) { glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); @@ -2756,6 +1933,12 @@ void HeightfieldRenderer::init(Spanner* spanner) { connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial); } +class HeightfieldPoint { +public: + glm::vec3 vertex; + glm::vec2 textureCoord; +}; + void HeightfieldRenderer::render(bool cursor) { // create the buffer objects lazily Heightfield* heightfield = static_cast(_spanner); @@ -2765,8 +1948,8 @@ void HeightfieldRenderer::render(bool cursor) { int width = heightfield->getHeight()->getWidth(); int height = heightfield->getHeight()->getContents().size() / width; - int innerWidth = width - 2 * HeightfieldBuffer::HEIGHT_BORDER; - int innerHeight = height - 2 * HeightfieldBuffer::HEIGHT_BORDER; + int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER; + int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER; int vertexCount = width * height; int rows = height - 1; int columns = width - 1; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index a911db123a..90560e63aa 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -78,8 +78,6 @@ public: Q_INVOKABLE void setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material); - Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID); - signals: void rendering(); @@ -185,92 +183,6 @@ public: typedef QExplicitlySharedDataPointer BufferDataPointer; -/// Contains the information necessary to render a heightfield block. -class HeightfieldBuffer : public BufferData { -public: - - static const int HEIGHT_BORDER; - static const int SHARED_EDGE; - static const int HEIGHT_EXTENSION; - - HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, - const QByteArray& color, const QByteArray& material = QByteArray(), - const QVector& materials = QVector()); - ~HeightfieldBuffer(); - - const glm::vec3& getTranslation() const { return _translation; } - float getScale() const { return _scale; } - - const Box& getHeightBounds() const { return _heightBounds; } - const Box& getColorBounds() const { return _colorBounds; } - const Box& getMaterialBounds() const { return _materialBounds; } - - QByteArray& getHeight() { return _height; } - const QByteArray& getHeight() const { return _height; } - - QByteArray& getColor() { return _color; } - const QByteArray& getColor() const { return _color; } - - QByteArray& getMaterial() { return _material; } - const QByteArray& getMaterial() const { return _material; } - - QVector& getMaterials() { return _materials; } - const QVector& getMaterials() const { return _materials; } - - QByteArray getUnextendedHeight() const; - QByteArray getUnextendedColor(int x = 0, int y = 0) const; - - int getHeightSize() const { return _heightSize; } - float getHeightIncrement() const { return _heightIncrement; } - - int getColorSize() const { return _colorSize; } - float getColorIncrement() const { return _colorIncrement; } - - int getMaterialSize() const { return _materialSize; } - float getMaterialIncrement() const { return _materialIncrement; } - - virtual void render(bool cursor = false); - -private: - - glm::vec3 _translation; - float _scale; - Box _heightBounds; - Box _colorBounds; - Box _materialBounds; - QByteArray _height; - QByteArray _color; - QByteArray _material; - QVector _materials; - GLuint _heightTextureID; - GLuint _colorTextureID; - GLuint _materialTextureID; - QVector _networkTextures; - int _heightSize; - float _heightIncrement; - int _colorSize; - float _colorIncrement; - int _materialSize; - float _materialIncrement; - - typedef QPair BufferPair; - static QHash _bufferPairs; -}; - -/// Convenience class for rendering a preview of a heightfield. -class HeightfieldPreview { -public: - - void setBuffers(const QVector& buffers) { _buffers = buffers; } - const QVector& getBuffers() const { return _buffers; } - - void render(const glm::vec3& translation, float scale) const; - -private: - - QVector _buffers; -}; - /// Describes contents of a vertex in a voxel buffer. class VoxelPoint { public: