mirror of
https://github.com/redstrate/Novus.git
synced 2025-06-08 06:07:46 +00:00
Add glTF import support, multiple fixes for upstream physis changes
Adds basic glTF import (although right now it only imports back positions) and fixes support for more of the vertex data that's available to us. The MDL file isn't written back out yet either, it only displays in the viewport.
This commit is contained in:
parent
be5625c1b8
commit
c7b6dd076c
9 changed files with 217 additions and 33 deletions
|
@ -45,6 +45,8 @@ private Q_SLOTS:
|
||||||
void reloadGear();
|
void reloadGear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void importModel(const QString &filename);
|
||||||
|
|
||||||
std::optional<GearInfo> currentGear;
|
std::optional<GearInfo> currentGear;
|
||||||
|
|
||||||
Race currentRace = Race::Hyur;
|
Race currentRace = Race::Hyur;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "filecache.h"
|
#include "filecache.h"
|
||||||
#include "magic_enum.hpp"
|
#include "magic_enum.hpp"
|
||||||
|
#include "tiny_gltf.h"
|
||||||
|
|
||||||
SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent)
|
SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
@ -88,6 +89,21 @@ SingleGearView::SingleGearView(GameData *data, FileCache &cache, QWidget *parent
|
||||||
|
|
||||||
importButton = new QPushButton(QStringLiteral("Import..."));
|
importButton = new QPushButton(QStringLiteral("Import..."));
|
||||||
importButton->setIcon(QIcon::fromTheme(QStringLiteral("document-import")));
|
importButton->setIcon(QIcon::fromTheme(QStringLiteral("document-import")));
|
||||||
|
connect(importButton, &QPushButton::clicked, this, [this](bool) {
|
||||||
|
if (currentGear.has_value()) {
|
||||||
|
// TODO: deduplicate
|
||||||
|
const auto sanitizeMdlPath = [](const QString &mdlPath) -> QString {
|
||||||
|
return QString(mdlPath).section(QLatin1Char('/'), -1).remove(QStringLiteral(".mdl"));
|
||||||
|
};
|
||||||
|
|
||||||
|
const QString fileName = QFileDialog::getOpenFileName(this,
|
||||||
|
tr("Import Model"),
|
||||||
|
QStringLiteral("%1.glb").arg(sanitizeMdlPath(gearView->getLoadedGearPath())),
|
||||||
|
tr("glTF Binary File (*.glb)"));
|
||||||
|
|
||||||
|
importModel(fileName);
|
||||||
|
}
|
||||||
|
});
|
||||||
topControlLayout->addWidget(importButton);
|
topControlLayout->addWidget(importButton);
|
||||||
|
|
||||||
exportButton = new QPushButton(QStringLiteral("Export..."));
|
exportButton = new QPushButton(QStringLiteral("Export..."));
|
||||||
|
@ -297,4 +313,75 @@ QString SingleGearView::getLoadedGearPath() const
|
||||||
return gearView->getLoadedGearPath();
|
return gearView->getLoadedGearPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SingleGearView::importModel(const QString &filename)
|
||||||
|
{
|
||||||
|
tinygltf::Model model;
|
||||||
|
|
||||||
|
std::string error, warning;
|
||||||
|
|
||||||
|
tinygltf::TinyGLTF loader;
|
||||||
|
if (!loader.LoadBinaryFromFile(&model, &error, &warning, filename.toStdString())) {
|
||||||
|
qInfo() << "Error when loading glTF model:" << error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!warning.empty()) {
|
||||||
|
qInfo() << "Warnings when loading glTF model:" << warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &mdl = gearView->part().getModel(0);
|
||||||
|
|
||||||
|
for (const auto &node : model.nodes) {
|
||||||
|
// Detect if it's a mesh node
|
||||||
|
if (node.mesh >= 0) {
|
||||||
|
qInfo() << "Importing" << node.name;
|
||||||
|
|
||||||
|
const QStringList parts = QString::fromStdString(node.name).split(QLatin1Char(' '));
|
||||||
|
const QString name = parts[0];
|
||||||
|
const QStringList lodPartNumber = parts[2].split(QLatin1Char('.'));
|
||||||
|
|
||||||
|
const int lodNumber = lodPartNumber[0].toInt();
|
||||||
|
const int partNumber = lodPartNumber[1].toInt();
|
||||||
|
|
||||||
|
qInfo() << "- LOD:" << lodNumber;
|
||||||
|
qInfo() << "- Part:" << partNumber;
|
||||||
|
|
||||||
|
auto &mesh = model.meshes[node.mesh];
|
||||||
|
auto &primitive = mesh.primitives[0];
|
||||||
|
|
||||||
|
// All of the accessors are mapped to the same buffer vertex view
|
||||||
|
const auto &vertexAccessor = model.accessors[primitive.attributes["POSITION"]];
|
||||||
|
const auto &vertexView = model.bufferViews[vertexAccessor.bufferView];
|
||||||
|
const auto &vertexBuffer = model.buffers[vertexView.buffer];
|
||||||
|
|
||||||
|
const auto &indexAccessor = model.accessors[primitive.indices];
|
||||||
|
const auto &indexView = model.bufferViews[indexAccessor.bufferView];
|
||||||
|
const auto &indexBuffer = model.buffers[indexView.buffer];
|
||||||
|
|
||||||
|
qInfo() << "- Importing mesh of" << vertexAccessor.count << "vertices and" << indexAccessor.count << "indices.";
|
||||||
|
|
||||||
|
auto vertexData = (glm::vec3 *)(&vertexBuffer.data.at(0) + vertexView.byteOffset);
|
||||||
|
|
||||||
|
std::vector<Vertex> newVertices;
|
||||||
|
for (int i = 0; i < vertexAccessor.count; i++) {
|
||||||
|
// Replace position data
|
||||||
|
auto vertex = mdl.model.lods[lodNumber].parts[partNumber].vertices[i];
|
||||||
|
vertex.position[0] = vertexData[i].x;
|
||||||
|
vertex.position[1] = vertexData[i].y;
|
||||||
|
vertex.position[2] = vertexData[i].z;
|
||||||
|
|
||||||
|
newVertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto indexData = (const uint16_t *)(&indexBuffer.data.at(0) + indexView.byteOffset);
|
||||||
|
|
||||||
|
physis_mdl_replace_vertices(&mdl.model, lodNumber, partNumber, vertexAccessor.count, newVertices.data(), indexAccessor.count, indexData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gearView->part().reloadModel(0);
|
||||||
|
|
||||||
|
qInfo() << "Successfully imported model!";
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_singlegearview.cpp"
|
#include "moc_singlegearview.cpp"
|
2
extern/libphysis
vendored
2
extern/libphysis
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 14fa0367302aa2b3ef9a8adba5cbe61f81a1f672
|
Subproject commit 66f64ee7ee510c2e2b30800e1f94b77a21bc0cf0
|
|
@ -199,6 +199,9 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
tinygltf::Model gltfModel;
|
tinygltf::Model gltfModel;
|
||||||
gltfModel.asset.generator = "Novus";
|
gltfModel.asset.generator = "Novus";
|
||||||
|
|
||||||
|
// TODO: just write the code better! dummy!!
|
||||||
|
gltfModel.nodes.reserve(1 + model.num_affected_bones + lod.num_parts);
|
||||||
|
|
||||||
auto &gltfSkeletonNode = gltfModel.nodes.emplace_back();
|
auto &gltfSkeletonNode = gltfModel.nodes.emplace_back();
|
||||||
gltfSkeletonNode.name = skeleton->root_bone->name;
|
gltfSkeletonNode.name = skeleton->root_bone->name;
|
||||||
|
|
||||||
|
@ -230,11 +233,19 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
|
|
||||||
auto &real_bone = skeleton->bones[real_bone_id];
|
auto &real_bone = skeleton->bones[real_bone_id];
|
||||||
if (real_bone.parent_bone != nullptr) {
|
if (real_bone.parent_bone != nullptr) {
|
||||||
|
bool found = false;
|
||||||
for (int k = 0; k < model.num_affected_bones; k++) {
|
for (int k = 0; k < model.num_affected_bones; k++) {
|
||||||
if (strcmp(model.affected_bone_names[k], real_bone.parent_bone->name) == 0) {
|
if (strcmp(model.affected_bone_names[k], real_bone.parent_bone->name) == 0) {
|
||||||
gltfModel.nodes[k + 1].children.push_back(i + 1); // +1 for the skeleton node taking up the first index
|
gltfModel.nodes[k + 1].children.push_back(i + 1); // +1 for the skeleton node taking up the first index
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the next closest bone that isn't a direct descendant
|
||||||
|
// of n_root, but won't have a parent anyway
|
||||||
|
if (!found) {
|
||||||
|
gltfSkeletonNode.children.push_back(i + 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
gltfSkeletonNode.children.push_back(i + 1);
|
gltfSkeletonNode.children.push_back(i + 1);
|
||||||
}
|
}
|
||||||
|
@ -280,13 +291,13 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < lod.num_parts; i++) {
|
for (int i = 0; i < lod.num_parts; i++) {
|
||||||
|
gltfSkeletonNode.children.push_back(gltfModel.nodes.size());
|
||||||
|
|
||||||
auto &gltfNode = gltfModel.nodes.emplace_back();
|
auto &gltfNode = gltfModel.nodes.emplace_back();
|
||||||
;
|
|
||||||
gltfNode.name = models[0].name.toStdString() + " Part " + std::to_string(i) + ".0";
|
gltfNode.name = models[0].name.toStdString() + " Part " + std::to_string(i) + ".0";
|
||||||
gltfNode.skin = 0;
|
gltfNode.skin = 0;
|
||||||
|
|
||||||
gltfSkeletonNode.children.push_back(gltfModel.nodes.size());
|
|
||||||
|
|
||||||
gltfNode.mesh = gltfModel.meshes.size();
|
gltfNode.mesh = gltfModel.meshes.size();
|
||||||
auto &gltfMesh = gltfModel.meshes.emplace_back();
|
auto &gltfMesh = gltfModel.meshes.emplace_back();
|
||||||
|
|
||||||
|
@ -295,9 +306,11 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
auto &gltfPrimitive = gltfMesh.primitives.emplace_back();
|
auto &gltfPrimitive = gltfMesh.primitives.emplace_back();
|
||||||
gltfPrimitive.attributes["POSITION"] = gltfModel.accessors.size();
|
gltfPrimitive.attributes["POSITION"] = gltfModel.accessors.size();
|
||||||
gltfPrimitive.attributes["TEXCOORD_0"] = gltfModel.accessors.size() + 1;
|
gltfPrimitive.attributes["TEXCOORD_0"] = gltfModel.accessors.size() + 1;
|
||||||
gltfPrimitive.attributes["NORMAL"] = gltfModel.accessors.size() + 2;
|
gltfPrimitive.attributes["TEXCOORD_1"] = gltfModel.accessors.size() + 2;
|
||||||
gltfPrimitive.attributes["WEIGHTS_0"] = gltfModel.accessors.size() + 3;
|
gltfPrimitive.attributes["NORMAL"] = gltfModel.accessors.size() + 3;
|
||||||
gltfPrimitive.attributes["JOINTS_0"] = gltfModel.accessors.size() + 4;
|
gltfPrimitive.attributes["COLOR_0"] = gltfModel.accessors.size() + 6;
|
||||||
|
gltfPrimitive.attributes["WEIGHTS_0"] = gltfModel.accessors.size() + 7;
|
||||||
|
gltfPrimitive.attributes["JOINTS_0"] = gltfModel.accessors.size() + 8;
|
||||||
gltfPrimitive.mode = TINYGLTF_MODE_TRIANGLES;
|
gltfPrimitive.mode = TINYGLTF_MODE_TRIANGLES;
|
||||||
|
|
||||||
// Vertices
|
// Vertices
|
||||||
|
@ -308,12 +321,19 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
positionAccessor.count = lod.parts[i].num_vertices;
|
positionAccessor.count = lod.parts[i].num_vertices;
|
||||||
positionAccessor.type = TINYGLTF_TYPE_VEC3;
|
positionAccessor.type = TINYGLTF_TYPE_VEC3;
|
||||||
|
|
||||||
auto &uvAccessor = gltfModel.accessors.emplace_back();
|
auto &uv0Accessor = gltfModel.accessors.emplace_back();
|
||||||
uvAccessor.bufferView = gltfModel.bufferViews.size();
|
uv0Accessor.bufferView = gltfModel.bufferViews.size();
|
||||||
uvAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
uv0Accessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||||
uvAccessor.count = lod.parts[i].num_vertices;
|
uv0Accessor.count = lod.parts[i].num_vertices;
|
||||||
uvAccessor.type = TINYGLTF_TYPE_VEC2;
|
uv0Accessor.type = TINYGLTF_TYPE_VEC2;
|
||||||
uvAccessor.byteOffset = offsetof(Vertex, uv);
|
uv0Accessor.byteOffset = offsetof(Vertex, uv0);
|
||||||
|
|
||||||
|
auto &uv1Accessor = gltfModel.accessors.emplace_back();
|
||||||
|
uv1Accessor.bufferView = gltfModel.bufferViews.size();
|
||||||
|
uv1Accessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||||
|
uv1Accessor.count = lod.parts[i].num_vertices;
|
||||||
|
uv1Accessor.type = TINYGLTF_TYPE_VEC2;
|
||||||
|
uv1Accessor.byteOffset = offsetof(Vertex, uv1);
|
||||||
|
|
||||||
auto &normalAccessor = gltfModel.accessors.emplace_back();
|
auto &normalAccessor = gltfModel.accessors.emplace_back();
|
||||||
normalAccessor.bufferView = gltfModel.bufferViews.size();
|
normalAccessor.bufferView = gltfModel.bufferViews.size();
|
||||||
|
@ -322,6 +342,27 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
normalAccessor.type = TINYGLTF_TYPE_VEC3;
|
normalAccessor.type = TINYGLTF_TYPE_VEC3;
|
||||||
normalAccessor.byteOffset = offsetof(Vertex, normal);
|
normalAccessor.byteOffset = offsetof(Vertex, normal);
|
||||||
|
|
||||||
|
auto &tangent1Accessor = gltfModel.accessors.emplace_back();
|
||||||
|
tangent1Accessor.bufferView = gltfModel.bufferViews.size();
|
||||||
|
tangent1Accessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||||
|
tangent1Accessor.count = lod.parts[i].num_vertices;
|
||||||
|
tangent1Accessor.type = TINYGLTF_TYPE_VEC4;
|
||||||
|
tangent1Accessor.byteOffset = offsetof(Vertex, tangent1);
|
||||||
|
|
||||||
|
auto &tangent2Accessor = gltfModel.accessors.emplace_back();
|
||||||
|
tangent2Accessor.bufferView = gltfModel.bufferViews.size();
|
||||||
|
tangent2Accessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||||
|
tangent2Accessor.count = lod.parts[i].num_vertices;
|
||||||
|
tangent2Accessor.type = TINYGLTF_TYPE_VEC4;
|
||||||
|
tangent2Accessor.byteOffset = offsetof(Vertex, tangent2);
|
||||||
|
|
||||||
|
auto &colorAccessor = gltfModel.accessors.emplace_back();
|
||||||
|
colorAccessor.bufferView = gltfModel.bufferViews.size();
|
||||||
|
colorAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||||
|
colorAccessor.count = lod.parts[i].num_vertices;
|
||||||
|
colorAccessor.type = TINYGLTF_TYPE_VEC4;
|
||||||
|
colorAccessor.byteOffset = offsetof(Vertex, color);
|
||||||
|
|
||||||
auto &boneWeightAccessor = gltfModel.accessors.emplace_back();
|
auto &boneWeightAccessor = gltfModel.accessors.emplace_back();
|
||||||
boneWeightAccessor.bufferView = gltfModel.bufferViews.size();
|
boneWeightAccessor.bufferView = gltfModel.bufferViews.size();
|
||||||
boneWeightAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
boneWeightAccessor.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
|
||||||
|
@ -331,7 +372,7 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
|
|
||||||
auto &boneIdAccessor = gltfModel.accessors.emplace_back();
|
auto &boneIdAccessor = gltfModel.accessors.emplace_back();
|
||||||
boneIdAccessor.bufferView = gltfModel.bufferViews.size();
|
boneIdAccessor.bufferView = gltfModel.bufferViews.size();
|
||||||
boneIdAccessor.componentType = TINYGLTF_COMPONENT_TYPE_BYTE;
|
boneIdAccessor.componentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||||
boneIdAccessor.count = lod.parts[i].num_vertices;
|
boneIdAccessor.count = lod.parts[i].num_vertices;
|
||||||
boneIdAccessor.type = TINYGLTF_TYPE_VEC4;
|
boneIdAccessor.type = TINYGLTF_TYPE_VEC4;
|
||||||
boneIdAccessor.byteOffset = offsetof(Vertex, bone_id);
|
boneIdAccessor.byteOffset = offsetof(Vertex, bone_id);
|
||||||
|
@ -378,6 +419,18 @@ void MDLPart::exportModel(const QString &fileName)
|
||||||
loader.WriteGltfSceneToFile(&gltfModel, fileName.toStdString(), true, true, false, true);
|
loader.WriteGltfSceneToFile(&gltfModel, fileName.toStdString(), true, true, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderModel &MDLPart::getModel(const int index)
|
||||||
|
{
|
||||||
|
return models[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MDLPart::reloadModel(const int index)
|
||||||
|
{
|
||||||
|
renderer->reloadModel(models[index], 0);
|
||||||
|
|
||||||
|
Q_EMIT modelChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void MDLPart::clear()
|
void MDLPart::clear()
|
||||||
{
|
{
|
||||||
models.clear();
|
models.clear();
|
||||||
|
|
|
@ -23,6 +23,8 @@ public:
|
||||||
explicit MDLPart(GameData *data, FileCache &cache);
|
explicit MDLPart(GameData *data, FileCache &cache);
|
||||||
|
|
||||||
void exportModel(const QString &fileName);
|
void exportModel(const QString &fileName);
|
||||||
|
RenderModel &getModel(int index);
|
||||||
|
void reloadModel(int index);
|
||||||
|
|
||||||
int lastX = -1;
|
int lastX = -1;
|
||||||
int lastY = -1;
|
int lastY = -1;
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
void resize(VkSurfaceKHR surface, int width, int height);
|
void resize(VkSurfaceKHR surface, int width, int height);
|
||||||
|
|
||||||
RenderModel addModel(const physis_MDL &model, int lod);
|
RenderModel addModel(const physis_MDL &model, int lod);
|
||||||
|
void reloadModel(RenderModel &model, int lod);
|
||||||
RenderTexture addTexture(uint32_t width, uint32_t height, const uint8_t *data, uint32_t data_size);
|
RenderTexture addTexture(uint32_t width, uint32_t height, const uint8_t *data, uint32_t data_size);
|
||||||
|
|
||||||
void render(std::vector<RenderModel> models);
|
void render(std::vector<RenderModel> models);
|
||||||
|
|
|
@ -4,10 +4,14 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec2 inUV0;
|
||||||
layout(location = 2) in vec2 inUV;
|
layout(location = 2) in vec2 inUV1;
|
||||||
layout(location = 3) in vec4 inBoneWeights;
|
layout(location = 3) in vec3 inNormal;
|
||||||
layout(location = 4) in uvec4 inBoneIds;
|
layout(location = 4) in uvec4 inTangent1;
|
||||||
|
layout(location = 5) in uvec4 inTangent2;
|
||||||
|
layout(location = 6) in vec4 inColor;
|
||||||
|
layout(location = 7) in vec4 inBoneWeights;
|
||||||
|
layout(location = 8) in uvec4 inBoneIds;
|
||||||
|
|
||||||
layout(location = 0) out vec3 outNormal;
|
layout(location = 0) out vec3 outNormal;
|
||||||
layout(location = 1) out vec3 outFragPos;
|
layout(location = 1) out vec3 outFragPos;
|
||||||
|
@ -42,5 +46,5 @@ void main() {
|
||||||
gl_Position = vp * bPos;
|
gl_Position = vp * bPos;
|
||||||
outNormal = bNor.xyz;
|
outNormal = bNor.xyz;
|
||||||
outFragPos = vec3(model * vec4(inPosition, 1.0));
|
outFragPos = vec3(model * vec4(inPosition, 1.0));
|
||||||
outUV = inUV;
|
outUV = inUV0;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -638,13 +638,22 @@ RenderModel Renderer::addModel(const physis_MDL &model, int lod)
|
||||||
RenderModel renderModel;
|
RenderModel renderModel;
|
||||||
renderModel.model = model;
|
renderModel.model = model;
|
||||||
|
|
||||||
if (lod < 0 || lod > model.num_lod)
|
reloadModel(renderModel, lod);
|
||||||
return {};
|
|
||||||
|
|
||||||
for (int i = 0; i < model.lods[lod].num_parts; i++) {
|
return renderModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::reloadModel(RenderModel &renderModel, int lod)
|
||||||
|
{
|
||||||
|
if (lod < 0 || lod > renderModel.model.num_lod)
|
||||||
|
return;
|
||||||
|
|
||||||
|
renderModel.parts.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < renderModel.model.lods[lod].num_parts; i++) {
|
||||||
RenderPart renderPart;
|
RenderPart renderPart;
|
||||||
|
|
||||||
const physis_Part part = model.lods[lod].parts[i];
|
const physis_Part part = renderModel.model.lods[lod].parts[i];
|
||||||
|
|
||||||
renderPart.materialIndex = part.material_index;
|
renderPart.materialIndex = part.material_index;
|
||||||
|
|
||||||
|
@ -702,8 +711,6 @@ RenderModel Renderer::addModel(const physis_MDL &model, int lod)
|
||||||
|
|
||||||
renderModel.boneInfoBuffer = buffer;
|
renderModel.boneInfoBuffer = buffer;
|
||||||
renderModel.boneInfoMemory = memory;
|
renderModel.boneInfoMemory = memory;
|
||||||
|
|
||||||
return renderModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::initPipeline()
|
void Renderer::initPipeline()
|
||||||
|
@ -729,27 +736,55 @@ void Renderer::initPipeline()
|
||||||
positionAttribute.format = VK_FORMAT_R32G32B32_SFLOAT;
|
positionAttribute.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
positionAttribute.offset = offsetof(Vertex, position);
|
positionAttribute.offset = offsetof(Vertex, position);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription uvAttribute = {};
|
VkVertexInputAttributeDescription uv0Attribute = {};
|
||||||
uvAttribute.format = VK_FORMAT_R32G32_SFLOAT;
|
uv0Attribute.format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
uvAttribute.location = 2;
|
uv0Attribute.location = 1;
|
||||||
uvAttribute.offset = offsetof(Vertex, uv);
|
uv0Attribute.offset = offsetof(Vertex, uv0);
|
||||||
|
|
||||||
|
VkVertexInputAttributeDescription uv1Attribute = {};
|
||||||
|
uv1Attribute.format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
uv1Attribute.location = 2;
|
||||||
|
uv1Attribute.offset = offsetof(Vertex, uv1);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription normalAttribute = {};
|
VkVertexInputAttributeDescription normalAttribute = {};
|
||||||
normalAttribute.format = VK_FORMAT_R32G32B32_SFLOAT;
|
normalAttribute.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
normalAttribute.location = 1;
|
normalAttribute.location = 3;
|
||||||
normalAttribute.offset = offsetof(Vertex, normal);
|
normalAttribute.offset = offsetof(Vertex, normal);
|
||||||
|
|
||||||
|
VkVertexInputAttributeDescription tangent1Attribute = {};
|
||||||
|
tangent1Attribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||||
|
tangent1Attribute.location = 4;
|
||||||
|
tangent1Attribute.offset = offsetof(Vertex, tangent1);
|
||||||
|
|
||||||
|
VkVertexInputAttributeDescription tangent2Attribute = {};
|
||||||
|
tangent2Attribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||||
|
tangent2Attribute.location = 5;
|
||||||
|
tangent2Attribute.offset = offsetof(Vertex, tangent2);
|
||||||
|
|
||||||
|
VkVertexInputAttributeDescription colorAttribute = {};
|
||||||
|
colorAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
|
colorAttribute.location = 6;
|
||||||
|
colorAttribute.offset = offsetof(Vertex, color);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription boneWeightAttribute = {};
|
VkVertexInputAttributeDescription boneWeightAttribute = {};
|
||||||
boneWeightAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
boneWeightAttribute.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
boneWeightAttribute.location = 3;
|
boneWeightAttribute.location = 7;
|
||||||
boneWeightAttribute.offset = offsetof(Vertex, bone_weight);
|
boneWeightAttribute.offset = offsetof(Vertex, bone_weight);
|
||||||
|
|
||||||
VkVertexInputAttributeDescription boneIdAttribute = {};
|
VkVertexInputAttributeDescription boneIdAttribute = {};
|
||||||
boneIdAttribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
boneIdAttribute.format = VK_FORMAT_R8G8B8A8_UINT;
|
||||||
boneIdAttribute.location = 4;
|
boneIdAttribute.location = 8;
|
||||||
boneIdAttribute.offset = offsetof(Vertex, bone_id);
|
boneIdAttribute.offset = offsetof(Vertex, bone_id);
|
||||||
|
|
||||||
const std::array attributes = {positionAttribute, normalAttribute, uvAttribute, boneWeightAttribute, boneIdAttribute};
|
const std::array attributes = {positionAttribute,
|
||||||
|
uv0Attribute,
|
||||||
|
uv1Attribute,
|
||||||
|
normalAttribute,
|
||||||
|
tangent1Attribute,
|
||||||
|
tangent2Attribute,
|
||||||
|
colorAttribute,
|
||||||
|
boneWeightAttribute,
|
||||||
|
boneIdAttribute};
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
|
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
|
||||||
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
|
Loading…
Add table
Reference in a new issue