mirror of
https://github.com/redstrate/Novus.git
synced 2025-04-29 06:57: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:
parent
d454dcf005
commit
275c1a9976
8 changed files with 1212 additions and 41 deletions
|
@ -10,6 +10,8 @@ add_subdirectory(libxiv)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
add_subdirectory(extern/magic_enum)
|
||||||
|
|
||||||
find_package(fmt QUIET)
|
find_package(fmt QUIET)
|
||||||
|
|
||||||
if(TARGET fmt::fmt)
|
if(TARGET fmt::fmt)
|
||||||
|
|
2
extern/magic_enum/CMakeLists.txt
vendored
Normal file
2
extern/magic_enum/CMakeLists.txt
vendored
Normal 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
1139
extern/magic_enum/include/magic_enum.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
2
libxiv
2
libxiv
|
@ -1 +1 @@
|
||||||
Subproject commit c78a1ab2458d18ddd92fc2728e3eedd95fdc4078
|
Subproject commit 872bef51bb32792750a7b2a392385fb41158ead6
|
|
@ -12,7 +12,8 @@ target_link_libraries(mdlviewer PUBLIC
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Widgets
|
Qt5::Widgets
|
||||||
renderer
|
renderer
|
||||||
assimp::assimp)
|
assimp::assimp
|
||||||
|
magic_enum)
|
||||||
|
|
||||||
install(TARGETS mdlviewer
|
install(TARGETS mdlviewer
|
||||||
DESTINATION "${INSTALL_BIN_PATH}")
|
DESTINATION "${INSTALL_BIN_PATH}")
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "types/slot.h"
|
#include "types/slot.h"
|
||||||
|
@ -25,13 +26,24 @@ class MainWindow : public QMainWindow {
|
||||||
public:
|
public:
|
||||||
MainWindow(GameData& data);
|
MainWindow(GameData& data);
|
||||||
|
|
||||||
void refreshModel();
|
|
||||||
|
|
||||||
void exportModel(Model& model, QString fileName);
|
void exportModel(Model& model, QString fileName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void loadInitialGearInfo(GearInfo& info);
|
||||||
|
void reloadGearModel();
|
||||||
|
void reloadGearAppearance();
|
||||||
|
|
||||||
std::vector<GearInfo> gears;
|
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;
|
Race currentRace = Race::HyurMidlanderMale;
|
||||||
int currentLod = 0;
|
int currentLod = 0;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
|
||||||
#include "gamedata.h"
|
#include "gamedata.h"
|
||||||
#include "exhparser.h"
|
#include "exhparser.h"
|
||||||
|
@ -163,29 +164,20 @@ MainWindow::MainWindow(GameData& data) : data(data) {
|
||||||
QHBoxLayout* controlLayout = new QHBoxLayout();
|
QHBoxLayout* controlLayout = new QHBoxLayout();
|
||||||
viewportLayout->addLayout(controlLayout);
|
viewportLayout->addLayout(controlLayout);
|
||||||
|
|
||||||
QComboBox* raceCombo = new QComboBox();
|
raceCombo = new QComboBox();
|
||||||
raceCombo->addItem("Midlander Male");
|
|
||||||
raceCombo->addItem("Midlander Female");
|
|
||||||
|
|
||||||
/*for(auto [race, raceName] : raceNames) {
|
|
||||||
raceCombo->addItem(raceName.data());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
connect(raceCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
connect(raceCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
currentRace = (Race)index;
|
currentRace = (Race)index;
|
||||||
refreshModel();
|
reloadGearModel();
|
||||||
});
|
});
|
||||||
|
|
||||||
controlLayout->addWidget(raceCombo);
|
controlLayout->addWidget(raceCombo);
|
||||||
|
|
||||||
auto lodCombo = new QComboBox();
|
lodCombo = new QComboBox();
|
||||||
lodCombo->addItem("0");
|
|
||||||
lodCombo->addItem("1");
|
|
||||||
lodCombo->addItem("2");
|
|
||||||
|
|
||||||
connect(lodCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
connect(lodCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
||||||
currentLod = index;
|
currentLod = index;
|
||||||
refreshModel();
|
reloadGearAppearance();
|
||||||
});
|
});
|
||||||
|
|
||||||
controlLayout->addWidget(lodCombo);
|
controlLayout->addWidget(lodCombo);
|
||||||
|
@ -210,33 +202,14 @@ MainWindow::MainWindow(GameData& data) : data(data) {
|
||||||
|
|
||||||
connect(listWidget, &QListWidget::itemClicked, [this](QListWidgetItem* item) {
|
connect(listWidget, &QListWidget::itemClicked, [this](QListWidgetItem* item) {
|
||||||
for(auto& gear : gears) {
|
for(auto& gear : gears) {
|
||||||
if(gear.name == item->text().toStdString())
|
if(gear.name == item->text().toStdString()) {
|
||||||
loadedGears = {&gear};
|
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) {
|
void MainWindow::exportModel(Model& model, QString fileName) {
|
||||||
Assimp::Exporter exporter;
|
Assimp::Exporter exporter;
|
||||||
|
|
||||||
|
@ -289,3 +262,42 @@ void MainWindow::exportModel(Model& model, QString fileName) {
|
||||||
|
|
||||||
exporter.Export(&scene, "fbx", fileName.toStdString());
|
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
|
||||||
|
}
|
|
@ -512,6 +512,9 @@ RenderModel Renderer::addModel(const Model& model, int lod) {
|
||||||
RenderModel renderModel;
|
RenderModel renderModel;
|
||||||
renderModel.model = model;
|
renderModel.model = model;
|
||||||
|
|
||||||
|
if(lod < 0 || lod > model.lods.size())
|
||||||
|
return {};
|
||||||
|
|
||||||
for(auto part : model.lods[lod].parts) {
|
for(auto part : model.lods[lod].parts) {
|
||||||
RenderPart renderPart;
|
RenderPart renderPart;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue