Graphics/Model: Add model loader
This commit is contained in:
parent
201ac025e2
commit
2bdd6f9351
|
|
@ -13,6 +13,7 @@
|
|||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Graphics/MaterialInstance.hpp>
|
||||
#include <Nazara/Graphics/MaterialPassRegistry.hpp>
|
||||
#include <Nazara/Graphics/Model.hpp>
|
||||
#include <Nazara/Graphics/PipelinePassList.hpp>
|
||||
#include <Nazara/Graphics/TextureSamplerCache.hpp>
|
||||
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||
|
|
@ -55,6 +56,8 @@ namespace Nz
|
|||
inline const MaterialInstanceLoader& GetMaterialInstanceLoader() const;
|
||||
inline MaterialLoader& GetMaterialLoader();
|
||||
inline const MaterialLoader& GetMaterialLoader() const;
|
||||
inline ModelLoader& GetModelLoader();
|
||||
inline const ModelLoader& GetModelLoader() const;
|
||||
inline PipelinePassListLoader& GetPipelinePassListLoader();
|
||||
inline const PipelinePassListLoader& GetPipelinePassListLoader() const;
|
||||
inline PixelFormat GetPreferredDepthFormat() const;
|
||||
|
|
@ -117,6 +120,7 @@ namespace Nz
|
|||
MaterialInstanceLoader m_materialInstanceLoader;
|
||||
MaterialLoader m_materialLoader;
|
||||
MaterialPassRegistry m_materialPassRegistry;
|
||||
ModelLoader m_modelLoader;
|
||||
PipelinePassListLoader m_pipelinePassListLoader;
|
||||
PixelFormat m_preferredDepthFormat;
|
||||
PixelFormat m_preferredDepthStencilFormat;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,16 @@ namespace Nz
|
|||
return m_materialLoader;
|
||||
}
|
||||
|
||||
inline ModelLoader& Graphics::GetModelLoader()
|
||||
{
|
||||
return m_modelLoader;
|
||||
}
|
||||
|
||||
inline const ModelLoader& Graphics::GetModelLoader() const
|
||||
{
|
||||
return m_modelLoader;
|
||||
}
|
||||
|
||||
inline PipelinePassListLoader& Graphics::GetPipelinePassListLoader()
|
||||
{
|
||||
return m_pipelinePassListLoader;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@
|
|||
#define NAZARA_GRAPHICS_MODEL_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/ObjectLibrary.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceLoader.hpp>
|
||||
#include <Nazara/Core/ResourceManager.hpp>
|
||||
#include <Nazara/Core/ResourceParameters.hpp>
|
||||
#include <Nazara/Core/ResourceSaver.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Graphics/GraphicalMesh.hpp>
|
||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||
|
|
@ -18,11 +24,26 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
class Material;
|
||||
struct NAZARA_GRAPHICS_API ModelParams : ResourceParameters
|
||||
{
|
||||
bool loadMaterials = true;
|
||||
MeshParams mesh;
|
||||
|
||||
class NAZARA_GRAPHICS_API Model : public InstancedRenderable
|
||||
bool IsValid() const;
|
||||
};
|
||||
|
||||
class Model;
|
||||
|
||||
using ModelLibrary = ObjectLibrary<Model>;
|
||||
using ModelLoader = ResourceLoader<Model, ModelParams>;
|
||||
using ModelManager = ResourceManager<Model, ModelParams>;
|
||||
using ModelSaver = ResourceSaver<Model, ModelParams>;
|
||||
|
||||
class NAZARA_GRAPHICS_API Model : public InstancedRenderable, public Resource
|
||||
{
|
||||
public:
|
||||
using Params = ModelParams;
|
||||
|
||||
Model(std::shared_ptr<GraphicalMesh> graphicalMesh);
|
||||
Model(const Model&) = delete;
|
||||
Model(Model&&) noexcept = default;
|
||||
|
|
@ -43,6 +64,10 @@ namespace Nz
|
|||
Model& operator=(const Model&) = delete;
|
||||
Model& operator=(Model&&) noexcept = default;
|
||||
|
||||
static std::shared_ptr<Model> LoadFromFile(const std::filesystem::path& filePath, const ModelParams& params = ModelParams());
|
||||
static std::shared_ptr<Model> LoadFromMemory(const void* data, std::size_t size, const ModelParams& params = ModelParams());
|
||||
static std::shared_ptr<Model> LoadFromStream(Stream& stream, const ModelParams& params = ModelParams());
|
||||
|
||||
private:
|
||||
struct SubMeshData
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/Formats/ModelMeshLoader.hpp>
|
||||
#include <Nazara/Graphics/GraphicalMesh.hpp>
|
||||
#include <Nazara/Graphics/MaterialInstance.hpp>
|
||||
#include <Nazara/Graphics/Model.hpp>
|
||||
#include <Nazara/Utility/Mesh.hpp>
|
||||
#include <Nazara/Utility/Utility.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz::Loaders
|
||||
{
|
||||
ModelLoader::Entry GetModelLoader_Mesh()
|
||||
{
|
||||
ModelLoader::Entry loaderEntry;
|
||||
loaderEntry.extensionSupport = [](std::string_view extension)
|
||||
{
|
||||
return Utility::Instance()->GetMeshLoader().IsExtensionSupported(extension);
|
||||
};
|
||||
|
||||
loaderEntry.streamLoader = [](Stream& stream, const ModelParams& parameters) -> Result<std::shared_ptr<Model>, ResourceLoadingError>
|
||||
{
|
||||
std::shared_ptr<Mesh> mesh = Mesh::LoadFromStream(stream, parameters.mesh);
|
||||
if (!mesh)
|
||||
return Err(ResourceLoadingError::Unrecognized);
|
||||
|
||||
std::shared_ptr<GraphicalMesh> gfxMesh = GraphicalMesh::BuildFromMesh(*mesh);
|
||||
if (!gfxMesh)
|
||||
return Err(ResourceLoadingError::Internal);
|
||||
|
||||
std::shared_ptr<Model> model = std::make_shared<Model>(std::move(gfxMesh));
|
||||
if (parameters.loadMaterials)
|
||||
{
|
||||
for (std::size_t matIndex = 0; matIndex < model->GetMaterialCount(); ++matIndex)
|
||||
{
|
||||
if (std::shared_ptr<MaterialInstance> matInstance = MaterialInstance::Build(mesh->GetMaterialData(matIndex)))
|
||||
model->SetMaterial(matIndex, std::move(matInstance));
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
};
|
||||
|
||||
loaderEntry.parameterFilter = [](const ModelParams& parameters)
|
||||
{
|
||||
if (auto result = parameters.custom.GetBooleanParameter("SkipNativeMeshLoader"); result.GetValueOr(false))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return loaderEntry;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_GRAPHICS_FORMATS_MODELMESHLOADER_HPP
|
||||
#define NAZARA_GRAPHICS_FORMATS_MODELMESHLOADER_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Model.hpp>
|
||||
|
||||
namespace Nz::Loaders
|
||||
{
|
||||
ModelLoader::Entry GetModelLoader_Mesh();
|
||||
}
|
||||
|
||||
#endif // NAZARA_GRAPHICS_FORMATS_MODELMESHLOADER_HPP
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
#include <Nazara/Graphics/PipelinePassList.hpp>
|
||||
#include <Nazara/Graphics/PostProcessPipelinePass.hpp>
|
||||
#include <Nazara/Graphics/PredefinedMaterials.hpp>
|
||||
#include <Nazara/Graphics/Formats/ModelMeshLoader.hpp>
|
||||
#include <Nazara/Graphics/Formats/PipelinePassListLoader.hpp>
|
||||
#include <Nazara/Graphics/Formats/TextureLoader.hpp>
|
||||
#include <Nazara/Utility/Font.hpp>
|
||||
|
|
@ -164,6 +165,7 @@ namespace Nz
|
|||
Font::SetDefaultAtlas(std::make_shared<GuillotineTextureAtlas>(*m_renderDevice));
|
||||
|
||||
m_materialInstanceLoader.RegisterLoader(Loaders::GetMaterialInstanceLoader_Texture()); // texture to material loader
|
||||
m_modelLoader.RegisterLoader(Loaders::GetModelLoader_Mesh());
|
||||
m_pipelinePassListLoader.RegisterLoader(Loaders::GetPipelinePassListLoader()); // texture to material loader
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
bool ModelParams::IsValid() const
|
||||
{
|
||||
return mesh.IsValid();
|
||||
}
|
||||
|
||||
Model::Model(std::shared_ptr<GraphicalMesh> graphicalMesh) :
|
||||
m_graphicalMesh(std::move(graphicalMesh))
|
||||
{
|
||||
|
|
@ -94,4 +99,28 @@ namespace Nz
|
|||
{
|
||||
return m_graphicalMesh->GetVertexBuffer(subMeshIndex);
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> Model::LoadFromFile(const std::filesystem::path& filePath, const ModelParams& params)
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
NazaraAssert(graphics, "Graphics module has not been initialized");
|
||||
|
||||
return graphics->GetModelLoader().LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> Model::LoadFromMemory(const void* data, std::size_t size, const ModelParams& params)
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
NazaraAssert(graphics, "Graphics module has not been initialized");
|
||||
|
||||
return graphics->GetModelLoader().LoadFromMemory(data, size, params);
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> Model::LoadFromStream(Stream& stream, const ModelParams& params)
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
NazaraAssert(graphics, "Graphics module has not been initialized");
|
||||
|
||||
return graphics->GetModelLoader().LoadFromStream(stream, params);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,52 +28,29 @@ int main()
|
|||
Nz::Application<Nz::Graphics> app(rendererConfig);
|
||||
auto& windowingApp = app.AddComponent<Nz::AppWindowingComponent>();
|
||||
|
||||
Nz::MeshParams meshParams;
|
||||
meshParams.center = true;
|
||||
meshParams.vertexRotation = Nz::EulerAnglesf(0.f, -90.f, 0.f);
|
||||
meshParams.vertexScale = Nz::Vector3f(0.002f);
|
||||
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV);
|
||||
|
||||
std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice();
|
||||
|
||||
std::string windowTitle = "Graphics Test";
|
||||
Nz::Window& window = windowingApp.CreateWindow(Nz::VideoMode(1280, 720), windowTitle);
|
||||
Nz::WindowSwapchain windowSwapchain(device, window);
|
||||
|
||||
std::shared_ptr<Nz::Mesh> spaceshipMesh = Nz::Mesh::LoadFromFile(resourceDir / "Spaceship/spaceship.obj", meshParams);
|
||||
if (!spaceshipMesh)
|
||||
Nz::ModelParams modelParams;
|
||||
modelParams.mesh.center = true;
|
||||
modelParams.mesh.vertexRotation = Nz::EulerAnglesf(0.f, -90.f, 0.f);
|
||||
modelParams.mesh.vertexScale = Nz::Vector3f(0.002f);
|
||||
modelParams.mesh.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV);
|
||||
|
||||
std::shared_ptr<Nz::Model> spaceshipModel = Nz::Model::LoadFromFile(resourceDir / "Spaceship/spaceship.obj", modelParams);
|
||||
if (!spaceshipModel)
|
||||
{
|
||||
NazaraError("failed to load model");
|
||||
return __LINE__;
|
||||
}
|
||||
|
||||
std::shared_ptr<Nz::GraphicalMesh> gfxMesh = Nz::GraphicalMesh::BuildFromMesh(*spaceshipMesh);
|
||||
|
||||
// Texture
|
||||
std::shared_ptr<Nz::Image> diffuseImage = Nz::Image::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png");
|
||||
if (!diffuseImage || !diffuseImage->Convert(Nz::PixelFormat::RGBA8_SRGB))
|
||||
{
|
||||
NazaraError("failed to load image");
|
||||
return __LINE__;
|
||||
}
|
||||
|
||||
Nz::TextureParams texParams;
|
||||
texParams.renderDevice = device;
|
||||
texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB;
|
||||
|
||||
std::shared_ptr<Nz::Texture> diffuseTexture = Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams);
|
||||
|
||||
std::shared_ptr<Nz::MaterialInstance> materialInstance = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Basic);
|
||||
materialInstance->SetTextureProperty(0, diffuseTexture);
|
||||
materialInstance->SetValueProperty(0, Nz::Color::White());
|
||||
|
||||
std::shared_ptr<Nz::MaterialInstance> materialInstance = spaceshipModel->GetMaterial(0);
|
||||
std::shared_ptr<Nz::MaterialInstance> materialInstance2 = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Basic);
|
||||
materialInstance2->SetValueProperty(0, Nz::Color::Green());
|
||||
|
||||
Nz::Model model(std::move(gfxMesh));
|
||||
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
|
||||
model.SetMaterial(i, materialInstance);
|
||||
|
||||
Nz::Vector2ui windowSize = window.GetSize();
|
||||
|
||||
Nz::Camera camera(std::make_shared<Nz::RenderWindow>(windowSwapchain));
|
||||
|
|
@ -97,8 +74,8 @@ int main()
|
|||
[[maybe_unused]] std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0);
|
||||
std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance);
|
||||
std::size_t worldInstanceIndex2 = framePipeline.RegisterWorldInstance(modelInstance2);
|
||||
framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox);
|
||||
framePipeline.RegisterRenderable(worldInstanceIndex2, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox);
|
||||
framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, spaceshipModel.get(), 0xFFFFFFFF, scissorBox);
|
||||
framePipeline.RegisterRenderable(worldInstanceIndex2, Nz::FramePipeline::NoSkeletonInstance, spaceshipModel.get(), 0xFFFFFFFF, scissorBox);
|
||||
|
||||
std::unique_ptr<Nz::SpotLight> light = std::make_unique<Nz::SpotLight>();
|
||||
light->UpdateInnerAngle(Nz::DegreeAnglef(15.f));
|
||||
|
|
@ -128,13 +105,13 @@ int main()
|
|||
case Nz::WindowEventType::KeyPressed:
|
||||
if (event.key.virtualKey == Nz::Keyboard::VKey::A)
|
||||
{
|
||||
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
|
||||
model.SetMaterial(i, materialInstance);
|
||||
for (std::size_t i = 0; i < spaceshipModel->GetSubMeshCount(); ++i)
|
||||
spaceshipModel->SetMaterial(i, materialInstance);
|
||||
}
|
||||
else if (event.key.virtualKey == Nz::Keyboard::VKey::B)
|
||||
{
|
||||
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
|
||||
model.SetMaterial(i, materialInstance2);
|
||||
for (std::size_t i = 0; i < spaceshipModel->GetSubMeshCount(); ++i)
|
||||
spaceshipModel->SetMaterial(i, materialInstance2);
|
||||
}
|
||||
else if (event.key.virtualKey == Nz::Keyboard::VKey::Space)
|
||||
{
|
||||
|
|
@ -216,7 +193,7 @@ int main()
|
|||
|
||||
for (const Nz::WorldInstancePtr& worldInstance : { modelInstance, modelInstance2 })
|
||||
{
|
||||
Nz::Boxf aabb = model.GetAABB();
|
||||
Nz::Boxf aabb = spaceshipModel->GetAABB();
|
||||
aabb.Transform(worldInstance->GetWorldMatrix());
|
||||
|
||||
framePipeline.GetDebugDrawer().DrawBox(aabb, Nz::Color::Green());
|
||||
|
|
|
|||
Loading…
Reference in New Issue