1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-04-27 22:27:46 +00:00

Overhaul race and lod combos in mdlviewer

The number of lods are now properly loaded from the model data, and race
is checked by checking for the existence of race-specific models (I
think this is the current best way?).

Also, magic_enum is added as a dependency for some enum magic involving
enumerating Race.
This commit is contained in:
Joshua Goins 2022-04-17 20:02:06 -04:00
parent d454dcf005
commit 275c1a9976
8 changed files with 1212 additions and 41 deletions

View file

@ -10,6 +10,8 @@ add_subdirectory(libxiv)
include(FetchContent)
add_subdirectory(extern/magic_enum)
find_package(fmt QUIET)
if(TARGET fmt::fmt)

2
extern/magic_enum/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,2 @@
add_library(magic_enum INTERFACE)
target_include_directories(magic_enum INTERFACE include)

1139
extern/magic_enum/include/magic_enum.hpp vendored Normal file

File diff suppressed because it is too large Load diff

2
libxiv

@ -1 +1 @@
Subproject commit c78a1ab2458d18ddd92fc2728e3eedd95fdc4078
Subproject commit 872bef51bb32792750a7b2a392385fb41158ead6

View file

@ -12,7 +12,8 @@ target_link_libraries(mdlviewer PUBLIC
Qt5::Core
Qt5::Widgets
renderer
assimp::assimp)
assimp::assimp
magic_enum)
install(TARGETS mdlviewer
DESTINATION "${INSTALL_BIN_PATH}")

View file

@ -2,6 +2,7 @@
#include <QMainWindow>
#include <unordered_map>
#include <QComboBox>
#include "renderer.hpp"
#include "types/slot.h"
@ -25,13 +26,24 @@ class MainWindow : public QMainWindow {
public:
MainWindow(GameData& data);
void refreshModel();
void exportModel(Model& model, QString fileName);
private:
void loadInitialGearInfo(GearInfo& info);
void reloadGearModel();
void reloadGearAppearance();
std::vector<GearInfo> gears;
std::vector<GearInfo*> loadedGears;
struct LoadedGear {
GearInfo* gearInfo;
Model model;
RenderModel renderModel;
};
LoadedGear loadedGear;
QComboBox* raceCombo, *lodCombo;
Race currentRace = Race::HyurMidlanderMale;
int currentLod = 0;

View file

@ -16,6 +16,7 @@
#include <assimp/postprocess.h>
#include <QPushButton>
#include <QFileDialog>
#include <magic_enum.hpp>
#include "gamedata.h"
#include "exhparser.h"
@ -163,29 +164,20 @@ MainWindow::MainWindow(GameData& data) : data(data) {
QHBoxLayout* controlLayout = new QHBoxLayout();
viewportLayout->addLayout(controlLayout);
QComboBox* raceCombo = new QComboBox();
raceCombo->addItem("Midlander Male");
raceCombo->addItem("Midlander Female");
/*for(auto [race, raceName] : raceNames) {
raceCombo->addItem(raceName.data());
}*/
raceCombo = new QComboBox();
connect(raceCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
currentRace = (Race)index;
refreshModel();
reloadGearModel();
});
controlLayout->addWidget(raceCombo);
auto lodCombo = new QComboBox();
lodCombo->addItem("0");
lodCombo->addItem("1");
lodCombo->addItem("2");
lodCombo = new QComboBox();
connect(lodCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
currentLod = index;
refreshModel();
reloadGearAppearance();
});
controlLayout->addWidget(lodCombo);
@ -210,33 +202,14 @@ MainWindow::MainWindow(GameData& data) : data(data) {
connect(listWidget, &QListWidget::itemClicked, [this](QListWidgetItem* item) {
for(auto& gear : gears) {
if(gear.name == item->text().toStdString())
loadedGears = {&gear};
if(gear.name == item->text().toStdString()) {
loadInitialGearInfo(gear);
return;
}
}
refreshModel();
});
}
void MainWindow::refreshModel() {
#ifdef USE_STANDALONE_WINDOW
standaloneWindow->models.clear();
#else
vkWindow->models.clear();
#endif
for(auto gear : loadedGears) {
auto mdl_data = data.extractFile(build_equipment_path(gear->modelInfo.primaryID, currentRace, gear->slot));
auto model = parseMDL(*mdl_data);
#ifndef USE_STANDALONE_WINDOW
vkWindow->models.push_back(renderer->addModel(model, currentLod));
#else
standaloneWindow->models.push_back(renderer->addModel(model, currentLod));
#endif
}
}
void MainWindow::exportModel(Model& model, QString fileName) {
Assimp::Exporter exporter;
@ -289,3 +262,42 @@ void MainWindow::exportModel(Model& model, QString fileName) {
exporter.Export(&scene, "fbx", fileName.toStdString());
}
void MainWindow::loadInitialGearInfo(GearInfo& info) {
loadedGear.gearInfo = &info;
raceCombo->clear();
for(auto [race, race_name] : magic_enum::enum_entries<Race>()) {
if(data.exists(build_equipment_path(loadedGear.gearInfo->modelInfo.primaryID, race, loadedGear.gearInfo->slot)))
raceCombo->addItem(race_name.data());
}
currentLod = 0;
currentRace = Race::HyurMidlanderMale;
reloadGearModel();
}
void MainWindow::reloadGearModel() {
auto mdl_data = data.extractFile(build_equipment_path(loadedGear.gearInfo->modelInfo.primaryID, currentRace, loadedGear.gearInfo->slot));
if(mdl_data == std::nullopt)
return;
loadedGear.model = parseMDL(*mdl_data);
lodCombo->clear();
for(int i = 0; i < loadedGear.model.lods.size(); i++)
lodCombo->addItem(QString::number(i));
reloadGearAppearance();
}
void MainWindow::reloadGearAppearance() {
loadedGear.renderModel = renderer->addModel(loadedGear.model, currentLod);
#ifndef USE_STANDALONE_WINDOW
vkWindow->models = {loadedGear.renderModel};
#else
standaloneWindow->models = {loadedGear.renderModel};
#endif
}

View file

@ -512,6 +512,9 @@ RenderModel Renderer::addModel(const Model& model, int lod) {
RenderModel renderModel;
renderModel.model = model;
if(lod < 0 || lod > model.lods.size())
return {};
for(auto part : model.lods[lod].parts) {
RenderPart renderPart;