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 | 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 | 453 | glDeleteTextures(1, (GLuint*)&heightID); |
| 454 | 454 | glDeleteTextures(1, (GLuint*)&colorID); |
| 455 | + glDeleteTextures(1, (GLuint*)&textureID); | |
| 455 | 456 | } |
| 456 | 457 | |
| 457 | 458 | MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { |
| @@ -601,19 +602,24 @@ const int HeightfieldBuffer::SHARED_EDGE = 1; · 143 unmodified lines | ||
| 601 | 602 | const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE; |
| 602 | 603 | |
| 603 | 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 | 606 | _translation(translation), |
| 606 | 607 | _scale(scale), |
| 607 | 608 | _heightBounds(translation, translation + glm::vec3(scale, scale, scale)), |
| 608 | 609 | _colorBounds(_heightBounds), |
| 610 | + _textureBounds(_heightBounds), | |
| 609 | 611 | _height(height), |
| 610 | 612 | _color(color), |
| 613 | + _texture(texture), | |
| 611 | 614 | _heightTextureID(0), |
| 612 | 615 | _colorTextureID(0), |
| 616 | + _textureTextureID(0), | |
| 613 | 617 | _heightSize(glm::sqrt(height.size())), |
| 614 | 618 | _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), |
| 615 | 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 | 624 | _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER; |
| 619 | 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 | 629 | _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE; |
| 624 | 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 | 636 | HeightfieldBuffer::~HeightfieldBuffer() { |
| 628 | 637 | // the textures have to be deleted on the main thread (for its opengl context) |
| 629 | 638 | if (QThread::currentThread() != Application::getInstance()->thread()) { |
| 630 | 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 | 641 | } else { |
| 633 | 642 | glDeleteTextures(1, &_heightTextureID); |
| 634 | 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 | 702 | int colorSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES); |
| 693 | 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 | 717 | // create the buffer objects lazily |
| 697 | 718 | int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; |
| @@ -998,7 +1019,8 @@ private: · 300 unmodified lines | ||
| 998 | 1019 | |
| 999 | 1020 | HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) : |
| 1000 | 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 | 1024 | _intersections(intersections) { |
| 1003 | 1025 | } |
| 1004 | 1026 | |
| @@ -1065,11 +1087,11 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) { · 60 unmodified lines | ||
| 1065 | 1087 | |
| 1066 | 1088 | int colorSize = _buffer->getColorSize(); |
| 1067 | 1089 | if (colorSize == 0) { |
| 1068 | − return STOP_RECURSION; | |
| 1090 | + continue; | |
| 1069 | 1091 | } |
| 1070 | 1092 | HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>(); |
| 1071 | 1093 | if (!color) { |
| 1072 | − return STOP_RECURSION; | |
| 1094 | + continue; | |
| 1073 | 1095 | } |
| 1074 | 1096 | const Box& colorBounds = _buffer->getColorBounds(); |
| 1075 | 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 | 1183 | return STOP_RECURSION; |
| 1118 | 1184 | } |
| @@ -1138,6 +1204,7 @@ private: · 19 unmodified lines | ||
| 1138 | 1204 | HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : |
| 1139 | 1205 | MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << |
| 1140 | 1206 | AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << |
| 1207 | + AttributeRegistry::getInstance()->getHeightfieldTextureAttribute() << | |
| 1141 | 1208 | Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() << |
| 1142 | 1209 | Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), |
| 1143 | 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 | 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 | 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 | 1246 | Box bounds = info.getBounds(); |
| 1171 | 1247 | if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && |
| 1172 | − existingBuffer->getColor().size() == colorContentsSize) { | |
| 1248 | + existingBuffer->getColor().size() == colorContentsSize && | |
| 1249 | + existingBuffer->getTexture().size() == textureContentsSize) { | |
| 1173 | 1250 | // we already have a buffer of the correct resolution |
| 1174 | 1251 | addRegion(bounds, existingBuffer->getHeightBounds()); |
| 1175 | 1252 | return STOP_RECURSION; |
| 1176 | 1253 | } |
| 1177 | 1254 | // we must create a new buffer and update its borders |
| 1178 | 1255 | buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), |
| 1179 | − QByteArray(colorContentsSize, 0)); | |
| 1256 | + QByteArray(colorContentsSize, 0), QByteArray(textureContentsSize, 0)); | |
| 1180 | 1257 | const Box& heightBounds = buffer->getHeightBounds(); |
| 1181 | 1258 | addRegion(bounds, heightBounds); |
| 1182 | 1259 | |
| @@ -1249,7 +1326,7 @@ int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { · 66 unmodified lines | ||
| 1249 | 1326 | return STOP_RECURSION; |
| 1250 | 1327 | } |
| 1251 | 1328 | HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, |
| 1252 | − buffer->getHeight(), buffer->getColor()); | |
| 1329 | + buffer->getHeight(), buffer->getColor(), buffer->getTexture()); | |
| 1253 | 1330 | _fetchVisitor.init(newBuffer); |
| 1254 | 1331 | _data->guide(_fetchVisitor); |
| 1255 | 1332 | info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); |