From e384a0f58f67256afc269d1233537ebc03a632db Mon Sep 17 00:00:00 2001 From: T1ti <40864460+T1ti@users.noreply.github.com> Date: Fri, 3 May 2024 08:15:56 +0200 Subject: [PATCH] update heightmap import to use range instead of multiplier + some polish --- src/noggit/MapTile.cpp | 42 ++-- src/noggit/MapTile.h | 3 +- src/noggit/MapView.cpp | 176 +++++++++++++++-- src/noggit/TileWater.cpp | 184 ++++++++++++++++++ src/noggit/TileWater.hpp | 2 + src/noggit/World.cpp | 59 +++++- src/noggit/World.h | 7 +- .../World/Tile/TileSetHeightmapImage.cpp | 3 +- 8 files changed, 433 insertions(+), 43 deletions(-) diff --git a/src/noggit/MapTile.cpp b/src/noggit/MapTile.cpp index f0a5b81c..e1490768 100755 --- a/src/noggit/MapTile.cpp +++ b/src/noggit/MapTile.cpp @@ -1054,7 +1054,9 @@ void MapTile::initEmptyChunks() QImage MapTile::getHeightmapImage(float min_height, float max_height) { - QImage image(257, 257, QImage::Format_Grayscale16); + // grayscale 16 doesn't work, it rounds values or is actually 8bit + QImage image(257, 257, QImage::Format_RGBA64); + int depth = image.depth(); unsigned const LONG{9}, SHORT{8}, SUM{LONG + SHORT}, DSUM{SUM * 2}; @@ -1076,7 +1078,7 @@ QImage MapTile::getHeightmapImage(float min_height, float max_height) unsigned const idx {(plain - (is_virtual ? (erp ? SUM : 1) : 0)) / 2}; float value = is_virtual ? (heightmap[idx].y + heightmap[idx + (erp ? SUM : 1)].y) / 2.f : heightmap[idx].y; value = std::min(1.0f, std::max(0.0f, ((value - min_height) / (max_height - min_height)))); - image.setPixelColor((k * 16) + x, (l * 16) + y, QColor::fromRgbF(value, value, value, 1.0)); + image.setPixelColor((k * 16) + x, (l * 16) + y, QColor::fromRgbF(value, value, value, 1.0)); // grayscale uses alpha channel ? } } } @@ -1126,7 +1128,7 @@ QImage MapTile::getNormalmapImage() QImage MapTile::getAlphamapImage(unsigned layer) { - QImage image(1024, 1024, QImage::Format_Grayscale8); + QImage image(1024, 1024, QImage::Format_RGBA8888); image.fill(Qt::black); for (int i = 0; i < 16; ++i) @@ -1159,7 +1161,7 @@ QImage MapTile::getAlphamapImage(unsigned layer) QImage MapTile::getAlphamapImage(std::string const& filename) { - QImage image(1024, 1024, QImage::Format_Grayscale8); + QImage image(1024, 1024, QImage::Format_RGBA8888); image.fill(Qt::black); for (int i = 0; i < 16; ++i) @@ -1230,9 +1232,11 @@ QImage MapTile::getAlphamapImage(std::string const& filename) return std::move(image); } -void MapTile::setHeightmapImage(QImage const& baseimage, float multiplier, int mode, bool tiledEdges) // image +void MapTile::setHeightmapImage(QImage const& baseimage, float min_height, float max_height, int mode, bool tiledEdges) // image { - auto image = baseimage.convertToFormat(QImage::Format_Grayscale16); + auto image = baseimage.convertToFormat(QImage::Format_RGBA64); + + float const height_range = (max_height - min_height); unsigned const LONG{9}, SHORT{8}, SUM{LONG + SHORT}, DSUM{SUM * 2}; for (int k = 0; k < 16; ++k) @@ -1268,22 +1272,27 @@ void MapTile::setHeightmapImage(QImage const& baseimage, float multiplier, int m case 16: case 32: { + float const ratio = qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f; // 0.0 - 1.0 + float const new_height = (height_range * ratio) + min_height; + + float test_newheight = (ratio + min_height) * (height_range); + switch (mode) { case 0: // Set - heightmap[idx].y = qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + heightmap[idx].y = new_height; break; case 1: // Add - heightmap[idx].y += qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + heightmap[idx].y += new_height; break; case 2: // Subtract - heightmap[idx].y -= qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + heightmap[idx].y -= new_height; break; case 3: // Multiply - heightmap[idx].y *= qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + heightmap[idx].y *= new_height; break; } @@ -1292,22 +1301,25 @@ void MapTile::setHeightmapImage(QImage const& baseimage, float multiplier, int m case 64: { + double const ratio = image.pixelColor((k * 16) + x, (l * 16) + y).redF(); // 0.0 - 1.0 + float new_height = height_range * ratio + min_height; + switch (mode) { case 0: // Set - heightmap[idx].y = image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier; + heightmap[idx].y = new_height; break; case 1: // Add - heightmap[idx].y += image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier;; + heightmap[idx].y += new_height; break; case 2: // Subtract - heightmap[idx].y -= image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier;; + heightmap[idx].y -= new_height; break; case 3: // Multiply - heightmap[idx].y *= image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier;; + heightmap[idx].y *= new_height; break; } @@ -1384,7 +1396,7 @@ void MapTile::setHeightmapImage(QImage const& baseimage, float multiplier, int m void MapTile::setAlphaImage(QImage const& baseimage, unsigned layer) { - auto image = baseimage.convertToFormat(QImage::Format_Grayscale8); + auto image = baseimage.convertToFormat(QImage::Format_RGBA8888); for (int k = 0; k < 16; ++k) { diff --git a/src/noggit/MapTile.h b/src/noggit/MapTile.h index 56cd0844..7610d3ce 100755 --- a/src/noggit/MapTile.h +++ b/src/noggit/MapTile.h @@ -142,7 +142,8 @@ public: QImage getAlphamapImage(std::string const& filename); QImage getVertexColorsImage(); QImage getNormalmapImage(); - void setHeightmapImage(QImage const& baseimage, float multiplier, int mode, bool tiledEdges); + void setHeightmapImage(QImage const& baseimage, float min_height, float max_height, int mode, bool tiledEdges); + void setWatermapImage(QImage const& baseimage, float multiplier, int mode, bool tiledEdges); void setAlphaImage(QImage const& image, unsigned layer); void setVertexColorImage(QImage const& image, int mode, bool tiledEdges); void registerChunkUpdate(unsigned flags) { _chunk_update_flags |= flags; }; diff --git a/src/noggit/MapView.cpp b/src/noggit/MapView.cpp index 05e66856..5728c5d4 100755 --- a/src/noggit/MapView.cpp +++ b/src/noggit/MapView.cpp @@ -1421,22 +1421,41 @@ void MapView::setupAssistMenu() } ); + // vertices can support up to 32bit but other things break at 16bit like WDL and MFBO + // DB/ZoneLight appears to be using -64000 and 64000 + // DB/DungeonMapChunk seems to use -10000 for lower default. + int constexpr MIN_HEIGHT = std::numeric_limits::min(); // -32768 + int constexpr MAX_HEIGHT = std::numeric_limits::max(); // 32768 + + int constexpr DEFAULT_MIN_HEIGHT = -2000; // outland goes to -1200 + int constexpr DEFAULT_MAX_HEIGHT = 3000; // hyjal goes to 2000 + QDialog* heightmap_export_params = new QDialog(this); heightmap_export_params->setWindowFlags(Qt::Popup); heightmap_export_params->setWindowTitle("Heightmap Exporter"); QVBoxLayout* heightmap_export_params_layout = new QVBoxLayout(heightmap_export_params); - heightmap_export_params_layout->addWidget(new QLabel("Min:", heightmap_export_params)); + heightmap_export_params_layout->addWidget(new QLabel("Import with the same values \nto keep the same coordinates.", + heightmap_export_params)); + + heightmap_export_params_layout->addWidget(new QLabel("Min Height:", heightmap_export_params)); QDoubleSpinBox* heightmap_export_min = new QDoubleSpinBox(heightmap_export_params); - heightmap_export_min->setRange(-10000000, 10000000); + heightmap_export_min->setRange(MIN_HEIGHT, MAX_HEIGHT); + heightmap_export_min->setValue(DEFAULT_MIN_HEIGHT); heightmap_export_params_layout->addWidget(heightmap_export_min); - heightmap_export_params_layout->addWidget(new QLabel("Max:", heightmap_export_params)); + heightmap_export_params_layout->addWidget(new QLabel("Max Height:", heightmap_export_params)); QDoubleSpinBox* heightmap_export_max = new QDoubleSpinBox(heightmap_export_params); - heightmap_export_max->setRange(-10000000, 10000000); - heightmap_export_max->setValue(100.0); + heightmap_export_max->setRange(MIN_HEIGHT, MAX_HEIGHT); + heightmap_export_max->setValue(DEFAULT_MAX_HEIGHT); heightmap_export_params_layout->addWidget(heightmap_export_max); + std::string const autoheights_tooltip_str = "Sets fields to this tile's min and max heights\nDefaults : Min: " + + std::to_string(DEFAULT_MIN_HEIGHT) + ", Max: " + std::to_string(DEFAULT_MAX_HEIGHT); + QPushButton* heightmap_export_params_auto_height = new QPushButton("Auto Heights", heightmap_export_params); + heightmap_export_params_auto_height->setToolTip(autoheights_tooltip_str.c_str()); + heightmap_export_params_layout->addWidget(heightmap_export_params_auto_height); + QPushButton* heightmap_export_okay = new QPushButton("Okay", heightmap_export_params); heightmap_export_params_layout->addWidget(heightmap_export_okay); @@ -1456,6 +1475,20 @@ void MapView::setupAssistMenu() }); + connect(heightmap_export_params_auto_height, &QPushButton::clicked + , [=]() + { + MapTile* tile = _world->mapIndex.getTile(_camera.position); + if (tile) + { + QSignalBlocker const blocker_min(heightmap_export_min); + QSignalBlocker const blocker_max(heightmap_export_max); + + heightmap_export_min->setValue(tile->getMinHeight()); + heightmap_export_max->setValue(tile->getMaxHeight()); + } + }); + connect(heightmap_export_okay, &QPushButton::clicked ,[=]() { @@ -1499,6 +1532,8 @@ void MapView::setupAssistMenu() auto cur_adt_import_menu(assist_menu->addMenu("Import")); + // alphamaps import + auto const alphamap_image_format = "Required Image format :\n1024x1024 and 8bit color channel."; QDialog* adt_import_params = new QDialog(this); adt_import_params->setWindowFlags(Qt::Popup); @@ -1513,6 +1548,11 @@ void MapView::setupAssistMenu() QPushButton* adt_import_params_okay = new QPushButton("Okay", adt_import_params); adt_import_params_layout->addWidget(adt_import_params_okay); + auto const alphamap_file_info_tooltip = "\nThe image file must be placed in the map's directory in the project" + " folder with the following naming : MAPNAME_XX_YY_layer1.png (or layer2...)." + "\nFor example \"C:/noggitproject/world/maps/MAPNAME/MAPNAME_29_53_layer2.png\""; + adt_import_params_okay->setToolTip(alphamap_file_info_tooltip); + connect(adt_import_params_okay, &QPushButton::clicked ,[=]() { @@ -1571,15 +1611,42 @@ void MapView::setupAssistMenu() } ); + auto const heightmap_image_format = "Required Image format :\n257x257 or 256x256(tiled edges)\nand 16bit per color channel."; + + auto const heightmap_file_info_tooltip = "Requires a .png image of 257x257, or 256x256 in Tiled Edges mode.(Otherwise it will be stretched)" + "\nThe image file must be placed in the map's directory in the project folder with the following naming : MAPNAME_XX_YY_height.png." + "\nFor example \"C:/noggitproject/world/maps/MAPNAME/MAPNAME_29_53_height.png\""; + + auto const tiled_edges_tooltip_str = "Tiled edge uses a 256x256 image instead 257." + "\nTiled image imports encroach on edge vertices on neighboring tiles to avoid duplicate edges. "; + + /*auto const multiplier_tooltip_str = "Multiplies pixel values by this to obtain the final position." + "\n For example a pixel grayscale of 40%(0.4%) with a multiplier of 100 means this vertex's height will be 0.4*100 = 40."; +*/ + + // heightmaps QDialog* adt_import_height_params = new QDialog(this); adt_import_height_params->setWindowFlags(Qt::Popup); - adt_import_height_params->setWindowTitle("Alphamap Importer"); + adt_import_height_params->setWindowTitle("Heightmap Importer"); QVBoxLayout* adt_import_height_params_layout = new QVBoxLayout(adt_import_height_params); - adt_import_height_params_layout->addWidget(new QLabel("Multiplier:", adt_import_height_params)); - QDoubleSpinBox* adt_import_height_params_multiplier = new QDoubleSpinBox(adt_import_height_params); - adt_import_height_params_multiplier->setRange(0, 100000000); - adt_import_height_params_layout->addWidget(adt_import_height_params_multiplier); + adt_import_height_params_layout->addWidget(new QLabel(heightmap_image_format, adt_import_height_params)); + + adt_import_height_params_layout->addWidget(new QLabel("Min Height:", adt_import_height_params)); + QDoubleSpinBox* heightmap_import_min = new QDoubleSpinBox(adt_import_height_params); + heightmap_import_min->setRange(MIN_HEIGHT, MAX_HEIGHT); + heightmap_import_min->setValue(DEFAULT_MIN_HEIGHT); + adt_import_height_params_layout->addWidget(heightmap_import_min); + + adt_import_height_params_layout->addWidget(new QLabel("Max Height:", adt_import_height_params)); + QDoubleSpinBox* heightmap_import_max = new QDoubleSpinBox(adt_import_height_params); + heightmap_import_max->setRange(MIN_HEIGHT, MAX_HEIGHT); + heightmap_import_max->setValue(DEFAULT_MAX_HEIGHT); + adt_import_height_params_layout->addWidget(heightmap_import_max); + + QPushButton* adt_import_height_params_auto_height = new QPushButton("Auto Heights", adt_import_height_params); + adt_import_height_params_auto_height->setToolTip(autoheights_tooltip_str.c_str()); + adt_import_height_params_layout->addWidget(adt_import_height_params_auto_height); adt_import_height_params_layout->addWidget(new QLabel("Mode:", adt_import_height_params)); QComboBox* adt_import_height_params_mode = new QComboBox(adt_import_height_params); @@ -1587,10 +1654,23 @@ void MapView::setupAssistMenu() adt_import_height_params_mode->addItems({"Set", "Add", "Subtract", "Multiply" }); QCheckBox* adt_import_height_tiled_edges = new QCheckBox("Tiled Edges", adt_import_height_params); + adt_import_height_tiled_edges->setToolTip(tiled_edges_tooltip_str); adt_import_height_params_layout->addWidget(adt_import_height_tiled_edges); QPushButton* adt_import_height_params_okay = new QPushButton("Okay", adt_import_height_params); adt_import_height_params_layout->addWidget(adt_import_height_params_okay); + adt_import_height_params_okay->setToolTip(heightmap_file_info_tooltip); + + connect(adt_import_height_params_auto_height, &QPushButton::clicked + , [=]() + { + MapTile* tile = _world->mapIndex.getTile(_camera.position); + if (tile) + { + heightmap_import_min->setValue(tile->getMinHeight()); + heightmap_import_max->setValue(tile->getMaxHeight()); + } + }); connect(adt_import_height_params_okay, &QPushButton::clicked ,[=]() @@ -1622,7 +1702,7 @@ void MapView::setupAssistMenu() img.load(filepath, "PNG"); NOGGIT_ACTION_MGR->beginAction(this, Noggit::ActionFlags::eCHUNKS_TERRAIN); - _world->importADTHeightmap(_camera.position, img, adt_import_height_params_multiplier->value(), + _world->importADTHeightmap(_camera.position, img, heightmap_import_min->value(), heightmap_import_max->value(), adt_import_height_params_mode->currentIndex(), adt_import_height_tiled_edges->isChecked()); NOGGIT_ACTION_MGR->endAction(); } @@ -1639,16 +1719,84 @@ void MapView::setupAssistMenu() OpenGL::context::scoped_setter const _(::gl, context()); NOGGIT_ACTION_MGR->beginAction(this, Noggit::ActionFlags::eCHUNKS_TERRAIN); - _world->importADTHeightmap(_camera.position, adt_import_height_params_multiplier->value(), + _world->importADTHeightmap(_camera.position, heightmap_import_min->value(), heightmap_import_max->value(), adt_import_height_params_mode->currentIndex(), adt_import_height_tiled_edges->isChecked()); NOGGIT_ACTION_MGR->endAction(); } } ); + // Watermap + QDialog* adt_import_water_params = new QDialog(this); + adt_import_water_params->setWindowFlags(Qt::Popup); + adt_import_water_params->setWindowTitle("Watermap Importer"); + QVBoxLayout* adt_import_water_params_layout = new QVBoxLayout(adt_import_water_params); + + // MIN MAX + adt_import_water_params_layout->addWidget(new QLabel("Min Height:", adt_import_water_params)); + QDoubleSpinBox* watermap_import_min = new QDoubleSpinBox(adt_import_water_params); + watermap_import_min->setRange(MIN_HEIGHT, MAX_HEIGHT); + watermap_import_min->setValue(MIN_HEIGHT); + adt_import_water_params_layout->addWidget(watermap_import_min); + + adt_import_water_params_layout->addWidget(new QLabel("Max Height:", adt_import_water_params)); + QDoubleSpinBox* watermap_import_max = new QDoubleSpinBox(adt_import_water_params); + watermap_import_max->setRange(MIN_HEIGHT, MAX_HEIGHT); + watermap_import_max->setValue(MAX_HEIGHT); + adt_import_water_params_layout->addWidget(watermap_import_max); + + adt_import_water_params_layout->addWidget(new QLabel("Mode:", adt_import_water_params)); + QComboBox* adt_import_water_params_mode = new QComboBox(adt_import_water_params); + adt_import_water_params_layout->addWidget(adt_import_water_params_mode); + adt_import_water_params_mode->addItems({ "Set", "Add", "Subtract", "Multiply" }); + + QCheckBox* adt_import_water_tiled_edges = new QCheckBox("Tiled Edges", adt_import_water_params); + adt_import_water_params_layout->addWidget(adt_import_water_tiled_edges); + + QPushButton* adt_import_water_params_okay = new QPushButton("Okay", adt_import_water_params); + adt_import_water_params_layout->addWidget(adt_import_water_params_okay); + + connect(adt_import_water_params_okay, &QPushButton::clicked + , [=]() + { + adt_import_water_params->accept(); + + }); + + ADD_ACTION_NS(cur_adt_import_menu + , "Import watermap (file)" + , [=] + { + if (adt_import_water_params->exec() == QDialog::Accepted) + { + makeCurrent(); + OpenGL::context::scoped_setter const _(::gl, context()); + + QString filepath = QFileDialog::getOpenFileName( + this, + tr("Open watermap (257x257)"), + "", + "PNG file (*.png);;" + ); + + if (!QFileInfo::exists(filepath)) + return; + + QImage img; + img.load(filepath, "PNG"); + + NOGGIT_ACTION_MGR->beginAction(this, Noggit::ActionFlags::eCHUNKS_WATER); + _world->importADTWatermap(_camera.position, img, watermap_import_min->value(), watermap_import_max->value(), + adt_import_water_params_mode->currentIndex(), adt_import_water_tiled_edges->isChecked()); + NOGGIT_ACTION_MGR->endAction(); + } + } + ); + + // Vertex Colors QDialog* adt_import_vcol_params = new QDialog(this); adt_import_vcol_params->setWindowFlags(Qt::Popup); - adt_import_vcol_params->setWindowTitle("Alphamap Importer"); + adt_import_vcol_params->setWindowTitle("Vertex Color Map Importer"); QVBoxLayout* adt_import_vcol_params_layout = new QVBoxLayout(adt_import_vcol_params); adt_import_vcol_params_layout->addWidget(new QLabel("Mode:", adt_import_vcol_params)); @@ -1864,7 +2012,7 @@ void MapView::setupAssistMenu() makeCurrent(); OpenGL::context::scoped_setter const _(::gl, context()); NOGGIT_ACTION_MGR->beginAction(this, Noggit::ActionFlags::eCHUNKS_TERRAIN); - _world->importAllADTsHeightmaps(adt_import_height_params_multiplier->value(), adt_import_height_params_mode->currentIndex(), adt_import_height_tiled_edges->isChecked()); + _world->importAllADTsHeightmaps(heightmap_import_min->value(), heightmap_import_max->value(), adt_import_height_params_mode->currentIndex(), adt_import_height_tiled_edges->isChecked()); NOGGIT_ACTION_MGR->endAction(); ) diff --git a/src/noggit/TileWater.cpp b/src/noggit/TileWater.cpp index af7ea8ee..29abc6a1 100755 --- a/src/noggit/TileWater.cpp +++ b/src/noggit/TileWater.cpp @@ -159,3 +159,187 @@ bool TileWater::isVisible(const math::frustum& frustum) const { return frustum.intersects(_extents[1], _extents[0]); } + +void TileWater::setWatermapImage(QImage const& baseimage, float min_height, float max_height, int mode, bool tiledEdges) // image +{ + auto image = baseimage.convertToFormat(QImage::Format_RGBA64); + + auto color_table = image.colorTable().toStdVector(); + + float height_range = max_height - min_height; + + unsigned const LONG{ 9 }, SHORT{ 8 }, SUM{ LONG + SHORT }, DSUM{ SUM * 2 }; + for (int k = 0; k < 16; ++k) + { + for (int l = 0; l < 16; ++l) + { + // MapChunk* chunk = getChunk(k, l); + ChunkWater* water_chunk = chunks[k][l].get(); + + // chunk->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + + auto map_chunk = tile->getChunk(k, l); + glm::vec3* heightmap = map_chunk->getHeightmap(); + + for (unsigned y = 0; y < SUM; ++y) + for (unsigned x = 0; x < SUM; ++x) + { + unsigned const plain{ y * SUM + x }; + bool const is_virtual{ static_cast(plain % 2) }; + + if (is_virtual) + continue; + + bool const erp = plain % DSUM / SUM; + unsigned const idx{ (plain - (is_virtual ? (erp ? SUM : 1) : 0)) / 2 }; + + if (tiledEdges && ((y == 16 && l == 15) || (x == 16 && k == 15))) + { + continue; + } + + int debug_depth = image.depth(); + + // auto blackcolor2 = qGray(Qt::black); // 0 + // auto pixcolorrgb = image.pixel((k * 16) + x, (l * 16) + y); + auto pixcolorgray = qGray(image.pixel((k * 16) + x, (l * 16) + y)); + + // 1 : Get terrain vertex height at same xy coord as not-black value in the rivers image + // ignore black pixels + if (pixcolorgray == qGray(Qt::black)) + continue; + + float const ratio = pixcolorgray / 255.0f; // 0.0 - 1.0 + float const new_height = (height_range * ratio) + min_height; + + // 2 : get terrain vertex's position + float water_height = heightmap[idx].y; + + // 3 : Increase water vertex height by river pixel's grey value + + // just additive mode for now + water_height += new_height; + + continue; + // TODO : modes + + + // switch (image.depth()) + // { + // case 8: + // case 16: + // case 32: + // { + // switch (mode) + // { + // case 0: // Set + // heightmap[idx].y = qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + // break; + // + // case 1: // Add + // heightmap[idx].y += qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + // break; + // + // case 2: // Subtract + // heightmap[idx].y -= qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + // break; + // + // case 3: // Multiply + // heightmap[idx].y *= qGray(image.pixel((k * 16) + x, (l * 16) + y)) / 255.0f * multiplier; + // break; + // } + // + // break; + // } + // + // case 64: + // { + // switch (mode) + // { + // case 0: // Set + // heightmap[idx].y = image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier; + // break; + // + // case 1: // Add + // heightmap[idx].y += image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier;; + // break; + // + // case 2: // Subtract + // heightmap[idx].y -= image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier;; + // break; + // + // case 3: // Multiply + // heightmap[idx].y *= image.pixelColor((k * 16) + x, (l * 16) + y).redF() * multiplier;; + // break; + // } + // + // break; + // } + // } + + } + + // registerChunkUpdate(ChunkUpdateFlags::VERTEX); + } + } + + // if (tiledEdges) // resize + fit + // { + // if (index.z > 0) + // { + // getWorld()->for_tile_at_force(TileIndex{ index.x, index.z - 1 } + // , [&](MapTile* tile) + // { + // for (int chunk_x = 0; chunk_x < 16; ++chunk_x) + // { + // MapChunk* targetChunk = tile->getChunk(chunk_x, 15); + // MapChunk* sourceChunk = this->getChunk(chunk_x, 0); + // targetChunk->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + // for (int vert_x = 0; vert_x < 9; ++vert_x) + // { + // int target_vert = 136 + vert_x; + // int source_vert = vert_x; + // targetChunk->getHeightmap()[target_vert].y = sourceChunk->getHeightmap()[source_vert].y; + // } + // } + // tile->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + // } + // ); + // } + // + // if (index.x > 0) + // { + // getWorld()->for_tile_at_force(TileIndex{ index.x - 1, index.z } + // , [&](MapTile* tile) + // { + // for (int chunk_y = 0; chunk_y < 16; ++chunk_y) + // { + // MapChunk* targetChunk = tile->getChunk(15, chunk_y); + // MapChunk* sourceChunk = this->getChunk(0, chunk_y); + // targetChunk->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + // for (int vert_y = 0; vert_y < 9; ++vert_y) + // { + // int target_vert = vert_y * 17 + 8; + // int source_vert = vert_y * 17; + // targetChunk->getHeightmap()[target_vert].y = sourceChunk->getHeightmap()[source_vert].y; + // } + // } + // tile->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + // } + // ); + // } + // + // if (index.x > 0 && index.z > 0) + // { + // getWorld()->for_tile_at_force(TileIndex{ index.x - 1, index.z - 1 } + // , [&](MapTile* tile) + // { + // MapChunk* targetChunk = tile->getChunk(15, 15); + // targetChunk->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + // tile->getChunk(15, 15)->getHeightmap()[144].y = this->getChunk(0, 0)->getHeightmap()[0].y; + // tile->registerChunkUpdate(ChunkUpdateFlags::VERTEX); + // } + // ); + // } + // } +} diff --git a/src/noggit/TileWater.hpp b/src/noggit/TileWater.hpp index 5ab2ff83..e95b5651 100755 --- a/src/noggit/TileWater.hpp +++ b/src/noggit/TileWater.hpp @@ -65,6 +65,8 @@ public: [[nodiscard]] bool isVisible(const math::frustum& frustum) const; + void setWatermapImage(QImage const& baseimage, float min_height, float max_height, int mode, bool tiledEdges); + void tagExtents(bool state) { _extents_changed = state; }; void tagUpdate() { _renderer.tagUpdate(); }; diff --git a/src/noggit/World.cpp b/src/noggit/World.cpp index fe1edd00..8dbcc8f9 100755 --- a/src/noggit/World.cpp +++ b/src/noggit/World.cpp @@ -2257,7 +2257,7 @@ void World::importADTAlphamap(glm::vec3 const& pos) ); } -void World::importADTHeightmap(glm::vec3 const& pos, QImage const& image, float multiplier, unsigned mode, bool tiledEdges) +void World::importADTHeightmap(glm::vec3 const& pos, QImage const& image, float min_height, float max_height, unsigned mode, bool tiledEdges) { ZoneScoped; int desired_dimensions = tiledEdges ? 256 : 257; @@ -2273,7 +2273,7 @@ void World::importADTHeightmap(glm::vec3 const& pos, QImage const& image, float for_tile_at ( pos , [&] (MapTile* tile) { - tile->setHeightmapImage(scaled, multiplier, mode, tiledEdges); + tile->setHeightmapImage(scaled, min_height, max_height, mode, tiledEdges); } ); @@ -2283,13 +2283,13 @@ void World::importADTHeightmap(glm::vec3 const& pos, QImage const& image, float for_tile_at ( pos , [&] (MapTile* tile) { - tile->setHeightmapImage(image, multiplier, mode, tiledEdges); + tile->setHeightmapImage(image, min_height, max_height, mode, tiledEdges); } ); } } -void World::importADTHeightmap(glm::vec3 const& pos, float multiplier, unsigned mode, bool tiledEdges) +void World::importADTHeightmap(glm::vec3 const& pos, float min_height, float max_height, unsigned mode, bool tiledEdges) { ZoneScoped; for_tile_at ( pos @@ -2306,8 +2306,17 @@ void World::importADTHeightmap(glm::vec3 const& pos, float multiplier, unsigned + "_" + std::to_string(tile->index.x).c_str() + "_" + std::to_string(tile->index.z).c_str() + "_height" + ".png"; - if(!QFileInfo::exists(filename)) + if (!QFileInfo::exists(filename)) + { + QMessageBox::warning + (nullptr + , "File not found" + , "File not found: " + filename + , QMessageBox::Ok + ); return; + } + for_all_chunks_on_tile(pos, [](MapChunk* chunk) { @@ -2321,12 +2330,44 @@ void World::importADTHeightmap(glm::vec3 const& pos, float multiplier, unsigned if (img.width() != desiredSize || img.height() != desiredSize) img = img.scaled(static_cast(desiredSize), static_cast(desiredSize), Qt::AspectRatioMode::IgnoreAspectRatio); - tile->setHeightmapImage(img, multiplier, mode, tiledEdges); + tile->setHeightmapImage(img, min_height, max_height, mode, tiledEdges); } ); } +void World::importADTWatermap(glm::vec3 const& pos, QImage const& image, float min_height, float max_height, unsigned mode, bool tiledEdges) +{ + ZoneScoped; + int desired_dimensions = tiledEdges ? 256 : 257; + for_all_chunks_on_tile(pos, [](MapChunk* chunk) + { + NOGGIT_CUR_ACTION->registerChunkLiquidChange(chunk); + }); + + if (image.width() != desired_dimensions || image.height() != desired_dimensions) + { + QImage scaled = image.scaled(desired_dimensions, desired_dimensions, Qt::AspectRatioMode::IgnoreAspectRatio); + + for_tile_at(pos + , [&](MapTile* tile) + { + tile->Water.setWatermapImage(scaled, min_height, max_height, mode, tiledEdges); + } + ); + + } + else + { + for_tile_at(pos + , [&](MapTile* tile) + { + tile->Water.setWatermapImage(image, min_height, max_height, mode, tiledEdges); + } + ); + } +} + void World::importADTVertexColorMap(glm::vec3 const& pos, int mode, bool tiledEdges) { ZoneScoped; @@ -3250,7 +3291,7 @@ void World::importAllADTsAlphamaps() } } -void World::importAllADTsHeightmaps(float multiplier, unsigned int mode, bool tiledEdges) +void World::importAllADTsHeightmaps(float min_height, float max_height, unsigned int mode, bool tiledEdges) { ZoneScoped; QString path = QString(Noggit::Project::CurrentProject::get()->ProjectPath.c_str()); @@ -3286,11 +3327,11 @@ void World::importAllADTsHeightmaps(float multiplier, unsigned int mode, bool ti if (img.width() != desiredSize || img.height() != desiredSize) { QImage scaled = img.scaled(257, 257, Qt::IgnoreAspectRatio); - mTile->setHeightmapImage(scaled, multiplier, mode, tiledEdges); + mTile->setHeightmapImage(scaled, min_height, max_height, mode, tiledEdges); } else { - mTile->setHeightmapImage(img, multiplier, mode, tiledEdges); + mTile->setHeightmapImage(img, min_height, max_height, mode, tiledEdges); } mTile->saveTile(this); diff --git a/src/noggit/World.h b/src/noggit/World.h index e01685ea..a5c3cc65 100755 --- a/src/noggit/World.h +++ b/src/noggit/World.h @@ -264,13 +264,14 @@ public: void importADTAlphamap(glm::vec3 const& pos, QImage const& image, unsigned layer); void importADTAlphamap(glm::vec3 const& pos); - void importADTHeightmap(glm::vec3 const& pos, QImage const& image, float multiplier, unsigned mode, bool tiledEdges); - void importADTHeightmap(glm::vec3 const& pos, float multiplier, unsigned mode, bool tiledEdges); + void importADTHeightmap(glm::vec3 const& pos, QImage const& image, float min_height, float max_height, unsigned mode, bool tiledEdges); + void importADTHeightmap(glm::vec3 const& pos, float min_height, float max_height, unsigned mode, bool tiledEdges); + void importADTWatermap(glm::vec3 const& pos, QImage const& image, float min_height, float max_height, unsigned mode, bool tiledEdges); void importADTVertexColorMap(glm::vec3 const& pos, int mode, bool tiledEdges); void importADTVertexColorMap(glm::vec3 const& pos, QImage const& image, int mode, bool tiledEdges); void importAllADTsAlphamaps(); - void importAllADTsHeightmaps(float multiplier, unsigned mode, bool tiledEdges); + void importAllADTsHeightmaps(float min_height, float max_height, unsigned mode, bool tiledEdges); void importAllADTVertexColorMaps(unsigned mode, bool tiledEdges); void ensureAllTilesetsADT(glm::vec3 const& pos); diff --git a/src/noggit/ui/tools/NodeEditor/Nodes/World/Tile/TileSetHeightmapImage.cpp b/src/noggit/ui/tools/NodeEditor/Nodes/World/Tile/TileSetHeightmapImage.cpp index 67ac1ad6..ba72666f 100755 --- a/src/noggit/ui/tools/NodeEditor/Nodes/World/Tile/TileSetHeightmapImage.cpp +++ b/src/noggit/ui/tools/NodeEditor/Nodes/World/Tile/TileSetHeightmapImage.cpp @@ -59,7 +59,8 @@ void TileSetHeightmapImageNode::compute() return; } - tile->setHeightmapImage(*image_to_use, static_cast(multiplier), _operation->currentIndex(), false); + // TODO change to min/max instead of multiplier + tile->setHeightmapImage(*image_to_use, -32768.f, 32768.f, _operation->currentIndex(), false); _out_ports[0].out_value = std::make_shared(true); _node->onDataUpdated(0);