mirror of
https://github.com/redstrate/Novus.git
synced 2025-04-24 13:07:44 +00:00
Apply racial scaling deforms
This commit is contained in:
parent
fecb015ff2
commit
8daa9f502d
4 changed files with 229 additions and 106 deletions
|
@ -33,7 +33,7 @@ public:
|
||||||
explicit GearView(GameData* data);
|
explicit GearView(GameData* data);
|
||||||
|
|
||||||
/// Returns an inclusive list of races supported by the current gearset.
|
/// Returns an inclusive list of races supported by the current gearset.
|
||||||
std::vector<Race> supportedRaces() const;
|
std::vector<std::pair<Race, Subrace>> supportedRaces() const;
|
||||||
|
|
||||||
/// Returns an inclusive list of genders supported by the current gearset.
|
/// Returns an inclusive list of genders supported by the current gearset.
|
||||||
std::vector<Gender> supportedGenders() const;
|
std::vector<Gender> supportedGenders() const;
|
||||||
|
@ -41,31 +41,36 @@ public:
|
||||||
/// Returns an inclusive list of LoDs supported by the current gearset.
|
/// Returns an inclusive list of LoDs supported by the current gearset.
|
||||||
int lodCount() const;
|
int lodCount() const;
|
||||||
|
|
||||||
void exportModel(const QString& fileName);
|
void exportModel(const QString &fileName);
|
||||||
|
|
||||||
MDLPart& part() const;
|
MDLPart &part() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Race currentRace = Race::Hyur;
|
||||||
|
Subrace currentSubrace = Subrace::Midlander;
|
||||||
|
Gender currentGender = Gender::Male;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
void gearChanged();
|
void gearChanged();
|
||||||
void modelReloaded();
|
void modelReloaded();
|
||||||
|
|
||||||
void raceChanged();
|
void raceChanged();
|
||||||
|
void subraceChanged();
|
||||||
void genderChanged();
|
void genderChanged();
|
||||||
void levelOfDetailChanged();
|
void levelOfDetailChanged();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void clear();
|
void clear();
|
||||||
void addGear(GearInfo& gear);
|
void addGear(GearInfo& gear);
|
||||||
|
|
||||||
void setRace(Race race);
|
void setRace(Race race);
|
||||||
|
void setSubrace(Subrace subrace);
|
||||||
void setGender(Gender gender);
|
void setGender(Gender gender);
|
||||||
void setLevelOfDetail(int lod);
|
void setLevelOfDetail(int lod);
|
||||||
|
|
||||||
void reloadModel();
|
void reloadModel();
|
||||||
|
void reloadRaceDeforms();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Race currentRace = Race::Hyur;
|
|
||||||
Gender currentGender = Gender::Female;
|
|
||||||
int currentLod = 0;
|
int currentLod = 0;
|
||||||
|
|
||||||
uint32_t maxLod = 0;
|
uint32_t maxLod = 0;
|
||||||
|
|
|
@ -5,31 +5,40 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
GearView::GearView(GameData *data) : data(data) {
|
GearView::GearView(GameData *data) : data(data) {
|
||||||
mdlPart = new MDLPart(data);
|
mdlPart = new MDLPart(data);
|
||||||
|
|
||||||
mdlPart->setSkeleton(physis_skeleton_from_skel(physis_read_file("c0101b0001.skel")));
|
reloadRaceDeforms();
|
||||||
|
|
||||||
auto layout = new QVBoxLayout();
|
auto layout = new QVBoxLayout();
|
||||||
layout->addWidget(mdlPart);
|
layout->addWidget(mdlPart);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
connect(this, &GearView::gearChanged, this, &GearView::reloadModel);
|
connect(this, &GearView::gearChanged, this, [=] { reloadModel(); });
|
||||||
|
|
||||||
connect(this, &GearView::raceChanged, this, &GearView::reloadModel);
|
connect(this, &GearView::raceChanged, this, [=] {
|
||||||
connect(this, &GearView::genderChanged, this, &GearView::reloadModel);
|
reloadRaceDeforms();
|
||||||
connect(this, &GearView::levelOfDetailChanged, this, &GearView::reloadModel);
|
reloadModel();
|
||||||
|
});
|
||||||
|
connect(this, &GearView::genderChanged, this, [=] {
|
||||||
|
reloadRaceDeforms();
|
||||||
|
reloadModel();
|
||||||
|
});
|
||||||
|
connect(this, &GearView::levelOfDetailChanged, this, &GearView::reloadModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Race> GearView::supportedRaces() const {
|
std::vector<std::pair<Race, Subrace>> GearView::supportedRaces() const {
|
||||||
std::vector<Race> races;
|
std::vector<std::pair<Race, Subrace>> races;
|
||||||
for (const auto& gear : gears) {
|
for (const auto &gear : gears) {
|
||||||
for(auto [race, race_name] : magic_enum::enum_entries<Race>()) {
|
for (auto [race, race_name] : magic_enum::enum_entries<Race>()) {
|
||||||
auto equip_path = physis_build_equipment_path(gear.modelInfo.primaryID, race, Subrace::Midlander, currentGender, gear.slot);
|
for (auto subrace : physis_get_supported_subraces(race).subraces) {
|
||||||
|
auto equip_path = physis_build_equipment_path(
|
||||||
|
gear.modelInfo.primaryID, race, subrace, currentGender, gear.slot);
|
||||||
|
|
||||||
if(physis_gamedata_exists(data, equip_path))
|
if (physis_gamedata_exists(data, equip_path))
|
||||||
races.push_back(race);
|
races.emplace_back(race, subrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return races;
|
return races;
|
||||||
}
|
}
|
||||||
|
@ -76,9 +85,26 @@ void GearView::setRace(Race race) {
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRace = race;
|
currentRace = race;
|
||||||
|
|
||||||
|
auto supportedSubraces = physis_get_supported_subraces(race);
|
||||||
|
if (supportedSubraces.subraces[0] == currentSubrace ||
|
||||||
|
supportedSubraces.subraces[1] == currentSubrace) {
|
||||||
|
} else {
|
||||||
|
setSubrace(supportedSubraces.subraces[0]);
|
||||||
|
}
|
||||||
|
|
||||||
Q_EMIT raceChanged();
|
Q_EMIT raceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GearView::setSubrace(Subrace subrace) {
|
||||||
|
if (currentSubrace == subrace) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSubrace = subrace;
|
||||||
|
Q_EMIT subraceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void GearView::setGender(Gender gender) {
|
void GearView::setGender(Gender gender) {
|
||||||
if (currentGender == gender) {
|
if (currentGender == gender) {
|
||||||
return;
|
return;
|
||||||
|
@ -103,25 +129,50 @@ void GearView::reloadModel() {
|
||||||
maxLod = 0;
|
maxLod = 0;
|
||||||
|
|
||||||
for (const auto& gear : gears) {
|
for (const auto& gear : gears) {
|
||||||
auto mdl_data = physis_gamedata_extract_file(data, physis_build_equipment_path(gear.modelInfo.primaryID, currentRace, Subrace::Midlander, currentGender, gear.slot));
|
auto mdl_data = physis_gamedata_extract_file(
|
||||||
|
data, physis_build_equipment_path(gear.modelInfo.primaryID,
|
||||||
|
currentRace, currentSubrace,
|
||||||
|
currentGender, gear.slot));
|
||||||
|
|
||||||
|
// attempt to load the next best race
|
||||||
|
// currently hardcoded to hyur midlander
|
||||||
|
Race fallbackRace = currentRace;
|
||||||
|
Subrace fallbackSubrace = currentSubrace;
|
||||||
|
if (mdl_data.size == 0) {
|
||||||
|
mdl_data = physis_gamedata_extract_file(
|
||||||
|
data, physis_build_equipment_path(
|
||||||
|
gear.modelInfo.primaryID, Race::Hyur,
|
||||||
|
Subrace::Midlander, currentGender, gear.slot));
|
||||||
|
fallbackRace = Race::Hyur;
|
||||||
|
fallbackSubrace = Subrace::Midlander;
|
||||||
|
}
|
||||||
|
|
||||||
if (mdl_data.size > 0) {
|
if (mdl_data.size > 0) {
|
||||||
auto mdl = physis_mdl_parse(mdl_data.size, mdl_data.data);
|
auto mdl = physis_mdl_parse(mdl_data.size, mdl_data.data);
|
||||||
|
|
||||||
std::vector<physis_Material> materials;
|
std::vector<physis_Material> materials;
|
||||||
for (int i = 0; i < mdl.num_material_names; i++) {
|
for (int i = 0; i < mdl.num_material_names; i++) {
|
||||||
const char* material_name = mdl.material_names[i];
|
const char *material_name = mdl.material_names[i];
|
||||||
|
|
||||||
//std::string mtrl_path = loadedGear.gearInfo->getMtrlPath(201);
|
// std::string mtrl_path =
|
||||||
std::string mtrl_path = fmt::format("chara/equipment/e{gearId:04d}/material/v{gearVersion:04d}{}", material_name,
|
// loadedGear.gearInfo->getMtrlPath(201);
|
||||||
fmt::arg("gearId", gear.modelInfo.primaryID),
|
std::string mtrl_path = fmt::format(
|
||||||
|
"chara/equipment/e{gearId:04d}/material/"
|
||||||
|
"v{gearVersion:04d}{}",
|
||||||
|
material_name, fmt::arg("gearId", gear.modelInfo.primaryID),
|
||||||
fmt::arg("gearVersion", gear.modelInfo.gearVersion));
|
fmt::arg("gearVersion", gear.modelInfo.gearVersion));
|
||||||
|
|
||||||
int bodyCode = 1;
|
int bodyCode = 1;
|
||||||
|
|
||||||
// skin path
|
// skin path
|
||||||
std::string skinmtrl_path = fmt::format("chara/human/c{raceCode:04d}/obj/body/b{bodyCode:04d}/material/v0001{}", material_name,
|
std::string skinmtrl_path = fmt::format(
|
||||||
fmt::arg("raceCode", physis_get_race_code(currentRace, Subrace::Midlander, currentGender)),
|
"chara/human/c{raceCode:04d}/obj/body/b{bodyCode:04d}/"
|
||||||
fmt::arg("bodyCode", bodyCode));
|
"material/v0001{}",
|
||||||
|
material_name,
|
||||||
|
fmt::arg("raceCode",
|
||||||
|
physis_get_race_code(fallbackRace, fallbackSubrace,
|
||||||
|
currentGender)),
|
||||||
|
fmt::arg("bodyCode", bodyCode));
|
||||||
|
|
||||||
if(physis_gamedata_exists(data, mtrl_path.c_str())) {
|
if(physis_gamedata_exists(data, mtrl_path.c_str())) {
|
||||||
auto mat = physis_material_parse(physis_gamedata_extract_file(data, mtrl_path.c_str()));
|
auto mat = physis_material_parse(physis_gamedata_extract_file(data, mtrl_path.c_str()));
|
||||||
|
@ -143,8 +194,33 @@ void GearView::reloadModel() {
|
||||||
Q_EMIT modelReloaded();
|
Q_EMIT modelReloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
MDLPart &GearView::part() const {
|
void GearView::reloadRaceDeforms() {
|
||||||
return *mdlPart;
|
qDebug() << "Loading race deform matrices for "
|
||||||
|
<< magic_enum::enum_name(currentRace).data()
|
||||||
|
<< magic_enum::enum_name(currentSubrace).data()
|
||||||
|
<< magic_enum::enum_name(currentGender).data();
|
||||||
|
const int raceCode =
|
||||||
|
physis_get_race_code(currentRace, currentSubrace, currentGender);
|
||||||
|
qDebug() << "Race code: " << raceCode;
|
||||||
|
|
||||||
|
QString skelName =
|
||||||
|
QString{"c%1b0001.skel"}.arg(raceCode, 4, 10, QLatin1Char{'0'});
|
||||||
|
mdlPart->setSkeleton(physis_skeleton_from_skel(
|
||||||
|
physis_read_file(skelName.toStdString().c_str())));
|
||||||
|
|
||||||
|
// racial deforms don't work on Hyur, not needed? TODO not sure
|
||||||
|
if (currentRace != Race::Hyur) {
|
||||||
|
QString deformName =
|
||||||
|
QString{"c%1_deform.json"}.arg(raceCode, 4, 10, QLatin1Char{'0'});
|
||||||
|
mdlPart->loadRaceDeformMatrices(
|
||||||
|
physis_read_file(deformName.toStdString().c_str()));
|
||||||
|
} else {
|
||||||
|
for (auto &data : mdlPart->boneData) {
|
||||||
|
data.deformRaceMatrix = glm::mat4(1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDLPart &GearView::part() const { return *mdlPart; }
|
||||||
|
|
||||||
#include "moc_gearview.cpp"
|
#include "moc_gearview.cpp"
|
||||||
|
|
|
@ -1,40 +1,43 @@
|
||||||
#include "mdlpart.h"
|
#include "mdlpart.h"
|
||||||
#include "glm/gtx/transform.hpp"
|
#include "glm/gtx/transform.hpp"
|
||||||
|
|
||||||
#include <QWindow>
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QVBoxLayout>
|
||||||
#include <QVulkanInstance>
|
#include <QVulkanInstance>
|
||||||
#include <QVulkanWindow>
|
#include <QVulkanWindow>
|
||||||
#include <QResizeEvent>
|
#include <QWindow>
|
||||||
|
#include <assimp/Exporter.hpp>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
#include <assimp/scene.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
#include <assimp/Exporter.hpp>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include <assimp/postprocess.h>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <glm/gtc/type_ptr.inl>
|
#include <glm/gtc/type_ptr.inl>
|
||||||
|
|
||||||
#ifndef USE_STANDALONE_WINDOW
|
#ifndef USE_STANDALONE_WINDOW
|
||||||
class VulkanWindow : public QWindow
|
class VulkanWindow : public QWindow {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
VulkanWindow(MDLPart* part, Renderer* renderer, QVulkanInstance* instance) : part(part), m_renderer(renderer), m_instance(instance) {
|
VulkanWindow(MDLPart *part, Renderer *renderer, QVulkanInstance *instance)
|
||||||
setSurfaceType(VulkanSurface);
|
: part(part), m_renderer(renderer), m_instance(instance) {
|
||||||
setVulkanInstance(instance);
|
setSurfaceType(VulkanSurface);
|
||||||
|
setVulkanInstance(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void exposeEvent(QExposeEvent *) {
|
||||||
|
if (isExposed()) {
|
||||||
|
if (!m_initialized) {
|
||||||
|
m_initialized = true;
|
||||||
|
|
||||||
|
auto surface = m_instance->surfaceForWindow(this);
|
||||||
|
if (!m_renderer->initSwapchain(surface, width(), height()))
|
||||||
|
m_initialized = false;
|
||||||
|
else
|
||||||
|
render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void exposeEvent(QExposeEvent *) {
|
|
||||||
if (isExposed()) {
|
|
||||||
if (!m_initialized) {
|
|
||||||
m_initialized = true;
|
|
||||||
|
|
||||||
auto surface = m_instance->surfaceForWindow(this);
|
|
||||||
if(!m_renderer->initSwapchain(surface, width(), height()))
|
|
||||||
m_initialized = false;
|
|
||||||
else
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool event(QEvent *e) {
|
bool event(QEvent *e) {
|
||||||
|
@ -346,6 +349,32 @@ void MDLPart::setSkeleton(physis_Skeleton newSkeleton) {
|
||||||
Q_EMIT skeletonChanged();
|
Q_EMIT skeletonChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MDLPart::loadRaceDeformMatrices(physis_Buffer buffer) {
|
||||||
|
QJsonDocument document = QJsonDocument::fromJson(
|
||||||
|
QByteArray((const char *)buffer.data, buffer.size));
|
||||||
|
for (auto boneObj : document.object()["Data"].toArray()) {
|
||||||
|
QJsonArray matrix = boneObj.toObject()["Matrix"].toArray();
|
||||||
|
QString boneName = boneObj.toObject()["Name"].toString();
|
||||||
|
|
||||||
|
glm::mat4 actualMatrix;
|
||||||
|
int i = 0;
|
||||||
|
for (auto val : matrix) {
|
||||||
|
glm::value_ptr(actualMatrix)[i++] = val.toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < skeleton->num_bones; i++) {
|
||||||
|
if (std::string_view{skeleton->bones[i].name} ==
|
||||||
|
boneName.toStdString()) {
|
||||||
|
auto &data = boneData[i];
|
||||||
|
|
||||||
|
data.deformRaceMatrix = actualMatrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
firstTimeSkeletonDataCalculated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MDLPart::clearSkeleton() {
|
void MDLPart::clearSkeleton() {
|
||||||
skeleton.reset();
|
skeleton.reset();
|
||||||
|
|
||||||
|
@ -366,12 +395,14 @@ void MDLPart::reloadRenderer() {
|
||||||
|
|
||||||
void MDLPart::reloadBoneData() {
|
void MDLPart::reloadBoneData() {
|
||||||
if(skeleton) {
|
if(skeleton) {
|
||||||
// first-time data, TODO split out
|
|
||||||
if (!firstTimeSkeletonDataCalculated) {
|
if (!firstTimeSkeletonDataCalculated) {
|
||||||
boneData.resize(skeleton->num_bones);
|
if (boneData.empty()) {
|
||||||
|
boneData.resize(skeleton->num_bones);
|
||||||
|
}
|
||||||
|
|
||||||
calculateBoneInversePose(*skeleton, *skeleton->root_bone, nullptr);
|
calculateBoneInversePose(*skeleton, *skeleton->root_bone, nullptr);
|
||||||
|
|
||||||
for (auto &bone: boneData) {
|
for (auto &bone : boneData) {
|
||||||
bone.inversePose = glm::inverse(bone.inversePose);
|
bone.inversePose = glm::inverse(bone.inversePose);
|
||||||
}
|
}
|
||||||
firstTimeSkeletonDataCalculated = true;
|
firstTimeSkeletonDataCalculated = true;
|
||||||
|
@ -450,7 +481,7 @@ RenderMaterial MDLPart::createMaterial(const physis_Material &material) {
|
||||||
void MDLPart::calculateBoneInversePose(physis_Skeleton& skeleton, physis_Bone& bone, physis_Bone* parent_bone) {
|
void MDLPart::calculateBoneInversePose(physis_Skeleton& skeleton, physis_Bone& bone, physis_Bone* parent_bone) {
|
||||||
const glm::mat4 parentMatrix = parent_bone == nullptr ? glm::mat4(1.0f) : boneData[parent_bone->index].inversePose;
|
const glm::mat4 parentMatrix = parent_bone == nullptr ? glm::mat4(1.0f) : boneData[parent_bone->index].inversePose;
|
||||||
|
|
||||||
glm::mat4 local(1.0f);
|
glm::mat4 local = glm::mat4(1.0f);
|
||||||
local = glm::translate(local, glm::vec3(bone.position[0], bone.position[1], bone.position[2]));
|
local = glm::translate(local, glm::vec3(bone.position[0], bone.position[1], bone.position[2]));
|
||||||
local *= glm::mat4_cast(glm::quat(bone.rotation[3], bone.rotation[0], bone.rotation[1], bone.rotation[2]));
|
local *= glm::mat4_cast(glm::quat(bone.rotation[3], bone.rotation[0], bone.rotation[1], bone.rotation[2]));
|
||||||
local = glm::scale(local, glm::vec3(bone.scale[0], bone.scale[1], bone.scale[2]));
|
local = glm::scale(local, glm::vec3(bone.scale[0], bone.scale[1], bone.scale[2]));
|
||||||
|
@ -465,18 +496,28 @@ void MDLPart::calculateBoneInversePose(physis_Skeleton& skeleton, physis_Bone& b
|
||||||
}
|
}
|
||||||
|
|
||||||
void MDLPart::calculateBone(physis_Skeleton& skeleton, physis_Bone& bone, const physis_Bone* parent_bone) {
|
void MDLPart::calculateBone(physis_Skeleton& skeleton, physis_Bone& bone, const physis_Bone* parent_bone) {
|
||||||
const glm::mat4 parent_matrix = parent_bone == nullptr ? glm::mat4(1.0f) : boneData[parent_bone->index].localTransform;
|
const glm::mat4 parent_matrix =
|
||||||
|
parent_bone == nullptr ? glm::mat4(1.0f)
|
||||||
|
: boneData[parent_bone->index].localTransform;
|
||||||
|
|
||||||
glm::mat4 local = glm::mat4(1.0f);
|
glm::mat4 local = glm::mat4(1.0f);
|
||||||
local = glm::translate(local, glm::vec3(bone.position[0], bone.position[1], bone.position[2]));
|
local = glm::translate(
|
||||||
local *= glm::mat4_cast(glm::quat(bone.rotation[3], bone.rotation[0], bone.rotation[1], bone.rotation[2]));
|
local, glm::vec3(bone.position[0], bone.position[1], bone.position[2]));
|
||||||
local = glm::scale(local, glm::vec3(bone.scale[0], bone.scale[1], bone.scale[2]));
|
local *= glm::mat4_cast(glm::quat(bone.rotation[3], bone.rotation[0],
|
||||||
|
bone.rotation[1], bone.rotation[2]));
|
||||||
|
local = glm::scale(local,
|
||||||
|
glm::vec3(bone.scale[0], bone.scale[1], bone.scale[2]));
|
||||||
|
|
||||||
boneData[bone.index].localTransform = parent_matrix * local;
|
boneData[bone.index].localTransform = parent_matrix * local;
|
||||||
boneData[bone.index].finalTransform = boneData[bone.index].localTransform * boneData[bone.index].inversePose;
|
boneData[bone.index].finalTransform =
|
||||||
|
boneData[bone.index].localTransform *
|
||||||
|
boneData[bone.index].deformRaceMatrix *
|
||||||
|
boneData[bone.index].inversePose;
|
||||||
|
|
||||||
for(int i = 0; i < skeleton.num_bones; i++) {
|
for (int i = 0; i < skeleton.num_bones; i++) {
|
||||||
if(skeleton.bones[i].parent_bone != nullptr && std::string_view{skeleton.bones[i].parent_bone->name} == std::string_view{bone.name}) {
|
if (skeleton.bones[i].parent_bone != nullptr &&
|
||||||
|
std::string_view{skeleton.bones[i].parent_bone->name} ==
|
||||||
|
std::string_view{bone.name}) {
|
||||||
calculateBone(skeleton, skeleton.bones[i], &bone);
|
calculateBone(skeleton, skeleton.bones[i], &bone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,66 +12,67 @@ class VulkanWindow;
|
||||||
class StandaloneWindow;
|
class StandaloneWindow;
|
||||||
|
|
||||||
class MDLPart : public QWidget {
|
class MDLPart : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MDLPart(GameData* data);
|
explicit MDLPart(GameData *data);
|
||||||
|
|
||||||
void exportModel(const QString& fileName);
|
void exportModel(const QString &fileName);
|
||||||
|
|
||||||
int lastX = -1;
|
int lastX = -1;
|
||||||
int lastY = -1;
|
int lastY = -1;
|
||||||
|
|
||||||
enum class CameraMode {
|
enum class CameraMode { None, Orbit, Move };
|
||||||
None,
|
|
||||||
Orbit,
|
|
||||||
Move
|
|
||||||
};
|
|
||||||
|
|
||||||
CameraMode cameraMode = CameraMode::None;
|
CameraMode cameraMode = CameraMode::None;
|
||||||
float pitch = 0.0f;
|
float pitch = 0.0f;
|
||||||
float yaw = 0.0f;
|
float yaw = 0.0f;
|
||||||
float cameraDistance = 5.0f;
|
float cameraDistance = 5.0f;
|
||||||
glm::vec3 position {0, 0, 0};
|
glm::vec3 position{0, 0, 0};
|
||||||
|
|
||||||
std::unique_ptr<physis_Skeleton> skeleton;
|
std::unique_ptr<physis_Skeleton> skeleton;
|
||||||
|
|
||||||
|
struct BoneData {
|
||||||
|
glm::mat4 localTransform, finalTransform, inversePose;
|
||||||
|
glm::mat4 deformRaceMatrix{1.0f};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<BoneData> boneData;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void modelChanged();
|
void modelChanged();
|
||||||
void skeletonChanged();
|
void skeletonChanged();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/// Clears all stored MDLs.
|
/// Clears all stored MDLs.
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/// Adds a new MDL with a list of materials used.
|
/// Adds a new MDL with a list of materials used.
|
||||||
void addModel(physis_MDL mdl, std::vector<physis_Material> materials, int lod);
|
void addModel(physis_MDL mdl, std::vector<physis_Material> materials,
|
||||||
|
int lod);
|
||||||
|
|
||||||
/// Sets the skeleton any skinned MDLs should bind to.
|
/// Sets the skeleton any skinned MDLs should bind to.
|
||||||
void setSkeleton(physis_Skeleton skeleton);
|
void setSkeleton(physis_Skeleton skeleton);
|
||||||
|
|
||||||
/// Clears the current skeleton.
|
/// Sets the race deform matrices
|
||||||
void clearSkeleton();
|
void loadRaceDeformMatrices(physis_Buffer buffer);
|
||||||
|
|
||||||
void reloadBoneData();
|
/// Clears the current skeleton.
|
||||||
void reloadRenderer();
|
void clearSkeleton();
|
||||||
|
|
||||||
|
void reloadBoneData();
|
||||||
|
void reloadRenderer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderMaterial createMaterial(const physis_Material& mat);
|
RenderMaterial createMaterial(const physis_Material &mat);
|
||||||
|
|
||||||
void calculateBoneInversePose(physis_Skeleton& skeleton, physis_Bone& bone, physis_Bone* parent_bone);
|
void calculateBoneInversePose(physis_Skeleton& skeleton, physis_Bone& bone, physis_Bone* parent_bone);
|
||||||
void calculateBone(physis_Skeleton& skeleton, physis_Bone& bone, const physis_Bone* parent_bone);
|
void calculateBone(physis_Skeleton& skeleton, physis_Bone& bone, const physis_Bone* parent_bone);
|
||||||
|
|
||||||
GameData* data = nullptr;
|
GameData* data = nullptr;
|
||||||
|
|
||||||
std::vector<RenderModel> models;
|
std::vector<RenderModel> models;
|
||||||
|
|
||||||
struct BoneData {
|
|
||||||
glm::mat4 localTransform, finalTransform, inversePose;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<BoneData> boneData;
|
|
||||||
|
|
||||||
Renderer* renderer;
|
Renderer* renderer;
|
||||||
VulkanWindow* vkWindow;
|
VulkanWindow* vkWindow;
|
||||||
StandaloneWindow* standaloneWindow;
|
StandaloneWindow* standaloneWindow;
|
||||||
|
|
Loading…
Add table
Reference in a new issue