fix: restore backpack material import output
This commit is contained in:
@@ -138,6 +138,7 @@ inline DXGI_FORMAT ToD3D12(Format format) {
|
||||
case Format::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
|
||||
case Format::R8G8_UNorm: return DXGI_FORMAT_R8G8_UNORM;
|
||||
case Format::R8G8B8A8_UNorm: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case Format::R8G8B8A8_SRGB: return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
case Format::R16_UInt: return DXGI_FORMAT_R16_UINT;
|
||||
case Format::R16G16B16A16_Float: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case Format::R32G32B32A32_Float: return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
@@ -167,6 +168,7 @@ inline Format FromD3D12(DXGI_FORMAT format) {
|
||||
case DXGI_FORMAT_R8_UNORM: return Format::R8_UNorm;
|
||||
case DXGI_FORMAT_R8G8_UNORM: return Format::R8G8_UNorm;
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM: return Format::R8G8B8A8_UNorm;
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return Format::R8G8B8A8_SRGB;
|
||||
case DXGI_FORMAT_R16_UINT: return Format::R16_UInt;
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT: return Format::R16G16B16A16_Float;
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT: return Format::R32G32B32A32_Float;
|
||||
|
||||
@@ -132,6 +132,9 @@ inline void ToOpenGLFormat(OpenGLFormat fmt, GLint& internalFormat, GLenum& glFo
|
||||
case OpenGLFormat::RGBA8:
|
||||
internalFormat = GL_RGBA8; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case OpenGLFormat::RGBA8_SRGB:
|
||||
internalFormat = GL_SRGB8_ALPHA8; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case OpenGLFormat::RGBA16F:
|
||||
internalFormat = GL_RGBA16F; glFormat = GL_RGBA; glType = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
@@ -27,7 +27,8 @@ enum class OpenGLFormat {
|
||||
Depth24Stencil8,
|
||||
Depth32F,
|
||||
CompressedDXT1,
|
||||
CompressedDXT5
|
||||
CompressedDXT5,
|
||||
RGBA8_SRGB
|
||||
};
|
||||
|
||||
enum class OpenGLInternalFormat {
|
||||
@@ -40,7 +41,8 @@ enum class OpenGLInternalFormat {
|
||||
Depth24Stencil8 = 38,
|
||||
Depth32F = 31,
|
||||
CompressedDXT1 = 21,
|
||||
CompressedDXT5 = 22
|
||||
CompressedDXT5 = 22,
|
||||
RGBA8_SRGB = 39
|
||||
};
|
||||
|
||||
class OpenGLTexture : public RHITexture {
|
||||
|
||||
@@ -317,7 +317,8 @@ enum class Format : uint32_t {
|
||||
R32G32B32A32_UInt,
|
||||
R32_UInt,
|
||||
R32G32_Float,
|
||||
R32G32B32_Float
|
||||
R32G32B32_Float,
|
||||
R8G8B8A8_SRGB
|
||||
};
|
||||
|
||||
enum class ResourceStates : uint32_t {
|
||||
|
||||
@@ -77,6 +77,8 @@ inline VkFormat ToVulkanFormat(Format format) {
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case Format::R8G8B8A8_UNorm:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case Format::R8G8B8A8_SRGB:
|
||||
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||
case Format::R16_UInt:
|
||||
return VK_FORMAT_R16_UINT;
|
||||
case Format::R16_Float:
|
||||
@@ -107,6 +109,7 @@ inline uint32_t GetFormatSize(Format format) {
|
||||
case Format::R8G8_UNorm:
|
||||
return 2;
|
||||
case Format::R8G8B8A8_UNorm:
|
||||
case Format::R8G8B8A8_SRGB:
|
||||
return 4;
|
||||
case Format::R16_UInt:
|
||||
case Format::R16_Float:
|
||||
@@ -136,6 +139,9 @@ inline Format ToRHIFormat(VkFormat format) {
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
return Format::R8G8B8A8_UNorm;
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
return Format::R8G8B8A8_SRGB;
|
||||
case VK_FORMAT_R16_UINT:
|
||||
return Format::R16_UInt;
|
||||
case VK_FORMAT_R16_SFLOAT:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Core/Asset/ImportSettings.h>
|
||||
#include <XCEngine/Core/IO/IResourceLoader.h>
|
||||
#include "Texture.h"
|
||||
|
||||
@@ -15,7 +16,11 @@ public:
|
||||
Containers::Array<Containers::String> GetSupportedExtensions() const override;
|
||||
bool CanLoad(const Containers::String& path) const override;
|
||||
LoadResult Load(const Containers::String& path, const ImportSettings* settings = nullptr) override;
|
||||
LoadResult LoadFromMemory(const Containers::String& path, const void* data, size_t dataSize) const;
|
||||
LoadResult LoadFromMemory(
|
||||
const Containers::String& path,
|
||||
const void* data,
|
||||
size_t dataSize,
|
||||
const ImportSettings* settings = nullptr) const;
|
||||
ImportSettings* GetDefaultSettings() const override;
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ uint32_t GetFormatBytesPerPixel(Format format) {
|
||||
case Format::R8G8_UNorm:
|
||||
return 2;
|
||||
case Format::R8G8B8A8_UNorm:
|
||||
case Format::R8G8B8A8_SRGB:
|
||||
return 4;
|
||||
case Format::R16_Float:
|
||||
return 2;
|
||||
|
||||
@@ -145,6 +145,8 @@ OpenGLFormat ToOpenGLTextureFormat(Format format) {
|
||||
return OpenGLFormat::RG32F;
|
||||
case Format::R8G8B8A8_UNorm:
|
||||
return OpenGLFormat::RGBA8;
|
||||
case Format::R8G8B8A8_SRGB:
|
||||
return OpenGLFormat::RGBA8_SRGB;
|
||||
case Format::R16G16B16A16_Float:
|
||||
return OpenGLFormat::RGBA16F;
|
||||
case Format::R32G32B32A32_Float:
|
||||
|
||||
@@ -10,8 +10,9 @@ namespace {
|
||||
RHI::Format ToRHITextureFormat(Resources::TextureFormat format) {
|
||||
switch (format) {
|
||||
case Resources::TextureFormat::RGBA8_UNORM:
|
||||
case Resources::TextureFormat::RGBA8_SRGB:
|
||||
return RHI::Format::R8G8B8A8_UNorm;
|
||||
case Resources::TextureFormat::RGBA8_SRGB:
|
||||
return RHI::Format::R8G8B8A8_SRGB;
|
||||
default:
|
||||
return RHI::Format::Unknown;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <XCEngine/Resources/Material/Material.h>
|
||||
#include <XCEngine/Resources/Texture/Texture.h>
|
||||
#include <XCEngine/Resources/Texture/TextureLoader.h>
|
||||
#include <XCEngine/Resources/Texture/TextureImportSettings.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/Core/Math/Matrix4.h>
|
||||
#include <assimp/Importer.hpp>
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <assimp/postprocess.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
@@ -131,6 +133,22 @@ Containers::String BuildSubResourcePath(const Containers::String& sourcePath,
|
||||
return Containers::String(path.c_str());
|
||||
}
|
||||
|
||||
TextureImportSettings BuildMaterialTextureImportSettings(const char* propertyName) {
|
||||
TextureImportSettings settings;
|
||||
(void)propertyName;
|
||||
settings.SetSRGB(false);
|
||||
settings.SetTargetFormat(TextureFormat::RGBA8_UNORM);
|
||||
return settings;
|
||||
}
|
||||
|
||||
std::string BuildTextureCacheKey(const std::string& pathKey, const TextureImportSettings& settings) {
|
||||
std::string cacheKey = pathKey;
|
||||
cacheKey += settings.GetSRGB() ? "|srgb" : "|linear";
|
||||
cacheKey += "|fmt=";
|
||||
cacheKey += std::to_string(static_cast<int>(settings.GetTargetFormat()));
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
Containers::String GetResourceNameFromPath(const Containers::String& path) {
|
||||
const std::filesystem::path filePath(path.CStr());
|
||||
const std::string fileName = filePath.filename().string();
|
||||
@@ -243,8 +261,9 @@ Texture* CreateRawTexture(const Containers::String& texturePath,
|
||||
|
||||
Texture* LoadEmbeddedTexture(const aiTexture& embeddedTexture,
|
||||
const Containers::String& texturePath,
|
||||
const TextureImportSettings& settings,
|
||||
TextureImportContext& context) {
|
||||
const std::string cacheKey(texturePath.CStr());
|
||||
const std::string cacheKey = BuildTextureCacheKey(texturePath.CStr(), settings);
|
||||
const auto cacheIt = context.textureCache.find(cacheKey);
|
||||
if (cacheIt != context.textureCache.end()) {
|
||||
return cacheIt->second;
|
||||
@@ -254,7 +273,8 @@ Texture* LoadEmbeddedTexture(const aiTexture& embeddedTexture,
|
||||
if (embeddedTexture.mHeight == 0) {
|
||||
LoadResult result = context.textureLoader.LoadFromMemory(texturePath,
|
||||
embeddedTexture.pcData,
|
||||
embeddedTexture.mWidth);
|
||||
embeddedTexture.mWidth,
|
||||
&settings);
|
||||
if (result) {
|
||||
texture = static_cast<Texture*>(result.resource);
|
||||
}
|
||||
@@ -272,7 +292,11 @@ Texture* LoadEmbeddedTexture(const aiTexture& embeddedTexture,
|
||||
}
|
||||
|
||||
texture = CreateRawTexture(texturePath,
|
||||
TextureFormat::RGBA8_UNORM,
|
||||
settings.GetTargetFormat() != TextureFormat::Unknown
|
||||
? settings.GetTargetFormat()
|
||||
: (settings.GetSRGB()
|
||||
? TextureFormat::RGBA8_SRGB
|
||||
: TextureFormat::RGBA8_UNORM),
|
||||
embeddedTexture.mWidth,
|
||||
embeddedTexture.mHeight,
|
||||
rgbaPixels.data(),
|
||||
@@ -288,25 +312,30 @@ Texture* LoadEmbeddedTexture(const aiTexture& embeddedTexture,
|
||||
}
|
||||
|
||||
Texture* LoadExternalTexture(const std::filesystem::path& textureFilePath,
|
||||
const TextureImportSettings& settings,
|
||||
TextureImportContext& context) {
|
||||
const std::string normalizedPath = textureFilePath.lexically_normal().string();
|
||||
const auto cacheIt = context.textureCache.find(normalizedPath);
|
||||
const std::string cacheKey = BuildTextureCacheKey(normalizedPath, settings);
|
||||
const auto cacheIt = context.textureCache.find(cacheKey);
|
||||
if (cacheIt != context.textureCache.end()) {
|
||||
return cacheIt->second;
|
||||
}
|
||||
|
||||
LoadResult result = context.textureLoader.Load(Containers::String(normalizedPath.c_str()));
|
||||
LoadResult result = context.textureLoader.Load(Containers::String(normalizedPath.c_str()), &settings);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Texture* texture = static_cast<Texture*>(result.resource);
|
||||
context.textureCache.emplace(normalizedPath, texture);
|
||||
context.textureCache.emplace(cacheKey, texture);
|
||||
context.ownedTextures.push_back(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
Texture* LoadTextureReference(const aiString& textureReference, TextureImportContext& context) {
|
||||
Texture* LoadTextureReference(
|
||||
const aiString& textureReference,
|
||||
const TextureImportSettings& settings,
|
||||
TextureImportContext& context) {
|
||||
if (textureReference.length == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -327,7 +356,7 @@ Texture* LoadTextureReference(const aiString& textureReference, TextureImportCon
|
||||
"embedded_texture",
|
||||
embeddedTextureIndex,
|
||||
Containers::String(extension.c_str()));
|
||||
return LoadEmbeddedTexture(*embeddedTexture, texturePath, context);
|
||||
return LoadEmbeddedTexture(*embeddedTexture, texturePath, settings, context);
|
||||
}
|
||||
|
||||
std::filesystem::path resolvedPath(textureReference.C_Str());
|
||||
@@ -335,11 +364,12 @@ Texture* LoadTextureReference(const aiString& textureReference, TextureImportCon
|
||||
resolvedPath = context.sourceDirectory / resolvedPath;
|
||||
}
|
||||
|
||||
return LoadExternalTexture(resolvedPath, context);
|
||||
return LoadExternalTexture(resolvedPath, settings, context);
|
||||
}
|
||||
|
||||
Texture* LoadMaterialTexture(const aiMaterial& assimpMaterial,
|
||||
std::initializer_list<aiTextureType> textureTypes,
|
||||
const TextureImportSettings& settings,
|
||||
TextureImportContext& context) {
|
||||
for (aiTextureType textureType : textureTypes) {
|
||||
if (assimpMaterial.GetTextureCount(textureType) == 0) {
|
||||
@@ -351,7 +381,7 @@ Texture* LoadMaterialTexture(const aiMaterial& assimpMaterial,
|
||||
continue;
|
||||
}
|
||||
|
||||
Texture* texture = LoadTextureReference(texturePath, context);
|
||||
Texture* texture = LoadTextureReference(texturePath, settings, context);
|
||||
if (texture != nullptr) {
|
||||
return texture;
|
||||
}
|
||||
@@ -360,12 +390,27 @@ Texture* LoadMaterialTexture(const aiMaterial& assimpMaterial,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HasMaterialTexture(
|
||||
const aiMaterial& assimpMaterial,
|
||||
std::initializer_list<aiTextureType> textureTypes) {
|
||||
for (aiTextureType textureType : textureTypes) {
|
||||
if (assimpMaterial.GetTextureCount(textureType) > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImportMaterialProperties(const aiMaterial& assimpMaterial, Material& material) {
|
||||
float opacity = 1.0f;
|
||||
if (assimpMaterial.Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
|
||||
material.SetFloat("opacity", opacity);
|
||||
}
|
||||
|
||||
const bool hasBaseColorTexture =
|
||||
HasMaterialTexture(assimpMaterial, { aiTextureType_BASE_COLOR, aiTextureType_DIFFUSE });
|
||||
|
||||
aiColor4D baseColor;
|
||||
if (assimpMaterial.Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR, baseColor) == AI_SUCCESS) {
|
||||
material.SetFloat4("baseColor",
|
||||
@@ -374,7 +419,9 @@ void ImportMaterialProperties(const aiMaterial& assimpMaterial, Material& materi
|
||||
aiColor3D diffuseColor;
|
||||
if (assimpMaterial.Get(AI_MATKEY_COLOR_DIFFUSE, diffuseColor) == AI_SUCCESS) {
|
||||
material.SetFloat4("baseColor",
|
||||
Math::Vector4(diffuseColor.r, diffuseColor.g, diffuseColor.b, opacity));
|
||||
hasBaseColorTexture
|
||||
? Math::Vector4(1.0f, 1.0f, 1.0f, opacity)
|
||||
: Math::Vector4(diffuseColor.r, diffuseColor.g, diffuseColor.b, opacity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +463,8 @@ void ImportMaterialTextures(const aiMaterial& assimpMaterial,
|
||||
TextureImportContext& context) {
|
||||
auto assignTexture = [&](const char* propertyName,
|
||||
std::initializer_list<aiTextureType> textureTypes) {
|
||||
Texture* texture = LoadMaterialTexture(assimpMaterial, textureTypes, context);
|
||||
const TextureImportSettings settings = BuildMaterialTextureImportSettings(propertyName);
|
||||
Texture* texture = LoadMaterialTexture(assimpMaterial, textureTypes, settings, context);
|
||||
if (texture != nullptr) {
|
||||
material.SetTexture(Containers::String(propertyName), ResourceHandle<Texture>(texture));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <XCEngine/Core/Asset/ArtifactFormats.h>
|
||||
#include <XCEngine/Resources/BuiltinResources.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/Resources/Texture/TextureImportSettings.h>
|
||||
#include <stb_image.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
@@ -50,6 +51,25 @@ LoadResult CreateTextureResource(const Containers::String& path,
|
||||
return LoadResult(texture);
|
||||
}
|
||||
|
||||
TextureFormat ResolveDecodedTextureFormat(const ImportSettings* settings, bool isHdrTexture) {
|
||||
if (isHdrTexture) {
|
||||
return TextureFormat::RGBA32_FLOAT;
|
||||
}
|
||||
|
||||
const auto* textureSettings = dynamic_cast<const TextureImportSettings*>(settings);
|
||||
if (textureSettings == nullptr) {
|
||||
return TextureFormat::RGBA8_UNORM;
|
||||
}
|
||||
|
||||
if (textureSettings->GetTargetFormat() != TextureFormat::Unknown) {
|
||||
return textureSettings->GetTargetFormat();
|
||||
}
|
||||
|
||||
return textureSettings->GetSRGB()
|
||||
? TextureFormat::RGBA8_SRGB
|
||||
: TextureFormat::RGBA8_UNORM;
|
||||
}
|
||||
|
||||
LoadResult LoadTextureArtifact(const Containers::String& path) {
|
||||
std::filesystem::path resolvedPath(path.CStr());
|
||||
if (!resolvedPath.is_absolute() && !std::filesystem::exists(resolvedPath)) {
|
||||
@@ -124,8 +144,6 @@ bool TextureLoader::CanLoad(const Containers::String& path) const {
|
||||
}
|
||||
|
||||
LoadResult TextureLoader::Load(const Containers::String& path, const ImportSettings* settings) {
|
||||
(void)settings;
|
||||
|
||||
if (IsBuiltinTexturePath(path)) {
|
||||
return CreateBuiltinTextureResource(path);
|
||||
}
|
||||
@@ -149,10 +167,14 @@ LoadResult TextureLoader::Load(const Containers::String& path, const ImportSetti
|
||||
return LoadResult(Containers::String("Failed to read file: ") + path);
|
||||
}
|
||||
|
||||
return LoadFromMemory(path, fileData.Data(), fileData.Size());
|
||||
return LoadFromMemory(path, fileData.Data(), fileData.Size(), settings);
|
||||
}
|
||||
|
||||
LoadResult TextureLoader::LoadFromMemory(const Containers::String& path, const void* data, size_t dataSize) const {
|
||||
LoadResult TextureLoader::LoadFromMemory(
|
||||
const Containers::String& path,
|
||||
const void* data,
|
||||
size_t dataSize,
|
||||
const ImportSettings* settings) const {
|
||||
if (data == nullptr || dataSize == 0) {
|
||||
return LoadResult(Containers::String("Texture data is empty: ") + path);
|
||||
}
|
||||
@@ -180,7 +202,7 @@ LoadResult TextureLoader::LoadFromMemory(const Containers::String& path, const v
|
||||
4u *
|
||||
sizeof(float);
|
||||
LoadResult result = CreateTextureResource(path,
|
||||
TextureFormat::RGBA32_FLOAT,
|
||||
ResolveDecodedTextureFormat(settings, true),
|
||||
static_cast<Core::uint32>(width),
|
||||
static_cast<Core::uint32>(height),
|
||||
pixels,
|
||||
@@ -204,7 +226,7 @@ LoadResult TextureLoader::LoadFromMemory(const Containers::String& path, const v
|
||||
4u *
|
||||
sizeof(stbi_uc);
|
||||
LoadResult result = CreateTextureResource(path,
|
||||
TextureFormat::RGBA8_UNORM,
|
||||
ResolveDecodedTextureFormat(settings, false),
|
||||
static_cast<Core::uint32>(width),
|
||||
static_cast<Core::uint32>(height),
|
||||
pixels,
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
using namespace XCEngine::Resources;
|
||||
@@ -51,6 +52,23 @@ bool PumpAsyncLoadsUntilIdle(ResourceManager& manager,
|
||||
return !manager.IsAsyncLoading();
|
||||
}
|
||||
|
||||
void FlipLastByte(const std::filesystem::path& path) {
|
||||
std::ifstream input(path, std::ios::binary);
|
||||
ASSERT_TRUE(input.is_open());
|
||||
|
||||
std::vector<char> bytes(
|
||||
(std::istreambuf_iterator<char>(input)),
|
||||
std::istreambuf_iterator<char>());
|
||||
ASSERT_FALSE(bytes.empty());
|
||||
|
||||
bytes.back() ^= 0x01;
|
||||
|
||||
std::ofstream output(path, std::ios::binary | std::ios::trunc);
|
||||
ASSERT_TRUE(output.is_open());
|
||||
output.write(bytes.data(), static_cast<std::streamsize>(bytes.size()));
|
||||
ASSERT_TRUE(static_cast<bool>(output));
|
||||
}
|
||||
|
||||
TEST(MeshLoader, GetResourceType) {
|
||||
MeshLoader loader;
|
||||
EXPECT_EQ(loader.GetResourceType(), ResourceType::Mesh);
|
||||
@@ -172,6 +190,7 @@ TEST(MeshLoader, ImportsMaterialTexturesFromObj) {
|
||||
EXPECT_EQ(diffuseTexture->GetWidth(), 2u);
|
||||
EXPECT_EQ(diffuseTexture->GetHeight(), 2u);
|
||||
EXPECT_EQ(diffuseTexture->GetPixelDataSize(), 16u);
|
||||
EXPECT_EQ(diffuseTexture->GetFormat(), TextureFormat::RGBA8_UNORM);
|
||||
EXPECT_EQ(mesh->GetTextures().Size(), 1u);
|
||||
|
||||
delete mesh;
|
||||
@@ -291,6 +310,64 @@ TEST(MeshLoader, AssetDatabaseCreatesModelArtifactAndReusesItWithoutReimport) {
|
||||
fs::remove_all(projectRoot);
|
||||
}
|
||||
|
||||
TEST(MeshLoader, AssetDatabaseReimportsModelWhenDependencyChanges) {
|
||||
namespace fs = std::filesystem;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
const fs::path projectRoot = fs::temp_directory_path() / "xc_mesh_dependency_reimport_test";
|
||||
const fs::path assetsDir = projectRoot / "Assets";
|
||||
|
||||
fs::remove_all(projectRoot);
|
||||
fs::create_directories(assetsDir);
|
||||
fs::copy_file(GetMeshFixturePath("textured_triangle.obj"),
|
||||
assetsDir / "textured_triangle.obj",
|
||||
fs::copy_options::overwrite_existing);
|
||||
fs::copy_file(GetMeshFixturePath("textured_triangle.mtl"),
|
||||
assetsDir / "textured_triangle.mtl",
|
||||
fs::copy_options::overwrite_existing);
|
||||
fs::copy_file(GetMeshFixturePath("checker.bmp"),
|
||||
assetsDir / "checker.bmp",
|
||||
fs::copy_options::overwrite_existing);
|
||||
|
||||
AssetDatabase database;
|
||||
database.Initialize(projectRoot.string().c_str());
|
||||
|
||||
AssetDatabase::ResolvedAsset firstResolve;
|
||||
ASSERT_TRUE(database.EnsureArtifact("Assets/textured_triangle.obj", ResourceType::Mesh, firstResolve));
|
||||
ASSERT_TRUE(firstResolve.artifactReady);
|
||||
const String firstArtifactPath = firstResolve.artifactMainPath;
|
||||
database.Shutdown();
|
||||
|
||||
std::this_thread::sleep_for(50ms);
|
||||
{
|
||||
std::ofstream mtlOutput(assetsDir / "textured_triangle.mtl", std::ios::app);
|
||||
ASSERT_TRUE(mtlOutput.is_open());
|
||||
mtlOutput << "\n# force dependency reimport\n";
|
||||
ASSERT_TRUE(static_cast<bool>(mtlOutput));
|
||||
}
|
||||
|
||||
database.Initialize(projectRoot.string().c_str());
|
||||
AssetDatabase::ResolvedAsset secondResolve;
|
||||
ASSERT_TRUE(database.EnsureArtifact("Assets/textured_triangle.obj", ResourceType::Mesh, secondResolve));
|
||||
ASSERT_TRUE(secondResolve.artifactReady);
|
||||
EXPECT_NE(firstArtifactPath, secondResolve.artifactMainPath);
|
||||
const String secondArtifactPath = secondResolve.artifactMainPath;
|
||||
database.Shutdown();
|
||||
|
||||
std::this_thread::sleep_for(50ms);
|
||||
FlipLastByte(assetsDir / "checker.bmp");
|
||||
|
||||
database.Initialize(projectRoot.string().c_str());
|
||||
AssetDatabase::ResolvedAsset thirdResolve;
|
||||
ASSERT_TRUE(database.EnsureArtifact("Assets/textured_triangle.obj", ResourceType::Mesh, thirdResolve));
|
||||
ASSERT_TRUE(thirdResolve.artifactReady);
|
||||
EXPECT_NE(secondArtifactPath, thirdResolve.artifactMainPath);
|
||||
EXPECT_TRUE(fs::exists(thirdResolve.artifactMainPath.CStr()));
|
||||
database.Shutdown();
|
||||
|
||||
fs::remove_all(projectRoot);
|
||||
}
|
||||
|
||||
TEST(MeshLoader, ResourceManagerLoadsModelByAssetRefFromProjectAssets) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <XCEngine/Core/Asset/AssetDatabase.h>
|
||||
#include <XCEngine/Core/Asset/AssetRef.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/Resources/Texture/TextureImportSettings.h>
|
||||
#include <XCEngine/Resources/Texture/TextureLoader.h>
|
||||
#include <XCEngine/Core/Asset/ResourceTypes.h>
|
||||
#include <XCEngine/Core/Containers/Array.h>
|
||||
@@ -64,6 +65,24 @@ TEST(TextureLoader, LoadValidBmpTexture) {
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST(TextureLoader, LoadValidBmpTextureAsSRGBWhenRequested) {
|
||||
TextureLoader loader;
|
||||
TextureImportSettings settings;
|
||||
settings.SetSRGB(true);
|
||||
|
||||
const std::string path = GetTextureFixturePath("checker.bmp");
|
||||
LoadResult result = loader.Load(path.c_str(), &settings);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_NE(result.resource, nullptr);
|
||||
|
||||
auto* texture = static_cast<Texture*>(result.resource);
|
||||
EXPECT_EQ(texture->GetWidth(), 2u);
|
||||
EXPECT_EQ(texture->GetHeight(), 2u);
|
||||
EXPECT_EQ(texture->GetFormat(), TextureFormat::RGBA8_SRGB);
|
||||
|
||||
delete texture;
|
||||
}
|
||||
|
||||
TEST(TextureLoader, AssetDatabaseCreatesTextureArtifactAndReusesItWithoutReimport) {
|
||||
namespace fs = std::filesystem;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
Reference in New Issue
Block a user