implement loading and rendering global wmo maps

This commit is contained in:
T1ti
2023-07-18 06:18:56 +02:00
parent 6cf6c95cf5
commit 5529aa4954
11 changed files with 124 additions and 21 deletions

View File

@@ -2811,7 +2811,11 @@ void MapView::move_camera_with_auto_height (glm::vec3 const& pos)
makeCurrent();
OpenGL::context::scoped_setter const _ (::gl, context());
_world->mapIndex.loadTile(pos)->wait_until_loaded();
TileIndex tile_index = TileIndex(pos);
if (_world->mapIndex.hasTile(tile_index))
{
_world->mapIndex.loadTile(pos)->wait_until_loaded();
}
_camera.position = pos;
_camera.position.y = 0.0f;

View File

@@ -64,7 +64,7 @@ bool World::IsEditableWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow
// Not using the libWDT here doubles performance. You might want to look at your lib again and improve it.
const int lFlags = *(reinterpret_cast<const int*>(lPointer + 8 + 4 + 8));
if (lFlags & 1)
return false;
return true; // filter them later
const int * lData = reinterpret_cast<const int*>(lPointer + 8 + 4 + 8 + 0x20 + 8);
for (int i = 0; i < 8192; i += 2)
@@ -76,14 +76,33 @@ bool World::IsEditableWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow
return false;
}
bool World::IsWMOWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow& record)
{
ZoneScoped;
std::string lMapName = record.Columns["Directory"].Value;
std::stringstream ssfilename;
ssfilename << "World\\Maps\\" << lMapName << "\\" << lMapName << ".wdt";
BlizzardArchive::ClientFile mf(ssfilename.str(), Noggit::Application::NoggitApplication::instance()->clientData());
const char* lPointer = reinterpret_cast<const char*>(mf.getPointer());
const int lFlags = *(reinterpret_cast<const int*>(lPointer + 8 + 4 + 8));
if (lFlags & 1)
return true;
return false;
}
World::World(const std::string& name, int map_id, Noggit::NoggitRenderContext context, bool create_empty)
: _renderer(Noggit::Rendering::WorldRender(this))
, _model_instance_storage(this)
, _tile_update_queue(this)
, mapIndex(name, map_id, this, context, create_empty)
, horizon(name, &mapIndex)
, mWmoFilename("")
, mWmoEntry(ENTRY_MODF())
, mWmoFilename(mapIndex.globalWMOName)
, mWmoEntry(mapIndex.wmoEntry)
, animtime(0)
, time(1450)
, basename(name)

View File

@@ -312,6 +312,8 @@ public:
static bool IsEditableWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow& record);
static bool IsWMOWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow& record);
void clearHeight(glm::vec3 const& pos);
void clearAllModelsOnADT(TileIndex const& tile);

View File

