Import material textures with mesh assets
This commit is contained in:
@@ -1,9 +1,54 @@
|
||||
#include <XCEngine/Resources/Texture/TextureLoader.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <stb_image.h>
|
||||
#include <filesystem>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Resources {
|
||||
|
||||
namespace {
|
||||
|
||||
Containers::String GetResourceNameFromPath(const Containers::String& path) {
|
||||
const std::filesystem::path filePath(path.CStr());
|
||||
const std::string fileName = filePath.filename().string();
|
||||
if (!fileName.empty()) {
|
||||
return Containers::String(fileName.c_str());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
LoadResult CreateTextureResource(const Containers::String& path,
|
||||
TextureFormat format,
|
||||
Core::uint32 width,
|
||||
Core::uint32 height,
|
||||
const void* pixelData,
|
||||
size_t pixelDataSize) {
|
||||
auto* texture = new Texture();
|
||||
|
||||
IResource::ConstructParams params;
|
||||
params.name = GetResourceNameFromPath(path);
|
||||
params.path = path;
|
||||
params.guid = ResourceGUID::Generate(path);
|
||||
params.memorySize = 0;
|
||||
texture->Initialize(params);
|
||||
|
||||
if (!texture->Create(width,
|
||||
height,
|
||||
1,
|
||||
1,
|
||||
TextureType::Texture2D,
|
||||
format,
|
||||
pixelData,
|
||||
pixelDataSize)) {
|
||||
delete texture;
|
||||
return LoadResult(Containers::String("Failed to create texture resource: ") + path);
|
||||
}
|
||||
|
||||
return LoadResult(texture);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TextureLoader::TextureLoader() = default;
|
||||
TextureLoader::~TextureLoader() = default;
|
||||
|
||||
@@ -21,8 +66,7 @@ Containers::Array<Containers::String> TextureLoader::GetSupportedExtensions() co
|
||||
}
|
||||
|
||||
bool TextureLoader::CanLoad(const Containers::String& path) const {
|
||||
Containers::String ext = GetExtension(path);
|
||||
ext.ToLower();
|
||||
Containers::String ext = GetExtension(path).ToLower();
|
||||
|
||||
return ext == "png" || ext == "jpg" || ext == "jpeg" ||
|
||||
ext == "tga" || ext == "bmp" || ext == "gif" ||
|
||||
@@ -32,29 +76,83 @@ bool TextureLoader::CanLoad(const Containers::String& path) const {
|
||||
LoadResult TextureLoader::Load(const Containers::String& path, const ImportSettings* settings) {
|
||||
(void)settings;
|
||||
|
||||
Containers::String ext = GetExtension(path);
|
||||
ext.ToLower();
|
||||
Containers::String ext = GetExtension(path).ToLower();
|
||||
|
||||
if (!CanLoad(path)) {
|
||||
return LoadResult(Containers::String("Unsupported texture format: ") + ext);
|
||||
}
|
||||
|
||||
if (ext == "dds") {
|
||||
return LoadResult(Containers::String("DDS texture decoding is not implemented yet: ") + path);
|
||||
}
|
||||
|
||||
Containers::Array<Core::uint8> fileData = ReadFileData(path);
|
||||
if (fileData.Empty()) {
|
||||
return LoadResult(Containers::String("Failed to read file: ") + path);
|
||||
}
|
||||
|
||||
auto* texture = new Texture();
|
||||
|
||||
IResource::ConstructParams params;
|
||||
params.name = path;
|
||||
params.path = path;
|
||||
params.guid = ResourceGUID::Generate(path);
|
||||
params.memorySize = fileData.Size();
|
||||
|
||||
texture->Initialize(params);
|
||||
|
||||
return LoadResult(texture);
|
||||
|
||||
return LoadFromMemory(path, fileData.Data(), fileData.Size());
|
||||
}
|
||||
|
||||
LoadResult TextureLoader::LoadFromMemory(const Containers::String& path, const void* data, size_t dataSize) const {
|
||||
if (data == nullptr || dataSize == 0) {
|
||||
return LoadResult(Containers::String("Texture data is empty: ") + path);
|
||||
}
|
||||
|
||||
const auto* stbData = reinterpret_cast<const stbi_uc*>(data);
|
||||
const int stbDataSize = static_cast<int>(dataSize);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int channels = 0;
|
||||
|
||||
if (stbi_is_hdr_from_memory(stbData, stbDataSize) != 0) {
|
||||
float* pixels = stbi_loadf_from_memory(stbData,
|
||||
stbDataSize,
|
||||
&width,
|
||||
&height,
|
||||
&channels,
|
||||
STBI_rgb_alpha);
|
||||
if (pixels == nullptr) {
|
||||
return LoadResult(Containers::String("Failed to decode HDR texture: ") + path);
|
||||
}
|
||||
|
||||
const size_t pixelDataSize = static_cast<size_t>(width) *
|
||||
static_cast<size_t>(height) *
|
||||
4u *
|
||||
sizeof(float);
|
||||
LoadResult result = CreateTextureResource(path,
|
||||
TextureFormat::RGBA32_FLOAT,
|
||||
static_cast<Core::uint32>(width),
|
||||
static_cast<Core::uint32>(height),
|
||||
pixels,
|
||||
pixelDataSize);
|
||||
stbi_image_free(pixels);
|
||||
return result;
|
||||
}
|
||||
|
||||
stbi_uc* pixels = stbi_load_from_memory(stbData,
|
||||
stbDataSize,
|
||||
&width,
|
||||
&height,
|
||||
&channels,
|
||||
STBI_rgb_alpha);
|
||||
if (pixels == nullptr) {
|
||||
return LoadResult(Containers::String("Failed to decode texture: ") + path);
|
||||
}
|
||||
|
||||
const size_t pixelDataSize = static_cast<size_t>(width) *
|
||||
static_cast<size_t>(height) *
|
||||
4u *
|
||||
sizeof(stbi_uc);
|
||||
LoadResult result = CreateTextureResource(path,
|
||||
TextureFormat::RGBA8_UNORM,
|
||||
static_cast<Core::uint32>(width),
|
||||
static_cast<Core::uint32>(height),
|
||||
pixels,
|
||||
pixelDataSize);
|
||||
stbi_image_free(pixels);
|
||||
return result;
|
||||
}
|
||||
|
||||
ImportSettings* TextureLoader::GetDefaultSettings() const {
|
||||
|
||||
Reference in New Issue
Block a user