Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 3 files). Show all
Unified · Split
| @@ -449,9 +449,10 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r · 448 unmodified lines | |||
| 449 | glDepthFunc(GL_LESS); | 449 | glDepthFunc(GL_LESS); |
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | void MetavoxelSystem::deleteTextures(int heightID, int colorID) { | 452 | void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) { |
| 453 | glDeleteTextures(1, (GLuint*)&heightID); | 453 | glDeleteTextures(1, (GLuint*)&heightID); |
| 454 | glDeleteTextures(1, (GLuint*)&colorID); | 454 | glDeleteTextures(1, (GLuint*)&colorID); |
| 455 | glDeleteTextures(1, (GLuint*)&textureID); | ||
| 455 | } | 456 | } |
| 456 | 457 | ||
| 457 | MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { | 458 | MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { |
| @@ -601,19 +602,24 @@ const int HeightfieldBuffer::SHARED_EDGE = 1; · 143 unmodified lines | |||
| 601 | const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE; | 602 | const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE; |
| 602 | 603 | ||
| 603 | HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, | 604 | HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, |
| 604 | const QByteArray& height, const QByteArray& color) : | 605 | const QByteArray& height, const QByteArray& color, const QByteArray& texture) : |
| 605 | _translation(translation), | 606 | _translation(translation), |
| 606 | _scale(scale), | 607 | _scale(scale), |
| 607 | _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), | 608 | _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), |
| 608 | _colorBounds(_heightBounds), | 609 | _colorBounds(_heightBounds), |
| 610 | _textureBounds(_heightBounds), | ||
| 609 | _height(height), | 611 | _height(height), |
| 610 | _color(color), | 612 | _color(color), |
| 613 | _texture(texture), | ||
| 611 | _heightTextureID(0), | 614 | _heightTextureID(0), |
| 612 | _colorTextureID(0), | 615 | _colorTextureID(0), |
| 616 | _textureTextureID(0), | ||
| 613 | _heightSize(glm::sqrt(height.size())), | 617 | _heightSize(glm::sqrt(height.size())), |
| 614 | _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), | 618 | _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), |
| 615 | _colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)), | 619 | _colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)), |
| 616 | _colorIncrement(scale / (_colorSize - SHARED_EDGE)) { | 620 | _colorIncrement(scale / (_colorSize - SHARED_EDGE)), |
| 621 | _textureSize(glm::sqrt(texture.size())), | ||
| 622 | _textureIncrement(scale / (_textureSize - SHARED_EDGE)) { | ||
| 617 | 623 | ||
| 618 | _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; | 624 | _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; |
| 619 | _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER; | 625 | _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER; |
| @@ -622,16 +628,20 @@ HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, · 2 unmodified lines | |||
| 622 | 628 | ||
| 623 | _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; | 629 | _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; |
| 624 | _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; | 630 | _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; |
| 631 | |||
| 632 | _textureBounds.maximum.x += _textureIncrement * SHARED_EDGE; | ||
| 633 | _textureBounds.maximum.z += _textureIncrement * SHARED_EDGE; | ||
| 625 | } | 634 | } |
| 626 | 635 | ||
| 627 | HeightfieldBuffer::~HeightfieldBuffer() { | 636 | HeightfieldBuffer::~HeightfieldBuffer() { |
| 628 | // the textures have to be deleted on the main thread (for its opengl context) | 637 | // the textures have to be deleted on the main thread (for its opengl context) |
| 629 | if (QThread::currentThread() != Application::getInstance()->thread()) { | 638 | if (QThread::currentThread() != Application::getInstance()->thread()) { |
| 630 | QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", | 639 | QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", |
| 631 | Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID)); | 640 | Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID), Q_ARG(int, _textureTextureID)); |
| 632 | } else { | 641 | } else { |
| 633 | glDeleteTextures(1, &_heightTextureID); | 642 | glDeleteTextures(1, &_heightTextureID); |
| 634 | glDeleteTextures(1, &_colorTextureID); | 643 | glDeleteTextures(1, &_colorTextureID); |
| 644 | glDeleteTextures(1, &_textureTextureID); | ||
| 635 | } | 645 | } |
| 636 | } | 646 | } |
| 637 | 647 | ||
| @@ -692,6 +702,17 @@ void HeightfieldBuffer::render(bool cursor) { · 54 unmodified lines | |||
| 692 | int colorSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES); | 702 | int colorSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES); |
| 693 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData()); | 703 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData()); |
| 694 | } | 704 | } |
| 705 | |||
| 706 | if (!_texture.isEmpty()) { | ||
| 707 | glGenTextures(1, &_textureTextureID); | ||
| 708 | glBindTexture(GL_TEXTURE_2D, _textureTextureID); | ||
| 709 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
| 710 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
| 711 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
| 712 | int textureSize = glm::sqrt(_texture.size()); | ||
| 713 | glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, textureSize, textureSize, 0, | ||
| 714 | GL_LUMINANCE, GL_UNSIGNED_BYTE, _texture.constData()); | ||
| 715 | } | ||
| 695 | } | 716 | } |
| 696 | // create the buffer objects lazily | 717 | // create the buffer objects lazily |
| 697 | int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; | 718 | int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; |
| @@ -998,7 +1019,8 @@ private: · 300 unmodified lines | |||
| 998 | 1019 | ||
| 999 | HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) : | 1020 | HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) : |
| 1000 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | 1021 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << |
| 1001 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod), | 1022 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << |
| 1023 | AttributeRegistry::getInstance()->getHeightfieldTextureAttribute(), QVector<AttributePointer>(), lod), | ||
| 1002 | _intersections(intersections) { | 1024 | _intersections(intersections) { |
| 1003 | } | 1025 | } |
| 1004 | 1026 | ||
| @@ -1065,11 +1087,11 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { · 60 unmodified lines | |||
| 1065 | 1087 | ||
| 1066 | int colorSize = _buffer->getColorSize(); | 1088 | int colorSize = _buffer->getColorSize(); |
| 1067 | if (colorSize == 0) { | 1089 | if (colorSize == 0) { |
| 1068 | return STOP_RECURSION; | 1090 | continue; |
| 1069 | } | 1091 | } |
| 1070 | HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>(); | 1092 | HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>(); |
| 1071 | if (!color) { | 1093 | if (!color) { |
| 1072 | return STOP_RECURSION; | 1094 | continue; |
| 1073 | } | 1095 | } |
| 1074 | const Box& colorBounds = _buffer->getColorBounds(); | 1096 | const Box& colorBounds = _buffer->getColorBounds(); |
| 1075 | overlap = colorBounds.getIntersection(overlap); | 1097 | overlap = colorBounds.getIntersection(overlap); |
| @@ -1113,6 +1135,50 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { · 37 unmodified lines | |||
| 1113 | } | 1135 | } |
| 1114 | } | 1136 | } |
| 1115 | } | 1137 | } |
| 1138 | |||
| 1139 | int textureSize = _buffer->getTextureSize(); | ||
| 1140 | if (textureSize == 0) { | ||
| 1141 | continue; | ||
| 1142 | } | ||
| 1143 | HeightfieldTextureDataPointer texture = info.inputValues.at(2).getInlineValue<HeightfieldTextureDataPointer>(); | ||
| 1144 | if (!texture) { | ||
| 1145 | continue; | ||
| 1146 | } | ||
| 1147 | const Box& textureBounds = _buffer->getTextureBounds(); | ||
| 1148 | overlap = textureBounds.getIntersection(overlap); | ||
| 1149 | float textureIncrement = _buffer->getTextureIncrement(); | ||
| 1150 | destX = (overlap.minimum.x - textureBounds.minimum.x) / textureIncrement; | ||
| 1151 | destY = (overlap.minimum.z - textureBounds.minimum.z) / textureIncrement; | ||
| 1152 | destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / textureIncrement); | ||
| 1153 | destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / textureIncrement); | ||
| 1154 | dest = _buffer->getTexture().data() + destY * textureSize + destX; | ||
| 1155 | |||
| 1156 | const QByteArray& srcTexture = texture->getContents(); | ||
| 1157 | srcSize = glm::sqrt(srcTexture.size()); | ||
| 1158 | srcIncrement = info.size / srcSize; | ||
| 1159 | |||
| 1160 | if (srcIncrement == textureIncrement) { | ||
| 1161 | // easy case: same resolution | ||
| 1162 | int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | ||
| 1163 | int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | ||
| 1164 | |||
| 1165 | const char* src = srcTexture.constData() + srcY * srcSize + srcX; | ||
| 1166 | for (int y = 0; y < destHeight; y++, src += srcSize, dest += textureSize) { | ||
| 1167 | memcpy(dest, src, destWidth); | ||
| 1168 | } | ||
| 1169 | } else { | ||
| 1170 | // more difficult: different resolutions | ||
| 1171 | float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement; | ||
| 1172 | float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement; | ||
| 1173 | float srcAdvance = textureIncrement / srcIncrement; | ||
| 1174 | for (int y = 0; y < destHeight; y++, dest += textureSize, srcY += srcAdvance) { | ||
| 1175 | const char* src = srcTexture.constData() + (int)srcY * srcSize; | ||
| 1176 | float lineSrcX = srcX; | ||
| 1177 | for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) { | ||
| 1178 | *lineDest = src[(int)lineSrcX]; | ||
| 1179 | } | ||
| 1180 | } | ||
| 1181 | } | ||
| 1116 | } | 1182 | } |
| 1117 | return STOP_RECURSION; | 1183 | return STOP_RECURSION; |
| 1118 | } | 1184 | } |
| @@ -1138,6 +1204,7 @@ private: · 19 unmodified lines | |||
| 1138 | HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : | 1204 | HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : |
| 1139 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << | 1205 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << |
| 1140 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << | 1206 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << |
| 1207 | AttributeRegistry::getInstance()->getHeightfieldTextureAttribute() << | ||
| 1141 | Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << | 1208 | Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << |
| 1142 | Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), | 1209 | Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), |
| 1143 | regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)), | 1210 | 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) { · 21 unmodified lines | |||
| 1165 | colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES; | 1232 | colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES; |
| 1166 | } | 1233 | } |
| 1167 | 1234 | ||
| 1235 | HeightfieldTextureDataPointer texture = info.inputValues.at(2).getInlineValue<HeightfieldTextureDataPointer>(); | ||
| 1236 | int textureContentsSize = 0; | ||
| 1237 | if (texture) { | ||
| 1238 | const QByteArray& textureContents = texture->getContents(); | ||
| 1239 | int textureSize = glm::sqrt(textureContents.size()); | ||
| 1240 | int extendedTextureSize = textureSize + HeightfieldBuffer::SHARED_EDGE; | ||
| 1241 | textureContentsSize = extendedTextureSize * extendedTextureSize; | ||
| 1242 | } | ||
| 1243 | |||
| 1168 | const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>( | 1244 | const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>( |
| 1169 | info.inputValues.at(2).getInlineValue<BufferDataPointer>().data()); | 1245 | info.inputValues.at(3).getInlineValue<BufferDataPointer>().data()); |
| 1170 | Box bounds = info.getBounds(); | 1246 | Box bounds = info.getBounds(); |
| 1171 | if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && | 1247 | if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && |
| 1172 | existingBuffer->getColor().size() == colorContentsSize) { | 1248 | existingBuffer->getColor().size() == colorContentsSize && |
| 1249 | existingBuffer->getTexture().size() == textureContentsSize) { | ||
| 1173 | // we already have a buffer of the correct resolution | 1250 | // we already have a buffer of the correct resolution |
| 1174 | addRegion(bounds, existingBuffer->getHeightBounds()); | 1251 | addRegion(bounds, existingBuffer->getHeightBounds()); |
| 1175 | return STOP_RECURSION; | 1252 | return STOP_RECURSION; |
| 1176 | } | 1253 | } |
| 1177 | // we must create a new buffer and update its borders | 1254 | // we must create a new buffer and update its borders |
| 1178 | buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), | 1255 | buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), |
| 1179 | QByteArray(colorContentsSize, 0)); | 1256 | QByteArray(colorContentsSize, 0), QByteArray(textureContentsSize, 0)); |
| 1180 | const Box& heightBounds = buffer->getHeightBounds(); | 1257 | const Box& heightBounds = buffer->getHeightBounds(); |
| 1181 | addRegion(bounds, heightBounds); | 1258 | addRegion(bounds, heightBounds); |
| 1182 | 1259 | ||
| @@ -1249,7 +1326,7 @@ int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { · 66 unmodified lines | |||
| 1249 | return STOP_RECURSION; | 1326 | return STOP_RECURSION; |
| 1250 | } | 1327 | } |
| 1251 | HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, | 1328 | HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, |
| 1252 | buffer->getHeight(), buffer->getColor()); | 1329 | buffer->getHeight(), buffer->getColor(), buffer->getTexture()); |
| 1253 | _fetchVisitor.init(newBuffer); | 1330 | _fetchVisitor.init(newBuffer); |
| 1254 | _data->guide(_fetchVisitor); | 1331 | _data->guide(_fetchVisitor); |
| 1255 | info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); | 1332 | info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); |