@@ -140,7 +140,7 @@ MapIndex::MapIndex (const std::string &pBasename, int map_id, World* world,
//! \bug MODF reads wrong. The assertion fails every time. Somehow, it keeps being MWMO. Or are there two blocks?
//! \nofuckingbug on eof read returns just without doing sth to the var and some wdts have a MWMO without having a MODF so only checking for eof above is not enough
mHasAGlobalWMO = false;
// mHasAGlobalWMO = false;
// - MWMO ----------------------------------------------

View File

@@ -273,10 +273,9 @@ private:
public:
int const _map_id;
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> _minimap_md5translate;
private:
std::string globalWMOName;
ENTRY_MODF wmoEntry;
private:
int _last_unload_time;
int _unload_interval;
int _unload_dist;
@@ -295,7 +294,6 @@ private:
uint32_t highestGUID;
ENTRY_MODF wmoEntry;
MPHD mphd;
// Holding all MapTiles there can be in a World.

View File

@@ -464,6 +464,19 @@ void WorldRender::draw (glm::mat4x4 const& model_view
wmo_program.uniform("camera", glm::vec3(camera_pos.x, camera_pos.y, camera_pos.z));
// make this check per WMO or global WMO with tiles may not work
bool disable_cull = false;
if (_world->mapIndex.hasAGlobalWMO() && !wmos_to_draw.size())
{
auto global_wmo = _world->_model_instance_storage.get_wmo_instance(_world->mWmoEntry.uniqueID);
if (global_wmo.has_value())
{
wmos_to_draw.push_back(global_wmo.value());
disable_cull = true;
}
}
for (auto& instance: wmos_to_draw)
{
@@ -526,7 +539,7 @@ void WorldRender::draw (glm::mat4x4 const& model_view
, _world->animtime
, _skies->hasSkies()
, display
, false
, disable_cull
, draw_wmo_exterior
);

View File

@@ -248,7 +248,33 @@ namespace Noggit
painter.drawLine (camera_vector);
}
}
if (_world->mapIndex.hasAGlobalWMO())
{
painter.setPen(QColor::fromRgbF(1.0f, 0.0f, 0.0f, 1.f));
auto extents = _world->mWmoEntry.extents;
// WMOInstance inst(_world->mWmoFilename, &_world->mWmoEntry, _world->_context);
float pos = tile_size * 64 / 2; // TODO : convert wmo pos
float min_point_x = pos + (extents[0][0] / TILESIZE * tile_size); // extents[min][x]
float min_point_y = pos + (extents[0][1] / TILESIZE * tile_size); // extents[min][y]
float max_point_x = pos + (extents[1][0] / TILESIZE * tile_size);
float max_point_y = pos + (extents[1][1] / TILESIZE * tile_size);
// tile_size = 14 | max size = 896
float width = max_point_x - min_point_x;
float height = max_point_y - min_point_y;
painter.drawRect(QRectF(min_point_x
, min_point_y
, width // width
, height // height
)
);
}
}
else
{
//! \todo Draw something so user realizes this will become the minimap.
@@ -283,7 +309,7 @@ namespace Noggit
QPoint tile = locateTile(event);
if (!world()->mapIndex.hasTile (TileIndex (tile.x(), tile.y())))
if (!world()->mapIndex.hasTile (TileIndex (tile.x(), tile.y())) && !_world->mapIndex.hasAGlobalWMO())
{
event->ignore();
return;

View File

@@ -173,6 +173,28 @@ namespace Noggit::Ui::Windows
bool from_bookmark
)
{
if (_world->mapIndex.hasAGlobalWMO())
{
// enter at mdoel's position
// pos = glm::vec3(_world->mWmoEntry[0], _world->mWmoEntry.pos[1], _world->mWmoEntry.pos[2]);
// better, enter at model's max extent, facing toward min extent
auto min_extent = glm::vec3(_world->mWmoEntry.extents[0][0], _world->mWmoEntry.extents[0][1], _world->mWmoEntry.extents[0][2]);
auto max_extent = glm::vec3(_world->mWmoEntry.extents[1][0], _world->mWmoEntry.extents[1][1] * 2, _world->mWmoEntry.extents[1][2]);
float dx = min_extent.x - max_extent.x;
float dy = min_extent.z - max_extent.z; // flipping z and y works better for some reason
float dz = min_extent.y - max_extent.y;
pos = max_extent;
camera_yaw = math::degrees(math::radians(std::atan2(dx, dy)));
float distance = std::sqrt(dx * dx + dy * dy + dz * dz);
camera_pitch = math::degrees(math::radians(std::asin(dz / distance)));
}
_map_creation_wizard->destroyFakeWorld();
_map_view = (new MapView(camera_yaw, camera_pitch, pos, this, _project, std::move(_world), uid_fix, from_bookmark));
connect(_map_view, &MapView::uid_fix_failed, [this]()
@@ -187,7 +209,7 @@ namespace Noggit::Ui::Windows
}
void NoggitWindow::applyFilterSearch(const QString &name, int type, int expansion)
void NoggitWindow::applyFilterSearch(const QString &name, int type, int expansion, bool wmo_maps)
{
for (int i = 0; i < _continents_table->count(); ++i)
{
@@ -215,6 +237,11 @@ namespace Noggit::Ui::Windows
{
item_widget->setHidden(true);
}
if (!(widget->wmo_map() == wmo_maps))
{
item_widget->setHidden(true);
}
}
}
@@ -294,26 +321,33 @@ namespace Noggit::Ui::Windows
_combo_exp_search->addItem(QIcon(":/icon-shadow"), tr("Shadowlands"));
_combo_exp_search->setCurrentIndex(0);
QObject::connect(_line_edit_search, QOverload<const QString&>::of(&QLineEdit::textChanged), [this, _combo_search, _combo_exp_search](const QString &name)
QCheckBox* _wmo_maps_search = new QCheckBox("Display WMO maps (No terrain)", this);
QObject::connect(_line_edit_search, QOverload<const QString&>::of(&QLineEdit::textChanged), [this, _combo_search, _combo_exp_search, _wmo_maps_search](const QString &name)
{
applyFilterSearch(name, _combo_search->currentIndex(), _combo_exp_search->currentIndex());
applyFilterSearch(name, _combo_search->currentIndex(), _combo_exp_search->currentIndex(), _wmo_maps_search->isChecked());
});
QObject::connect(_combo_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_exp_search](int index)
QObject::connect(_combo_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_exp_search, _wmo_maps_search](int index)
{
applyFilterSearch(_line_edit_search->text(), index, _combo_exp_search->currentIndex());
applyFilterSearch(_line_edit_search->text(), index, _combo_exp_search->currentIndex(), _wmo_maps_search->isChecked());
});
QObject::connect(_combo_exp_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_search](int index)
QObject::connect(_combo_exp_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_search, _wmo_maps_search](int index)
{
applyFilterSearch(_line_edit_search->text(), _combo_search->currentIndex(), index);
applyFilterSearch(_line_edit_search->text(), _combo_search->currentIndex(), index, _wmo_maps_search->isChecked());
});
QObject::connect(_wmo_maps_search, &QCheckBox::stateChanged, [this, _line_edit_search, _combo_search, _combo_exp_search](bool b)
{
applyFilterSearch(_line_edit_search->text(), _combo_search->currentIndex(), _combo_exp_search->currentIndex(), b);
});
QFormLayout* _group_layout = new QFormLayout();
_group_layout->addRow(tr("Name : "), _line_edit_search);
_group_layout->addRow(tr("Type : "), _combo_search);
_group_layout->addRow(tr("Expansion : "), _combo_exp_search);
_group_layout->addRow( _wmo_maps_search);
_group_search->setLayout(_group_layout);
_first_tab_layout->addWidget(_group_search);
@@ -374,7 +408,10 @@ namespace Noggit::Ui::Windows
QObject::connect(_minimap, &minimap_widget::map_clicked, [this](::glm::vec3 const& pos)
{
check_uid_then_enter_map(pos, math::degrees(30.f), math::degrees(90.f));
if (_world->mapIndex.hasAGlobalWMO()) // skip uid check
enterMapAt(pos, math::degrees(30.f), math::degrees(90.f), uid_fix_mode::none, false);
else
check_uid_then_enter_map(pos, math::degrees(30.f), math::degrees(90.f));
}
);

View File

@@ -87,7 +87,7 @@ namespace Noggit::Ui::Windows
QListWidget* _continents_table;
QString _filter_name;
void applyFilterSearch(const QString& name, int type, int expansion);
void applyFilterSearch(const QString& name, int type, int expansion, bool wmo_maps);
std::unique_ptr<World> _world;

View File

@@ -42,6 +42,8 @@ void BuildMapListComponent::buildMapList(Noggit::Ui::Windows::NoggitWindow* pare
if (map_list_data.map_type_id < 0 || map_list_data.map_type_id > 5 || !World::IsEditableWorld(record))
continue;
map_list_data.wmo_map = (World::IsWMOWorld(record));
auto project_pinned_maps = parent->_project->PinnedMaps;
auto pinned_map_found = std::find_if(std::begin(project_pinned_maps), std::end(project_pinned_maps),

View File

@@ -18,6 +18,7 @@ namespace Noggit::Ui::Widget
int map_type_id;
int expansion_id;
bool pinned;
bool wmo_map;
};
class MapListItem : public QWidget
@@ -40,6 +41,7 @@ namespace Noggit::Ui::Widget
int id() { return _map_data.map_id; };
int type() { return _map_data.map_type_id; };
int expansion() { return _map_data.expansion_id; };
bool wmo_map() { return _map_data.wmo_map; };
private:
QString toCamelCase(const QString& s);