1
Fork 0
mirror of https://github.com/redstrate/Novus.git synced 2025-05-16 13:27:45 +00:00

Begin loading BG objects from the LGB

It "works" but it's too slow to actually all of them and
takes way too much memory.
This commit is contained in:
Joshua Goins 2025-05-14 21:06:41 -04:00
parent 58425c1ae0
commit 75a094134a
16 changed files with 182 additions and 104 deletions

View file

@ -12,6 +12,7 @@ class AppState : public QObject
public: public:
explicit AppState(QObject *parent = nullptr); explicit AppState(QObject *parent = nullptr);
QString basePath;
std::vector<std::pair<QString, physis_LayerGroup>> lgbFiles; std::vector<std::pair<QString, physis_LayerGroup>> lgbFiles;
Q_SIGNALS: Q_SIGNALS:

View file

@ -27,6 +27,7 @@ public Q_SLOTS:
private: private:
MDLPart *mdlPart = nullptr; MDLPart *mdlPart = nullptr;
GameData *data; GameData *m_data;
FileCache &cache; FileCache &m_cache;
AppState *m_appState;
}; };

View file

@ -74,14 +74,8 @@ void MainWindow::setupActions()
void MainWindow::openMap(const QString &basePath) void MainWindow::openMap(const QString &basePath)
{ {
QString base2Path = basePath.left(basePath.lastIndexOf(QStringLiteral("/level/"))); QString base2Path = basePath.left(basePath.lastIndexOf(QStringLiteral("/level/")));
QString bgPath = QStringLiteral("bg/%1/bgplate/").arg(base2Path);
std::string bgPathStd = bgPath.toStdString() + "terrain.tera"; m_appState->basePath = basePath;
auto tera_buffer = physis_gamedata_extract_file(data, bgPathStd.c_str());
auto tera = physis_parse_tera(tera_buffer);
mapView->addTerrain(bgPath, tera);
setWindowTitle(basePath); setWindowTitle(basePath);

View file

@ -6,13 +6,15 @@
#include <QThreadPool> #include <QThreadPool>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "appstate.h"
#include "filecache.h" #include "filecache.h"
#include "objectpass.h" #include "objectpass.h"
MapView::MapView(GameData *data, FileCache &cache, AppState *appState, QWidget *parent) MapView::MapView(GameData *data, FileCache &cache, AppState *appState, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, data(data) , m_data(data)
, cache(cache) , m_cache(cache)
, m_appState(appState)
{ {
mdlPart = new MDLPart(data, cache); mdlPart = new MDLPart(data, cache);
mdlPart->enableFreemode(); mdlPart->enableFreemode();
@ -24,6 +26,71 @@ MapView::MapView(GameData *data, FileCache &cache, AppState *appState, QWidget *
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(mdlPart); layout->addWidget(mdlPart);
setLayout(layout); setLayout(layout);
connect(appState, &AppState::mapLoaded, this, [this] {
mdlPart->clear();
QString base2Path = m_appState->basePath.left(m_appState->basePath.lastIndexOf(QStringLiteral("/level/")));
QString bgPath = QStringLiteral("bg/%1/bgplate/").arg(base2Path);
std::string bgPathStd = bgPath.toStdString() + "terrain.tera";
auto tera_buffer = physis_gamedata_extract_file(m_data, bgPathStd.c_str());
auto tera = physis_parse_tera(tera_buffer);
addTerrain(bgPath, tera);
// add bg models
for (const auto &[name, lgb] : m_appState->lgbFiles) {
// only load the bg models for now
if (name != QStringLiteral("bg")) {
continue;
}
for (int i = 0; i < lgb.num_chunks; i++) {
const auto chunk = lgb.chunks[i];
for (int j = 0; j < chunk.num_layers; j++) {
const auto layer = chunk.layers[j];
for (int z = 0; z < layer.num_objects; z++) {
const auto object = layer.objects[z];
switch (object.data.tag) {
case physis_LayerEntry::Tag::BG: {
std::string assetPath = object.data.bg._0.asset_path;
if (!assetPath.empty()) {
auto plateMdlFile = physis_gamedata_extract_file(m_data, assetPath.c_str());
if (plateMdlFile.size == 0) {
continue;
}
auto plateMdl = physis_mdl_parse(plateMdlFile);
if (plateMdl.p_ptr != nullptr) {
std::vector<physis_Material> materials;
for (uint32_t j = 0; j < plateMdl.num_material_names; j++) {
const char *material_name = plateMdl.material_names[j];
auto mat = physis_material_parse(m_cache.lookupFile(QLatin1String(material_name)));
materials.push_back(mat);
}
mdlPart->addModel(
plateMdl,
false,
glm::vec3(object.transform.translation[0], object.transform.translation[1], object.transform.translation[2]),
QString::fromStdString(assetPath),
materials,
0);
numLoadedBgModels++;
}
}
} break;
}
}
}
}
}
});
} }
MDLPart &MapView::part() const MDLPart &MapView::part() const
@ -33,20 +100,18 @@ MDLPart &MapView::part() const
void MapView::addTerrain(QString basePath, physis_Terrain terrain) void MapView::addTerrain(QString basePath, physis_Terrain terrain)
{ {
mdlPart->clear();
for (int i = 0; i < terrain.num_plates; i++) { for (int i = 0; i < terrain.num_plates; i++) {
QString mdlPath = QStringLiteral("%1%2").arg(basePath, QString::fromStdString(terrain.plates[i].filename)); QString mdlPath = QStringLiteral("%1%2").arg(basePath, QString::fromStdString(terrain.plates[i].filename));
std::string mdlPathStd = mdlPath.toStdString(); std::string mdlPathStd = mdlPath.toStdString();
auto plateMdlFile = physis_gamedata_extract_file(data, mdlPathStd.c_str()); auto plateMdlFile = physis_gamedata_extract_file(m_data, mdlPathStd.c_str());
auto plateMdl = physis_mdl_parse(plateMdlFile); auto plateMdl = physis_mdl_parse(plateMdlFile);
if (plateMdl.p_ptr != nullptr) { if (plateMdl.p_ptr != nullptr) {
std::vector<physis_Material> materials; std::vector<physis_Material> materials;
for (uint32_t j = 0; j < plateMdl.num_material_names; j++) { for (uint32_t j = 0; j < plateMdl.num_material_names; j++) {
const char *material_name = plateMdl.material_names[j]; const char *material_name = plateMdl.material_names[j];
auto mat = physis_material_parse(cache.lookupFile(QLatin1String(material_name))); auto mat = physis_material_parse(m_cache.lookupFile(QLatin1String(material_name)));
materials.push_back(mat); materials.push_back(mat);
} }

2
extern/libphysis vendored

@ -1 +1 @@
Subproject commit f0b53912ef8ef9361aaede623ae0a38d1bd833bb Subproject commit 5946c315e39f6909b71787bc344ba0d879479d73

View file

@ -50,25 +50,25 @@ MDLPart::MDLPart(GameData *data, FileCache &cache, QWidget *parent)
void MDLPart::exportModel(const QString &fileName) void MDLPart::exportModel(const QString &fileName)
{ {
auto &model = models[0]; auto &model = vkWindow->models[0];
::exportModel(model.name, model.model, *skeleton, boneData, fileName); ::exportModel(model.name, model.sourceObject->model, *skeleton, boneData, fileName);
} }
DrawObject &MDLPart::getModel(const int index) DrawObject &MDLPart::getModel(const int index)
{ {
return models[index]; return *vkWindow->models[index].sourceObject;
} }
void MDLPart::reloadModel(const int index) void MDLPart::reloadModel(const int index)
{ {
renderer->reloadDrawObject(models[index], 0); renderer->reloadDrawObject(*vkWindow->models[index].sourceObject, 0);
Q_EMIT modelChanged(); Q_EMIT modelChanged();
} }
void MDLPart::clear() void MDLPart::clear()
{ {
models.clear(); vkWindow->models.clear();
Q_EMIT modelChanged(); Q_EMIT modelChanged();
} }
@ -82,24 +82,27 @@ void MDLPart::addModel(physis_MDL mdl,
uint16_t fromBodyId, uint16_t fromBodyId,
uint16_t toBodyId) uint16_t toBodyId)
{ {
qDebug() << "Adding model to MDLPart"; DrawObject *model;
if (vkWindow->sourceModels.contains(name)) {
model = vkWindow->sourceModels[name];
} else {
model = renderer->addDrawObject(mdl, lod);
model->from_body_id = fromBodyId;
model->to_body_id = toBodyId;
model->skinned = skinned;
auto model = renderer->addDrawObject(mdl, lod); std::transform(materials.begin(), materials.end(), std::back_inserter(model->materials), [this](const physis_Material &mat) {
model.name = name; return createOrCacheMaterial(mat);
model.from_body_id = fromBodyId; });
model.to_body_id = toBodyId;
model.position = position;
model.skinned = skinned;
std::transform(materials.begin(), materials.end(), std::back_inserter(model.materials), [this](const physis_Material &mat) { if (materials.empty()) {
return createOrCacheMaterial(mat); model->materials.push_back(createOrCacheMaterial(physis_Material{}));
}); }
if (materials.empty()) { vkWindow->sourceModels[name] = model;
model.materials.push_back(createOrCacheMaterial(physis_Material{}));
} }
models.push_back(model); vkWindow->models.push_back(DrawObjectInstance{name, model, position});
Q_EMIT modelChanged(); Q_EMIT modelChanged();
} }
@ -125,8 +128,6 @@ void MDLPart::clearSkeleton()
void MDLPart::reloadRenderer() void MDLPart::reloadRenderer()
{ {
reloadBoneData(); reloadBoneData();
vkWindow->models = models;
} }
void MDLPart::enableFreemode() void MDLPart::enableFreemode()
@ -166,31 +167,32 @@ void MDLPart::reloadBoneData()
// update data // update data
calculateBone(*skeleton, *skeleton->root_bone, nullptr); calculateBone(*skeleton, *skeleton->root_bone, nullptr);
for (auto &model : models) { // TODO: this applies to all instances
for (auto &[_, model] : vkWindow->sourceModels) {
// we want to map the actual affected bones to bone ids // we want to map the actual affected bones to bone ids
std::map<int, int> boneMapping; std::map<int, int> boneMapping;
for (uint32_t i = 0; i < model.model.num_affected_bones; i++) { for (uint32_t i = 0; i < model->model.num_affected_bones; i++) {
for (uint32_t k = 0; k < skeleton->num_bones; k++) { for (uint32_t k = 0; k < skeleton->num_bones; k++) {
if (std::string_view{skeleton->bones[k].name} == std::string_view{model.model.affected_bone_names[i]}) { if (std::string_view{skeleton->bones[k].name} == std::string_view{model->model.affected_bone_names[i]}) {
boneMapping[i] = k; boneMapping[i] = k;
} }
} }
} }
std::vector<glm::mat4> deformBones(model.model.num_affected_bones); std::vector<glm::mat4> deformBones(model->model.num_affected_bones);
for (uint32_t i = 0; i < model.model.num_affected_bones; i++) { for (uint32_t i = 0; i < model->model.num_affected_bones; i++) {
deformBones[i] = glm::mat4(1.0f); deformBones[i] = glm::mat4(1.0f);
} }
// get deform matrices // get deform matrices
if (enableRacialDeform) { if (enableRacialDeform) {
auto deform = physis_pbd_get_deform_matrix(pbd, model.from_body_id, model.to_body_id); auto deform = physis_pbd_get_deform_matrix(pbd, model->from_body_id, model->to_body_id);
if (deform.num_bones != 0) { if (deform.num_bones != 0) {
for (int i = 0; i < deform.num_bones; i++) { for (int i = 0; i < deform.num_bones; i++) {
auto deformBone = deform.bones[i]; auto deformBone = deform.bones[i];
for (uint32_t k = 0; k < model.model.num_affected_bones; k++) { for (uint32_t k = 0; k < model->model.num_affected_bones; k++) {
if (std::string_view{model.model.affected_bone_names[k]} == std::string_view{deformBone.name}) { if (std::string_view{model->model.affected_bone_names[k]} == std::string_view{deformBone.name}) {
deformBones[k] = deformBones[k] =
glm::rowMajor4(glm::vec4{deformBone.deform[0], deformBone.deform[1], deformBone.deform[2], deformBone.deform[3]}, glm::rowMajor4(glm::vec4{deformBone.deform[0], deformBone.deform[1], deformBone.deform[2], deformBone.deform[3]},
glm::vec4{deformBone.deform[4], deformBone.deform[5], deformBone.deform[6], deformBone.deform[7]}, glm::vec4{deformBone.deform[4], deformBone.deform[5], deformBone.deform[6], deformBone.deform[7]},
@ -202,9 +204,9 @@ void MDLPart::reloadBoneData()
} }
} }
for (uint32_t i = 0; i < model.model.num_affected_bones; i++) { for (uint32_t i = 0; i < model->model.num_affected_bones; i++) {
const int originalBoneId = boneMapping[i]; const int originalBoneId = boneMapping[i];
model.boneData[i] = deformBones[i] * boneData[originalBoneId].localTransform * boneData[originalBoneId].inversePose; model->boneData[i] = deformBones[i] * boneData[originalBoneId].localTransform * boneData[originalBoneId].inversePose;
} }
} }
} }
@ -397,12 +399,14 @@ void MDLPart::calculateBone(physis_Skeleton &skeleton, physis_Bone &bone, const
void MDLPart::removeModel(const physis_MDL &mdl) void MDLPart::removeModel(const physis_MDL &mdl)
{ {
models.erase(std::remove_if(models.begin(), // TODO: restore this functionality
models.end(), qWarning() << "MDLPart::removeModel needs to be reimplemented!";
/*vkWindow->models.erase(std::remove_if(vkWindow->models.begin(),
vkWindow->models.end(),
[mdl](const DrawObject &other) { [mdl](const DrawObject &other) {
return mdl.p_ptr == other.model.p_ptr; return mdl.p_ptr == other.model.p_ptr;
}), }),
models.end()); vkWindow->models.end());*/
Q_EMIT modelChanged(); Q_EMIT modelChanged();
} }
@ -420,7 +424,7 @@ bool MDLPart::wireframe() const
int MDLPart::numModels() const int MDLPart::numModels() const
{ {
return models.size(); return vkWindow->models.size();
} }
RenderManager *MDLPart::manager() const RenderManager *MDLPart::manager() const

View file

@ -102,7 +102,6 @@ private:
GameData *data = nullptr; GameData *data = nullptr;
FileCache &cache; FileCache &cache;
std::vector<DrawObject> models;
std::unordered_map<uint64_t, RenderMaterial> renderMaterialCache; std::unordered_map<uint64_t, RenderMaterial> renderMaterialCache;
RenderManager *renderer = nullptr; RenderManager *renderer = nullptr;

View file

@ -20,7 +20,8 @@ public:
void render(); void render();
std::vector<DrawObject> models; std::vector<DrawObjectInstance> models;
std::unordered_map<QString, DrawObject *> sourceModels;
bool freeMode = false; bool freeMode = false;
private: private:

View file

@ -14,7 +14,7 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
class Renderer; class Renderer;
struct DrawObject; struct DrawObjectInstance;
struct Camera; struct Camera;
struct Texture; struct Texture;
struct Scene; struct Scene;
@ -31,7 +31,7 @@ public:
virtual void resize() = 0; virtual void resize() = 0;
/// Render a frame into @p commandBuffer. @p currentFrame is the same value as SwapChain::currentFrame for convenience. /// Render a frame into @p commandBuffer. @p currentFrame is the same value as SwapChain::currentFrame for convenience.
virtual void render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObject> &models) = 0; virtual void render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObjectInstance> &models) = 0;
/// The final composite texture that is drawn into with render() /// The final composite texture that is drawn into with render()
virtual Texture &getCompositeTexture() = 0; virtual Texture &getCompositeTexture() = 0;

View file

@ -34,13 +34,10 @@ struct RenderMaterial {
}; };
struct DrawObject { struct DrawObject {
QString name;
physis_MDL model; physis_MDL model;
std::vector<RenderPart> parts; std::vector<RenderPart> parts;
std::array<glm::mat4, 768> boneData; // JOINT_MATRIX_SIZE_DAWNTRAIL std::array<glm::mat4, 768> boneData; // JOINT_MATRIX_SIZE_DAWNTRAIL
std::vector<RenderMaterial> materials; std::vector<RenderMaterial> materials;
glm::vec3 position;
bool skinned = false; bool skinned = false;
uint16_t from_body_id = 101; uint16_t from_body_id = 101;
@ -48,3 +45,9 @@ struct DrawObject {
Buffer boneInfoBuffer; Buffer boneInfoBuffer;
}; };
struct DrawObjectInstance {
QString name;
DrawObject *sourceObject = nullptr;
glm::vec3 position;
};

View file

@ -31,7 +31,7 @@ public:
void resize() override; void resize() override;
void render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObject> &models) override; void render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObjectInstance> &models) override;
Texture &getCompositeTexture() override; Texture &getCompositeTexture() override;

View file

@ -33,11 +33,11 @@ public:
void destroySwapchain(); void destroySwapchain();
DrawObject addDrawObject(const physis_MDL &model, int lod); DrawObject *addDrawObject(const physis_MDL &model, int lod);
void reloadDrawObject(DrawObject &model, uint32_t lod); void reloadDrawObject(DrawObject &model, uint32_t lod);
Texture addGameTexture(VkFormat format, physis_Texture gameTexture); Texture addGameTexture(VkFormat format, physis_Texture gameTexture);
void render(const std::vector<DrawObject> &models); void render(const std::vector<DrawObjectInstance> &models);
VkRenderPass presentationRenderPass() const; VkRenderPass presentationRenderPass() const;

View file

@ -30,7 +30,7 @@ public:
void resize() override; void resize() override;
void render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObject> &models) override; void render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObjectInstance> &models) override;
Texture &getCompositeTexture() override; Texture &getCompositeTexture() override;

View file

@ -255,7 +255,7 @@ GameRenderer::GameRenderer(Device &device, GameData *data)
createImageResources(); createImageResources();
} }
void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObject> &models) void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObjectInstance> &models)
{ {
Q_UNUSED(scene) Q_UNUSED(scene)
@ -299,29 +299,29 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &
const int jointMatrixSize = m_dawntrailMode ? JOINT_MATRIX_SIZE_DAWNTRAIL : JOINT_MATRIX_SIZE_ARR; const int jointMatrixSize = m_dawntrailMode ? JOINT_MATRIX_SIZE_DAWNTRAIL : JOINT_MATRIX_SIZE_ARR;
const size_t bufferSize = sizeof(glm::mat3x4) * jointMatrixSize; const size_t bufferSize = sizeof(glm::mat3x4) * jointMatrixSize;
void *mapped_data = nullptr; void *mapped_data = nullptr;
vkMapMemory(m_device.device, model.boneInfoBuffer.memory, 0, bufferSize, 0, &mapped_data); vkMapMemory(m_device.device, model.sourceObject->boneInfoBuffer.memory, 0, bufferSize, 0, &mapped_data);
std::vector<glm::mat3x4> newBoneData(model.boneData.size()); std::vector<glm::mat3x4> newBoneData(model.sourceObject->boneData.size());
for (int i = 0; i < jointMatrixSize; i++) { for (int i = 0; i < jointMatrixSize; i++) {
newBoneData[i] = glm::transpose(model.boneData[i]); newBoneData[i] = glm::transpose(model.sourceObject->boneData[i]);
} }
memcpy(mapped_data, newBoneData.data(), bufferSize); memcpy(mapped_data, newBoneData.data(), bufferSize);
VkMappedMemoryRange range = {}; VkMappedMemoryRange range = {};
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.memory = model.boneInfoBuffer.memory; range.memory = model.sourceObject->boneInfoBuffer.memory;
range.size = bufferSize; range.size = bufferSize;
vkFlushMappedMemoryRanges(m_device.device, 1, &range); vkFlushMappedMemoryRanges(m_device.device, 1, &range);
vkUnmapMemory(m_device.device, model.boneInfoBuffer.memory); vkUnmapMemory(m_device.device, model.sourceObject->boneInfoBuffer.memory);
} }
for (const auto &part : model.parts) { for (const auto &part : model.sourceObject->parts) {
RenderMaterial renderMaterial = model.materials[part.materialIndex]; RenderMaterial renderMaterial = model.sourceObject->materials[part.materialIndex];
if (static_cast<size_t>(part.materialIndex + 1) > model.materials.size()) { if (static_cast<size_t>(part.materialIndex + 1) > model.sourceObject->materials.size()) {
renderMaterial = model.materials[0]; // TODO: better fallback renderMaterial = model.sourceObject->materials[0]; // TODO: better fallback
} }
if (renderMaterial.shaderPackage.p_ptr == nullptr) { if (renderMaterial.shaderPackage.p_ptr == nullptr) {
@ -341,7 +341,7 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &
bool found = false; bool found = false;
if (id == physis_shpk_crc("TransformView")) { if (id == physis_shpk_crc("TransformView")) {
if (model.skinned) { if (model.sourceObject->skinned) {
sceneKeys.push_back(physis_shpk_crc("TransformViewSkin")); sceneKeys.push_back(physis_shpk_crc("TransformViewSkin"));
} else { } else {
sceneKeys.push_back(physis_shpk_crc("TransformViewRigid")); sceneKeys.push_back(physis_shpk_crc("TransformViewRigid"));
@ -400,9 +400,14 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &
physis_Shader vertexShader = renderMaterial.shaderPackage.vertex_shaders[vertexShaderIndice]; physis_Shader vertexShader = renderMaterial.shaderPackage.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = renderMaterial.shaderPackage.pixel_shaders[pixelShaderIndice]; physis_Shader pixelShader = renderMaterial.shaderPackage.pixel_shaders[pixelShaderIndice];
auto &pipeline = auto &pipeline = bindPipeline(commandBuffer,
bindPipeline(commandBuffer, pass, vertexShader, pixelShader, renderMaterial.mat.shpk_name, &model.model, &part.originalPart); pass,
bindDescriptorSets(commandBuffer, pipeline, &model, &renderMaterial, pass); vertexShader,
pixelShader,
renderMaterial.mat.shpk_name,
&model.sourceObject->model,
&part.originalPart);
bindDescriptorSets(commandBuffer, pipeline, model.sourceObject, &renderMaterial, pass);
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
for (int j = 0; j < part.originalPart.num_streams; j++) { for (int j = 0; j < part.originalPart.num_streams; j++) {
@ -541,11 +546,11 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &
beginPass(commandBuffer, pass); beginPass(commandBuffer, pass);
for (auto &model : models) { for (auto &model : models) {
for (const auto &part : model.parts) { for (const auto &part : model.sourceObject->parts) {
RenderMaterial renderMaterial = model.materials[part.materialIndex]; RenderMaterial renderMaterial = model.sourceObject->materials[part.materialIndex];
if (static_cast<size_t>(part.materialIndex + 1) > model.materials.size()) { if (static_cast<size_t>(part.materialIndex + 1) > model.sourceObject->materials.size()) {
renderMaterial = model.materials[0]; // TODO: better fallback renderMaterial = model.sourceObject->materials[0]; // TODO: better fallback
} }
if (renderMaterial.shaderPackage.p_ptr == nullptr) { if (renderMaterial.shaderPackage.p_ptr == nullptr) {
@ -564,7 +569,7 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &
bool found = false; bool found = false;
if (id == physis_shpk_crc("TransformView")) { if (id == physis_shpk_crc("TransformView")) {
if (model.skinned) { if (model.sourceObject->skinned) {
sceneKeys.push_back(physis_shpk_crc("TransformViewSkin")); sceneKeys.push_back(physis_shpk_crc("TransformViewSkin"));
} else { } else {
sceneKeys.push_back(physis_shpk_crc("TransformViewRigid")); sceneKeys.push_back(physis_shpk_crc("TransformViewRigid"));
@ -623,9 +628,14 @@ void GameRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &
physis_Shader vertexShader = renderMaterial.shaderPackage.vertex_shaders[vertexShaderIndice]; physis_Shader vertexShader = renderMaterial.shaderPackage.vertex_shaders[vertexShaderIndice];
physis_Shader pixelShader = renderMaterial.shaderPackage.pixel_shaders[pixelShaderIndice]; physis_Shader pixelShader = renderMaterial.shaderPackage.pixel_shaders[pixelShaderIndice];
auto &pipeline = auto &pipeline = bindPipeline(commandBuffer,
bindPipeline(commandBuffer, pass, vertexShader, pixelShader, renderMaterial.mat.shpk_name, &model.model, &part.originalPart); pass,
bindDescriptorSets(commandBuffer, pipeline, &model, &renderMaterial, pass); vertexShader,
pixelShader,
renderMaterial.mat.shpk_name,
&model.sourceObject->model,
&part.originalPart);
bindDescriptorSets(commandBuffer, pipeline, model.sourceObject, &renderMaterial, pass);
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
for (int j = 0; j < part.originalPart.num_streams; j++) { for (int j = 0; j < part.originalPart.num_streams; j++) {

View file

@ -397,7 +397,7 @@ void RenderManager::destroySwapchain()
} }
} }
void RenderManager::render(const std::vector<DrawObject> &models) void RenderManager::render(const std::vector<DrawObjectInstance> &models)
{ {
vkWaitForFences(m_device->device, vkWaitForFences(m_device->device,
1, 1,
@ -509,12 +509,12 @@ VkRenderPass RenderManager::presentationRenderPass() const
return m_renderPass; return m_renderPass;
} }
DrawObject RenderManager::addDrawObject(const physis_MDL &model, int lod) DrawObject *RenderManager::addDrawObject(const physis_MDL &model, int lod)
{ {
DrawObject DrawObject; auto DrawObject = new ::DrawObject();
DrawObject.model = model; DrawObject->model = model;
reloadDrawObject(DrawObject, lod); reloadDrawObject(*DrawObject, lod);
return DrawObject; return DrawObject;
} }

View file

@ -49,7 +49,7 @@ void SimpleRenderer::resize()
m_device.nameObject(VK_OBJECT_TYPE_FRAMEBUFFER, reinterpret_cast<uint64_t>(m_framebuffer), "simple renderer framebuffer"); m_device.nameObject(VK_OBJECT_TYPE_FRAMEBUFFER, reinterpret_cast<uint64_t>(m_framebuffer), "simple renderer framebuffer");
} }
void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObject> &models) void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene &scene, const std::vector<DrawObjectInstance> &models)
{ {
Q_UNUSED(scene) Q_UNUSED(scene)
@ -72,7 +72,7 @@ void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
for (const auto &model : models) { for (const auto &model : models) {
if (model.skinned) { if (model.sourceObject->skinned) {
if (m_wireframe) { if (m_wireframe) {
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_skinnedPipelineWireframe); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_skinnedPipelineWireframe);
} else { } else {
@ -90,33 +90,33 @@ void SimpleRenderer::render(VkCommandBuffer commandBuffer, Camera &camera, Scene
{ {
const size_t bufferSize = sizeof(glm::mat4) * 128; const size_t bufferSize = sizeof(glm::mat4) * 128;
void *mapped_data = nullptr; void *mapped_data = nullptr;
vkMapMemory(m_device.device, model.boneInfoBuffer.memory, 0, bufferSize, 0, &mapped_data); vkMapMemory(m_device.device, model.sourceObject->boneInfoBuffer.memory, 0, bufferSize, 0, &mapped_data);
memcpy(mapped_data, model.boneData.data(), bufferSize); memcpy(mapped_data, model.sourceObject->boneData.data(), bufferSize);
VkMappedMemoryRange range = {}; VkMappedMemoryRange range = {};
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.memory = model.boneInfoBuffer.memory; range.memory = model.sourceObject->boneInfoBuffer.memory;
range.size = bufferSize; range.size = bufferSize;
vkFlushMappedMemoryRanges(m_device.device, 1, &range); vkFlushMappedMemoryRanges(m_device.device, 1, &range);
vkUnmapMemory(m_device.device, model.boneInfoBuffer.memory); vkUnmapMemory(m_device.device, model.sourceObject->boneInfoBuffer.memory);
} }
for (const auto &part : model.parts) { for (const auto &part : model.sourceObject->parts) {
RenderMaterial defaultMaterial = {}; RenderMaterial defaultMaterial = {};
RenderMaterial *material = nullptr; RenderMaterial *material = nullptr;
if (static_cast<size_t>(part.materialIndex) >= model.materials.size()) { if (static_cast<size_t>(part.materialIndex) >= model.sourceObject->materials.size()) {
material = &defaultMaterial; material = &defaultMaterial;
} else { } else {
material = const_cast<RenderMaterial *>(&model.materials[part.materialIndex]); material = const_cast<RenderMaterial *>(&model.sourceObject->materials[part.materialIndex]);
} }
const auto h = hash(model, *material); const auto h = hash(*model.sourceObject, *material);
if (!cachedDescriptors.count(h)) { if (!cachedDescriptors.count(h)) {
if (auto descriptor = createDescriptorFor(model, *material); descriptor != VK_NULL_HANDLE) { if (auto descriptor = createDescriptorFor(*model.sourceObject, *material); descriptor != VK_NULL_HANDLE) {
cachedDescriptors[h] = descriptor; cachedDescriptors[h] = descriptor;
} else { } else {
continue; continue;