Split mesh artifacts into material and texture artifacts
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <XCEngine/Resources/Mesh/MeshLoader.h>
|
||||
#include <XCEngine/Core/Asset/ArtifactFormats.h>
|
||||
#include <XCEngine/Resources/BuiltinResources.h>
|
||||
#include <XCEngine/Resources/Material/MaterialLoader.h>
|
||||
#include <XCEngine/Resources/Mesh/MeshImportSettings.h>
|
||||
#include <XCEngine/Resources/Material/Material.h>
|
||||
#include <XCEngine/Resources/Texture/Texture.h>
|
||||
@@ -148,6 +149,68 @@ Core::uint32 FindEmbeddedTextureIndex(const aiScene& scene, const aiTexture& emb
|
||||
return 0;
|
||||
}
|
||||
|
||||
Containers::String NormalizePathString(const std::filesystem::path& path) {
|
||||
return Containers::String(path.lexically_normal().generic_string().c_str());
|
||||
}
|
||||
|
||||
Containers::String ResolveArtifactDependencyPath(const Containers::String& dependencyPath,
|
||||
const Containers::String& ownerArtifactPath) {
|
||||
if (dependencyPath.Empty()) {
|
||||
return dependencyPath;
|
||||
}
|
||||
|
||||
std::filesystem::path dependencyFsPath(dependencyPath.CStr());
|
||||
if (dependencyFsPath.is_absolute() && std::filesystem::exists(dependencyFsPath)) {
|
||||
return NormalizePathString(dependencyFsPath);
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(dependencyFsPath)) {
|
||||
return NormalizePathString(dependencyFsPath);
|
||||
}
|
||||
|
||||
const Containers::String& resourceRoot = ResourceManager::Get().GetResourceRoot();
|
||||
if (!resourceRoot.Empty()) {
|
||||
const std::filesystem::path projectRelativeCandidate =
|
||||
std::filesystem::path(resourceRoot.CStr()) / dependencyFsPath;
|
||||
if (std::filesystem::exists(projectRelativeCandidate)) {
|
||||
return NormalizePathString(projectRelativeCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
const std::filesystem::path ownerArtifactFsPath(ownerArtifactPath.CStr());
|
||||
if (!ownerArtifactFsPath.is_absolute()) {
|
||||
return dependencyPath;
|
||||
}
|
||||
|
||||
const std::filesystem::path ownerRelativeCandidate =
|
||||
ownerArtifactFsPath.parent_path() / dependencyFsPath;
|
||||
if (std::filesystem::exists(ownerRelativeCandidate)) {
|
||||
return NormalizePathString(ownerRelativeCandidate);
|
||||
}
|
||||
|
||||
std::filesystem::path current = ownerArtifactFsPath.parent_path();
|
||||
while (!current.empty()) {
|
||||
if (current.filename() == "Library") {
|
||||
const std::filesystem::path projectRoot = current.parent_path();
|
||||
if (!projectRoot.empty()) {
|
||||
const std::filesystem::path projectRelativeCandidate = projectRoot / dependencyFsPath;
|
||||
if (std::filesystem::exists(projectRelativeCandidate)) {
|
||||
return NormalizePathString(projectRelativeCandidate);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const std::filesystem::path parent = current.parent_path();
|
||||
if (parent == current) {
|
||||
break;
|
||||
}
|
||||
current = parent;
|
||||
}
|
||||
|
||||
return dependencyPath;
|
||||
}
|
||||
|
||||
Texture* CreateRawTexture(const Containers::String& texturePath,
|
||||
TextureFormat format,
|
||||
Core::uint32 width,
|
||||
@@ -570,7 +633,7 @@ LoadResult LoadMeshArtifact(const Containers::String& path) {
|
||||
}
|
||||
|
||||
const std::string magic(header.magic, header.magic + 7);
|
||||
if (magic != "XCMESH1") {
|
||||
if (magic != "XCMESH2") {
|
||||
return LoadResult(Containers::String("Invalid mesh artifact magic: ") + path);
|
||||
}
|
||||
|
||||
@@ -628,93 +691,31 @@ LoadResult LoadMeshArtifact(const Containers::String& path) {
|
||||
bounds.SetMinMax(header.boundsMin, header.boundsMax);
|
||||
mesh->SetBounds(bounds);
|
||||
|
||||
std::vector<Containers::String> textureFiles;
|
||||
textureFiles.reserve(header.textureCount);
|
||||
for (Core::uint32 textureIndex = 0; textureIndex < header.textureCount; ++textureIndex) {
|
||||
textureFiles.push_back(ReadBinaryString(input));
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, Texture*> loadedTextures;
|
||||
TextureLoader textureLoader;
|
||||
const std::filesystem::path artifactDirectory = std::filesystem::path(path.CStr()).parent_path();
|
||||
MaterialLoader materialLoader;
|
||||
|
||||
for (Core::uint32 materialIndex = 0; materialIndex < header.materialCount; ++materialIndex) {
|
||||
Core::uint32 materialPresent = 0;
|
||||
input.read(reinterpret_cast<char*>(&materialPresent), sizeof(materialPresent));
|
||||
const Containers::String materialArtifactPath = ReadBinaryString(input);
|
||||
if (!input) {
|
||||
return LoadResult(Containers::String("Failed to read mesh material flag: ") + path);
|
||||
return LoadResult(Containers::String("Failed to read mesh material artifact path: ") + path);
|
||||
}
|
||||
|
||||
if (materialPresent == 0) {
|
||||
if (materialArtifactPath.Empty()) {
|
||||
mesh->AddMaterial(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* material = new Material();
|
||||
material->m_name = ReadBinaryString(input);
|
||||
material->m_path = ReadBinaryString(input);
|
||||
material->m_guid = ResourceGUID::Generate(material->m_path);
|
||||
material->m_isValid = true;
|
||||
material->SetShaderPass(ReadBinaryString(input));
|
||||
|
||||
MaterialArtifactHeader materialHeader;
|
||||
input.read(reinterpret_cast<char*>(&materialHeader), sizeof(materialHeader));
|
||||
if (!input) {
|
||||
delete material;
|
||||
return LoadResult(Containers::String("Failed to read material artifact header: ") + path);
|
||||
}
|
||||
|
||||
material->SetRenderQueue(materialHeader.renderQueue);
|
||||
material->SetRenderState(materialHeader.renderState);
|
||||
|
||||
for (Core::uint32 tagIndex = 0; tagIndex < materialHeader.tagCount; ++tagIndex) {
|
||||
material->SetTag(ReadBinaryString(input), ReadBinaryString(input));
|
||||
}
|
||||
|
||||
for (Core::uint32 propertyIndex = 0; propertyIndex < materialHeader.propertyCount; ++propertyIndex) {
|
||||
MaterialProperty property;
|
||||
property.name = ReadBinaryString(input);
|
||||
|
||||
MaterialPropertyArtifact propertyArtifact;
|
||||
input.read(reinterpret_cast<char*>(&propertyArtifact), sizeof(propertyArtifact));
|
||||
if (!input) {
|
||||
delete material;
|
||||
return LoadResult(Containers::String("Failed to read material property: ") + path);
|
||||
}
|
||||
|
||||
property.type = static_cast<MaterialPropertyType>(propertyArtifact.propertyType);
|
||||
property.value = propertyArtifact.value;
|
||||
ApplyMaterialProperty(*material, property);
|
||||
}
|
||||
|
||||
for (Core::uint32 bindingIndex = 0; bindingIndex < materialHeader.textureBindingCount; ++bindingIndex) {
|
||||
const Containers::String bindingName = ReadBinaryString(input);
|
||||
const Containers::String textureFile = ReadBinaryString(input);
|
||||
if (textureFile.Empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string textureKey(textureFile.CStr());
|
||||
Texture* texture = nullptr;
|
||||
auto textureIt = loadedTextures.find(textureKey);
|
||||
if (textureIt != loadedTextures.end()) {
|
||||
texture = textureIt->second;
|
||||
} else {
|
||||
const Containers::String texturePath =
|
||||
Containers::String((artifactDirectory / textureFile.CStr()).lexically_normal().string().c_str());
|
||||
LoadResult textureResult = textureLoader.Load(texturePath);
|
||||
if (textureResult && textureResult.resource != nullptr) {
|
||||
texture = static_cast<Texture*>(textureResult.resource);
|
||||
loadedTextures.emplace(textureKey, texture);
|
||||
mesh->AddTexture(texture);
|
||||
}
|
||||
}
|
||||
|
||||
if (texture != nullptr) {
|
||||
material->SetTexture(bindingName, ResourceHandle<Texture>(texture));
|
||||
}
|
||||
const Containers::String resolvedMaterialArtifactPath =
|
||||
ResolveArtifactDependencyPath(materialArtifactPath, path);
|
||||
LoadResult materialResult = materialLoader.Load(resolvedMaterialArtifactPath);
|
||||
if (!materialResult || materialResult.resource == nullptr) {
|
||||
return LoadResult(
|
||||
Containers::String("Failed to load mesh material artifact: ") +
|
||||
resolvedMaterialArtifactPath +
|
||||
" for " +
|
||||
path);
|
||||
}
|
||||
|
||||
auto* material = static_cast<Material*>(materialResult.resource);
|
||||
material->RecalculateMemorySize();
|
||||
mesh->AddMaterial(material);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user