From d37a68320ce6bde0cd1d6d17b3ed31268ab57b46 Mon Sep 17 00:00:00 2001 From: Simon Tippe Date: Thu, 8 Aug 2024 22:42:33 +0200 Subject: [PATCH] More changes --- src/editor/App.cpp | 6 +- src/editor/BlockingOperation.h | 28 ++ src/editor/Singletons.cpp | 2 + src/editor/Singletons.h | 2 + src/editor/ui/panels/PopupPanels.cpp | 60 ++++- src/editor/ui/panels/PopupPanels.h | 2 + src/editor/ui/panels/ViewportPanel.cpp | 8 +- src/editor/ui/windows/SceneWindow.cpp | 21 +- src/engine/Serializer.cpp | 67 +++-- src/engine/Serializer.h | 2 +- src/engine/loader/ModelImporter.cpp | 243 ++++++++++-------- src/engine/mesh/MeshSerializer.cpp | 25 +- src/engine/mesh/MeshSerializer.h | 26 +- src/engine/scene/Scene.cpp | 2 - .../scene/components/ComponentSerializer.cpp | 2 +- 15 files changed, 330 insertions(+), 166 deletions(-) create mode 100644 src/editor/BlockingOperation.h diff --git a/src/editor/App.cpp b/src/editor/App.cpp index 1d5a71568..d6e28d54f 100644 --- a/src/editor/App.cpp +++ b/src/editor/App.cpp @@ -47,6 +47,7 @@ namespace Atlas::Editor { // Everything that needs the config comes afterwards Singletons::icons = CreateRef(); + Singletons::blockingOperation = CreateRef(); Singletons::renderTarget = CreateRef(1280, 720); Singletons::pathTraceRenderTarget = CreateRef(1280, 720); Singletons::mainRenderer = mainRenderer; @@ -84,6 +85,9 @@ namespace Atlas::Editor { ContentDiscovery::Update(); Singletons::imguiWrapper->Update(&window, deltaTime); + if (Singletons::blockingOperation->block) + return; + // Create new windows for fully loaded scenes for (size_t i = 0; i < waitToLoadScenes.size(); i++) { if (waitToLoadScenes[i].IsLoaded()) { @@ -309,7 +313,7 @@ namespace Atlas::Editor { if (saveScene) { auto activeSceneWindow = sceneWindows.empty() ? nullptr : sceneWindows[activeSceneIdx]; - activeSceneWindow->SaveScene(); + activeSceneWindow->SaveScene(); } ImGui::EndMainMenuBar(); diff --git a/src/editor/BlockingOperation.h b/src/editor/BlockingOperation.h new file mode 100644 index 000000000..bfcf312b1 --- /dev/null +++ b/src/editor/BlockingOperation.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +namespace Atlas::Editor { + + class BlockingOperation { + + public: + void Block(const std::string& text, std::function blocker) { + if (future.valid()) + future.get(); + block = true; + blockText = text; + future = std::async(std::launch::async, [blocker, &block = block] { + blocker(); + block = false; + }); + } + + std::future future; + std::string blockText; + bool block = false; + + }; + +} \ No newline at end of file diff --git a/src/editor/Singletons.cpp b/src/editor/Singletons.cpp index 5a892f76e..cc03a9bca 100644 --- a/src/editor/Singletons.cpp +++ b/src/editor/Singletons.cpp @@ -8,6 +8,7 @@ namespace Atlas::Editor { Ref Singletons::mainRenderer; Ref Singletons::icons; Ref Singletons::config; + Ref Singletons::blockingOperation; void Singletons::Destruct() { @@ -17,6 +18,7 @@ namespace Atlas::Editor { mainRenderer.reset(); icons.reset(); config.reset(); + blockingOperation.reset(); } diff --git a/src/editor/Singletons.h b/src/editor/Singletons.h index 77313a55b..f178bc519 100644 --- a/src/editor/Singletons.h +++ b/src/editor/Singletons.h @@ -6,6 +6,7 @@ #include "renderer/MainRenderer.h" #include "Icons.h" #include "Config.h" +#include "BlockingOperation.h" namespace Atlas::Editor { @@ -20,6 +21,7 @@ namespace Atlas::Editor { static Ref mainRenderer; static Ref icons; static Ref config; + static Ref blockingOperation; }; diff --git a/src/editor/ui/panels/PopupPanels.cpp b/src/editor/ui/panels/PopupPanels.cpp index 27248b8af..4d806f2d9 100644 --- a/src/editor/ui/panels/PopupPanels.cpp +++ b/src/editor/ui/panels/PopupPanels.cpp @@ -5,6 +5,8 @@ #include #include "DataCreator.h" +#include "Singletons.h" +#include "Notifications.h" namespace Atlas::Editor::UI { @@ -17,6 +19,7 @@ namespace Atlas::Editor::UI { RenderNewScenePopup(); RenderImportScenePopup(); + RenderBlockingPopup(); } @@ -129,16 +132,23 @@ namespace Atlas::Editor::UI { ImGui::SameLine(); if (ImGui::Button("Ok") || ImGui::IsKeyReleased(ImGuiKey_Enter)) { - auto scene = DataCreator::CreateSceneFromMesh(filename, minSize, maxSize, - octreeDepth, invertUVs, addRigidBodies, combineMeshes, makeMeshesStatic); - scene->name = name; + Singletons::blockingOperation->Block("Importing scene. Please wait...", + [&]() { + auto scene = DataCreator::CreateSceneFromMesh(filename, minSize, maxSize, + octreeDepth, invertUVs, addRigidBodies, combineMeshes, makeMeshesStatic); + scene->name = name; - bool alreadyExisted; - Atlas::ResourceManager::AddResource(name, scene, alreadyExisted); + bool alreadyExisted; + Atlas::ResourceManager::AddResource(name, scene, alreadyExisted); - if (alreadyExisted) { - Log::Warning("Scene couldn't be created due to scene with same name existing already"); - } + if (alreadyExisted) { + Log::Warning("Scene couldn't be created due to scene with same name existing already"); + Notifications::Push({ .message = "Error importing scene " + scene->name }); + return; + } + + Notifications::Push({ .message = "Imported scene " + scene->name }); + }); isImportScenePopupVisible = false; ImGui::CloseCurrentPopup(); @@ -150,6 +160,40 @@ namespace Atlas::Editor::UI { } + void PopupPanels::RenderBlockingPopup() { + + if (!ImGui::IsPopupOpen("Blocking popup") && !Singletons::blockingOperation->block) + return; + + if (!ImGui::IsPopupOpen("Blocking popup")) { + ImGui::OpenPopup("Blocking popup"); + } + + ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.0f, 0.0f, 0.0f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_PopupBorderSize, 2.0f); + + SetupPopupSize(0.2f, 0.05f); + + if (ImGui::BeginPopupModal("Blocking popup", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar)) { + + ImGui::SetKeyboardFocusHere(); + + ImGui::Text(Singletons::blockingOperation->blockText.c_str()); + + if (!Singletons::blockingOperation->block) + ImGui::CloseCurrentPopup(); + + ImGui::EndPopup(); + + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + } + void PopupPanels::SetupPopupSize(float horizontalFactor, float verticalFactor) { auto viewport = ImGui::GetMainViewport(); diff --git a/src/editor/ui/panels/PopupPanels.h b/src/editor/ui/panels/PopupPanels.h index c1de77c67..8b8210075 100644 --- a/src/editor/ui/panels/PopupPanels.h +++ b/src/editor/ui/panels/PopupPanels.h @@ -22,6 +22,8 @@ namespace Atlas::Editor::UI { static void RenderImportScenePopup(); + static void RenderBlockingPopup(); + }; } \ No newline at end of file diff --git a/src/editor/ui/panels/ViewportPanel.cpp b/src/editor/ui/panels/ViewportPanel.cpp index ff7936cb2..0898fc7d8 100644 --- a/src/editor/ui/panels/ViewportPanel.cpp +++ b/src/editor/ui/panels/ViewportPanel.cpp @@ -33,6 +33,8 @@ namespace Atlas::Editor::UI { ImGui::Begin(GetNameID()); + bool isBlocked = Singletons::blockingOperation->block; + // Workaround for offsetted Gizmo without resize after a restart // Seems like some ImGuizmo or ImGui config isn't properly updated if (firstFrame) { @@ -59,7 +61,7 @@ namespace Atlas::Editor::UI { CreateRenderPass(); } - if (scene != nullptr && validRegion && isActiveWindow) { + if (scene != nullptr && validRegion && isActiveWindow && !isBlocked) { auto& config = Singletons::config; if (config->pathTrace) { @@ -97,12 +99,12 @@ namespace Atlas::Editor::UI { ImGui::Image(set, region); } - if (drawOverlayFunc) + if (drawOverlayFunc && !isBlocked) drawOverlayFunc(); ImGui::SetCursorPos(ImVec2(0.0f, 0.0f)); - if (drawMenuBarFunc) { + if (drawMenuBarFunc && !isBlocked) { isFocused |= ImGui::IsWindowFocused(); drawMenuBarFunc(); diff --git a/src/editor/ui/windows/SceneWindow.cpp b/src/editor/ui/windows/SceneWindow.cpp index fb24bc653..ebf14f654 100644 --- a/src/editor/ui/windows/SceneWindow.cpp +++ b/src/editor/ui/windows/SceneWindow.cpp @@ -71,6 +71,8 @@ namespace Atlas::Editor::UI { ImGui::SetWindowFocus(); } + bool isBlocked = Singletons::blockingOperation->block; + ImGuiID dsID = ImGui::GetID(dockSpaceNameID.c_str()); if (!ImGui::DockBuilderGetNode(dsID) || resetDockingLayout) { @@ -143,7 +145,7 @@ namespace Atlas::Editor::UI { } // We want to update the scene after all panels have update their respective values/changed the scene - if (!isPlaying) { + if (!isPlaying && !isBlocked) { // Temporarily disable all scene cameras, only let editor camera be main std::map cameraMainMap; auto cameraSubset = scene->GetSubset(); @@ -635,17 +637,20 @@ namespace Atlas::Editor::UI { if (!scene.IsLoaded()) return; - cameraState = Scene::Entity::Backup(scene.Get(), cameraEntity); + Singletons::blockingOperation->Block("Saving scene. Please wait...", + [&]() { + cameraState = Scene::Entity::Backup(scene.Get(), cameraEntity); - scene->DestroyEntity(cameraEntity); + scene->DestroyEntity(cameraEntity); - Serializer::SerializeScene(scene.Get(), "scenes/" + std::string(scene->name) + ".aescene", true); - - cameraEntity = Scene::Entity::Restore(scene.Get(), cameraState); + Serializer::SerializeScene(scene.Get(), "scenes/" + std::string(scene->name) + ".aescene", true); - cameraState.clear(); + cameraEntity = Scene::Entity::Restore(scene.Get(), cameraState); + + cameraState.clear(); - Notifications::Push({ .message = "Saved scene " + scene->name }); + Notifications::Push({ .message = "Saved scene " + scene->name }); + }); } diff --git a/src/engine/Serializer.cpp b/src/engine/Serializer.cpp index b9cc17c32..fff790195 100644 --- a/src/engine/Serializer.cpp +++ b/src/engine/Serializer.cpp @@ -36,23 +36,7 @@ namespace Atlas { } if (saveDependencies) { - auto meshes = scene->GetMeshes(); - std::map> materials; - - for (const auto& mesh : meshes) { - if (!mesh.IsLoaded()) continue; - - Loader::MeshLoader::SaveMesh(mesh.Get(), mesh.GetResource()->path); - - for (const auto& material : mesh->data.materials) - materials[material.GetID()] = material; - } - - for (const auto& [_, material] : materials) { - if (!material.IsLoaded()) continue; - - Loader::MaterialLoader::SaveMaterial(material.Get(), material.GetResource()->path); - } + SaveDependencies(scene); } fileStream.close(); @@ -150,4 +134,53 @@ namespace Atlas { } + void Serializer::SaveDependencies(Ref scene, bool multithreaded) { + + auto meshes = scene->GetMeshes(); + std::map> materials; + + if (multithreaded) { + std::atomic_int32_t counter = 0; + + auto workerCount = std::thread::hardware_concurrency(); + std::vector> workers; + for (uint32_t i = 0; i < workerCount; i++) { + workers.emplace_back(std::async(std::launch::async, [&]() { + auto i = counter++; + + while (i < int32_t(meshes.size())) { + auto& mesh = meshes[i]; + + if (!mesh.IsLoaded()) continue; + + Loader::MeshLoader::SaveMesh(mesh.Get(), mesh.GetResource()->path, true); + + i = counter++; + } + })); + } + + for (uint32_t i = 0; i < workerCount; i++) { + workers[i].get(); + } + } + + for (const auto& mesh : meshes) { + if (!mesh.IsLoaded()) continue; + + if (!multithreaded) + Loader::MeshLoader::SaveMesh(mesh.Get(), mesh.GetResource()->path, true); + + for (const auto& material : mesh->data.materials) + materials[material.GetID()] = material; + } + + for (const auto& [_, material] : materials) { + if (!material.IsLoaded()) continue; + + Loader::MaterialLoader::SaveMaterial(material.Get(), material.GetResource()->path); + } + + } + } \ No newline at end of file diff --git a/src/engine/Serializer.h b/src/engine/Serializer.h index a64a3100c..d6a2b32af 100644 --- a/src/engine/Serializer.h +++ b/src/engine/Serializer.h @@ -17,7 +17,7 @@ namespace Atlas { static Scene::Entity DeserializePrefab(Ref scene, const std::string& filename); private: - + static void SaveDependencies(Ref scene, bool multithreaded = true); }; diff --git a/src/engine/loader/ModelImporter.cpp b/src/engine/loader/ModelImporter.cpp index b436262f6..9ec0bdda4 100644 --- a/src/engine/loader/ModelImporter.cpp +++ b/src/engine/loader/ModelImporter.cpp @@ -168,8 +168,10 @@ namespace Atlas { normals[usedVertices] = vec4(normal, 0.0f); if (hasTangents && mesh->mTangents != nullptr) { - vec3 tangent = vec3(matrix * vec4(mesh->mTangents[j].x, - mesh->mTangents[j].y, mesh->mTangents[j].z, 0.0f)); + // Avoid tangents that are fully zero + vec3 tangent = vec3(mesh->mTangents[j].x, + mesh->mTangents[j].y, mesh->mTangents[j].z) + 1e-9f; + tangent = vec3(matrix * vec4(tangent, 0.0f)); tangent = normalize(tangent - normal * dot(normal, tangent)); vec3 estimatedBitangent = normalize(cross(tangent, normal)); @@ -225,7 +227,7 @@ namespace Atlas { mesh->UpdateData(); auto meshFilename = state.paths.meshPath + mesh->name + ".aemesh"; - Loader::MeshLoader::SaveMesh(mesh, meshFilename); + Loader::MeshLoader::SaveMesh(mesh, meshFilename, true); return mesh; @@ -245,145 +247,162 @@ namespace Atlas { vec3 offset; }; - std::map meshMap; + std::vector meshes; + meshes.resize(state.scene->mNumMeshes); - for (uint32_t i = 0; i < state.scene->mNumMeshes; i++) { - auto assimpMesh = state.scene->mMeshes[i]; - auto materialIdx = assimpMesh->mMaterialIndex; - auto material = materials[materialIdx]; + std::atomic_int32_t counter = 0; + auto threadCount = std::thread::hardware_concurrency(); + std::vector> threads; - uint32_t indexCount = assimpMesh->mNumFaces * 3; - uint32_t vertexCount = assimpMesh->mNumVertices; + for (uint32_t i = 0; i < threadCount; i++) { + threads.emplace_back(std::async(std::launch::async, [&]() { + auto i = counter++; - bool hasTangents = false; - bool hasVertexColors = false; - bool hasTexCoords = assimpMesh->mNumUVComponents[0] > 0; + while (i < int32_t(meshes.size())) { - auto mesh = CreateRef(); - auto& meshData = mesh->data; + auto assimpMesh = state.scene->mMeshes[i]; + auto materialIdx = assimpMesh->mMaterialIndex; + auto material = materials[materialIdx]; - hasTangents |= forceTangents; - if (material->HasNormalMap()) - hasTangents = true; - if (material->HasDisplacementMap()) - hasTangents = true; + uint32_t indexCount = assimpMesh->mNumFaces * 3; + uint32_t vertexCount = assimpMesh->mNumVertices; - if (vertexCount > 65535) { - meshData.indices.SetType(Mesh::ComponentFormat::UnsignedInt); - } - else { - meshData.indices.SetType(Mesh::ComponentFormat::UnsignedShort); - } + bool hasTangents = false; + bool hasVertexColors = false; + bool hasTexCoords = assimpMesh->mNumUVComponents[0] > 0; - hasVertexColors = assimpMesh->HasVertexColors(0); + auto mesh = CreateRef(); + auto& meshData = mesh->data; - meshData.SetIndexCount(indexCount); - meshData.SetVertexCount(vertexCount); + hasTangents |= forceTangents; + if (material->HasNormalMap()) + hasTangents = true; + if (material->HasDisplacementMap()) + hasTangents = true; - auto& indices = meshData.indices; + if (vertexCount > 65535) { + meshData.indices.SetType(Mesh::ComponentFormat::UnsignedInt); + } + else { + meshData.indices.SetType(Mesh::ComponentFormat::UnsignedShort); + } - auto& vertices = meshData.vertices; - auto& texCoords = meshData.texCoords; - auto& normals = meshData.normals; - auto& tangents = meshData.tangents; - auto& colors = meshData.colors; + hasVertexColors = assimpMesh->HasVertexColors(0); - indices.SetElementCount(indexCount); + meshData.SetIndexCount(indexCount); + meshData.SetVertexCount(vertexCount); - vertices.SetElementCount(vertexCount); - texCoords.SetElementCount(hasTexCoords ? vertexCount : 0); - normals.SetElementCount(vertexCount); - tangents.SetElementCount(hasTangents ? vertexCount : 0); - colors.SetElementCount(hasVertexColors ? vertexCount : 0); + auto& indices = meshData.indices; - material->vertexColors &= hasVertexColors; - meshData.materials.push_back(material); + auto& vertices = meshData.vertices; + auto& texCoords = meshData.texCoords; + auto& normals = meshData.normals; + auto& tangents = meshData.tangents; + auto& colors = meshData.colors; - auto min = vec3(std::numeric_limits::max()); - auto max = vec3(-std::numeric_limits::max()); + indices.SetElementCount(indexCount); - uint32_t uvChannel = material->uvChannel; - for (uint32_t j = 0; j < assimpMesh->mNumVertices; j++) { + vertices.SetElementCount(vertexCount); + texCoords.SetElementCount(hasTexCoords ? vertexCount : 0); + normals.SetElementCount(vertexCount); + tangents.SetElementCount(hasTangents ? vertexCount : 0); + colors.SetElementCount(hasVertexColors ? vertexCount : 0); - vec3 vertex = vec3(assimpMesh->mVertices[j].x, - assimpMesh->mVertices[j].y, assimpMesh->mVertices[j].z); + material->vertexColors &= hasVertexColors; + meshData.materials.push_back(material); - vertices[j] = vertex; + auto min = vec3(std::numeric_limits::max()); + auto max = vec3(-std::numeric_limits::max()); - max = glm::max(vertex, max); - min = glm::min(vertex, min); + uint32_t uvChannel = material->uvChannel; + for (uint32_t j = 0; j < assimpMesh->mNumVertices; j++) { - vec3 normal = vec3(assimpMesh->mNormals[j].x, - assimpMesh->mNormals[j].y, assimpMesh->mNormals[j].z); - normal = normalize(normal); + vec3 vertex = vec3(assimpMesh->mVertices[j].x, + assimpMesh->mVertices[j].y, assimpMesh->mVertices[j].z); - normals[j] = vec4(normal, 0.0f); + vertices[j] = vertex; - if (hasTangents && assimpMesh->mTangents != nullptr) { - vec3 tangent = vec3(assimpMesh->mTangents[j].x, - assimpMesh->mTangents[j].y, assimpMesh->mTangents[j].z); - tangent = normalize(tangent - normal * dot(normal, tangent)); + max = glm::max(vertex, max); + min = glm::min(vertex, min); - vec3 estimatedBitangent = normalize(cross(tangent, normal)); - vec3 correctBitangent = vec3(assimpMesh->mBitangents[j].x, - assimpMesh->mBitangents[j].y, assimpMesh->mBitangents[j].z); - correctBitangent = normalize(correctBitangent); + vec3 normal = vec3(assimpMesh->mNormals[j].x, + assimpMesh->mNormals[j].y, assimpMesh->mNormals[j].z); + normal = normalize(normal); - float dotProduct = dot(estimatedBitangent, correctBitangent); + normals[j] = vec4(normal, 0.0f); - tangents[j] = vec4(tangent, dotProduct <= 0.0f ? -1.0f : 1.0f); - } + if (hasTangents && assimpMesh->mTangents != nullptr) { + // Avoid tangents that are fully zero + vec3 tangent = vec3(assimpMesh->mTangents[j].x, + assimpMesh->mTangents[j].y, assimpMesh->mTangents[j].z) + 1e-9f; + tangent = normalize(tangent - normal * dot(normal, tangent)); - if (hasTexCoords && assimpMesh->mTextureCoords[uvChannel] != nullptr) { - texCoords[j] = vec2(assimpMesh->mTextureCoords[uvChannel][j].x, - assimpMesh->mTextureCoords[uvChannel][j].y); - } + vec3 estimatedBitangent = normalize(cross(tangent, normal)); + vec3 correctBitangent = vec3(assimpMesh->mBitangents[j].x, + assimpMesh->mBitangents[j].y, assimpMesh->mBitangents[j].z); + correctBitangent = normalize(correctBitangent); - if (hasVertexColors && assimpMesh->mColors[0] != nullptr) { - colors[j] = vec4(assimpMesh->mColors[0][j].r, assimpMesh->mColors[0][j].g, - assimpMesh->mColors[0][j].b, assimpMesh->mColors[0][j].a); - } + float dotProduct = dot(estimatedBitangent, correctBitangent); + tangents[j] = vec4(tangent, dotProduct <= 0.0f ? -1.0f : 1.0f); + } - } + if (hasTexCoords && assimpMesh->mTextureCoords[uvChannel] != nullptr) { + texCoords[j] = vec2(assimpMesh->mTextureCoords[uvChannel][j].x, + assimpMesh->mTextureCoords[uvChannel][j].y); + } - auto offset = vec3((max.x + min.x) * 0.5f, min.y, (max.z + min.z) * 0.5f); - // Recenter mesh - min -= offset; - max -= offset; - for (uint32_t j = 0; j < assimpMesh->mNumVertices; j++) { - vertices[j] = vertices[j] - offset; - } - - // Copy indices - for (uint32_t j = 0; j < assimpMesh->mNumFaces; j++) { - for (uint32_t k = 0; k < 3; k++) { - indices[j * 3 + k] = assimpMesh->mFaces[j].mIndices[k]; - } - } + if (hasVertexColors && assimpMesh->mColors[0] != nullptr) { + colors[j] = vec4(assimpMesh->mColors[0][j].r, assimpMesh->mColors[0][j].g, + assimpMesh->mColors[0][j].b, assimpMesh->mColors[0][j].a); + } - meshData.aabb = Volume::AABB(min, max); - meshData.radius = glm::length(max - min) * 0.5; + } - meshData.subData.push_back({ - .indicesOffset = 0, - .indicesCount = indexCount, + auto offset = (max + min) * 0.5f; + // Recenter mesh + min -= offset; + max -= offset; + for (uint32_t j = 0; j < assimpMesh->mNumVertices; j++) { + vertices[j] = vertices[j] - offset; + } + + // Copy indices + for (uint32_t j = 0; j < assimpMesh->mNumFaces; j++) { + for (uint32_t k = 0; k < 3; k++) { + indices[j * 3 + k] = assimpMesh->mFaces[j].mIndices[k]; + } + } - .material = material, - .materialIdx = 0, + meshData.aabb = Volume::AABB(min, max); + meshData.radius = glm::length(max - min) * 0.5; - .aabb = meshData.aabb - }); + meshData.subData.push_back({ + .indicesOffset = 0, + .indicesCount = indexCount, - meshData.name = std::string(assimpMesh->mName.C_Str()); - mesh->name = meshData.name; - mesh->UpdateData(); + .material = material, + .materialIdx = 0, - auto meshFilename = state.paths.meshPath + mesh->name + "_" + std::to_string(i) + ".aemesh"; + .aabb = meshData.aabb + }); - auto handle = ResourceManager::AddResource(meshFilename, mesh); - meshMap[assimpMesh] = { handle, offset }; + meshData.name = std::string(assimpMesh->mName.C_Str()); + mesh->name = meshData.name; + mesh->UpdateData(); - Loader::MeshLoader::SaveMesh(mesh, meshFilename); + auto meshFilename = state.paths.meshPath + mesh->name + "_" + std::to_string(i) + ".aemesh"; + auto handle = ResourceManager::AddResource(meshFilename, mesh); + meshes[i] = { handle, offset }; + + Loader::MeshLoader::SaveMesh(mesh, meshFilename, true); + + i = counter++; + } + })); + } + + for (uint32_t i = 0; i < threadCount; i++) { + threads[i].get(); } auto scene = CreateRef(filename, min, max, depth); @@ -393,24 +412,20 @@ namespace Atlas { auto& rootHierarchy = rootEntity.AddComponent(); rootHierarchy.root = true; - int32_t triangleCount = 0; - std::function traverseNodeTree; traverseNodeTree = [&](aiNode* node, Scene::Entity parentEntity) { auto nodeTransform = glm::transpose(glm::make_mat4(&node->mTransformation.a1)); for (uint32_t i = 0; i < node->mNumMeshes; i++) { auto meshId = node->mMeshes[i]; - auto mesh = state.scene->mMeshes[meshId]; - - triangleCount += mesh->mNumFaces; + auto& meshInfo = meshes[meshId]; - auto instanceTransform = glm::translate(meshMap[mesh].offset); + auto instanceTransform = glm::translate(meshInfo.offset); auto entity = scene->CreatePrefab( - meshMap[mesh].mesh, nodeTransform * instanceTransform, makeMeshesStatic); + meshInfo.mesh, nodeTransform * instanceTransform, makeMeshesStatic); - auto name = std::string(mesh->mName.C_Str()) + "_" + std::to_string(entity); + auto name = std::string(meshInfo.mesh->name) + "_" + std::to_string(entity); entity.AddComponent(name); parentEntity.GetComponent().AddChild(entity); diff --git a/src/engine/mesh/MeshSerializer.cpp b/src/engine/mesh/MeshSerializer.cpp index 1c63c180a..5c180213c 100644 --- a/src/engine/mesh/MeshSerializer.cpp +++ b/src/engine/mesh/MeshSerializer.cpp @@ -60,6 +60,8 @@ namespace Atlas::Mesh { void to_json(json& j, const MeshData& p) { + bool binary = true; + j = json{ {"name", p.name}, {"indexCount", p.GetIndexCount()}, @@ -74,8 +76,16 @@ namespace Atlas::Mesh { {"primitiveType", p.primitiveType}, {"radius", p.radius}, {"aabb", p.aabb}, + {"binary", binary}, }; + to_json(j["indices"], p.indices, binary); + to_json(j["vertices"], p.vertices, binary); + to_json(j["texCoords"], p.texCoords, binary); + to_json(j["normals"], p.normals, binary); + to_json(j["tangents"], p.tangents, binary); + to_json(j["colors"], p.colors, binary); + for (size_t i = 0; i < p.materials.size(); i++) { auto& material = p.materials[i]; auto path = material.GetResource()->path; @@ -86,6 +96,7 @@ namespace Atlas::Mesh { void from_json(const json& j, MeshData& p) { + bool binary; int32_t indexCount, vertexCount; j.at("name").get_to(p.name); @@ -95,16 +106,18 @@ namespace Atlas::Mesh { p.SetIndexCount(indexCount); p.SetVertexCount(vertexCount); - j.at("indices").get_to(p.indices); - j.at("vertices").get_to(p.vertices); - j.at("texCoords").get_to(p.texCoords); - j.at("normals").get_to(p.normals); - j.at("tangents").get_to(p.tangents); - j.at("colors").get_to(p.colors); j.at("subData").get_to(p.subData); j.at("primitiveType").get_to(p.primitiveType); j.at("radius").get_to(p.radius); j.at("aabb").get_to(p.aabb); + j.at("binary").get_to(binary); + + from_json(j["indices"], p.indices, binary); + from_json(j["vertices"], p.vertices, binary); + from_json(j["texCoords"], p.texCoords, binary); + from_json(j["normals"], p.normals, binary); + from_json(j["tangents"], p.tangents, binary); + from_json(j["colors"], p.colors, binary); if (j.contains("materials")) { for (auto& path : j["materials"]) { diff --git a/src/engine/mesh/MeshSerializer.h b/src/engine/mesh/MeshSerializer.h index b82e92019..5257c8e75 100644 --- a/src/engine/mesh/MeshSerializer.h +++ b/src/engine/mesh/MeshSerializer.h @@ -26,27 +26,43 @@ namespace Atlas::Mesh { void from_json(const json& j, Impostor& p); template - void to_json(json& j, const DataComponent& p) { + void to_json(json& j, const DataComponent& p, bool binary) { int format = static_cast(p.format); j = json{ {"format", format}, - {"data", p.data} }; + std::vector binaryData; + if (!p.data.empty()) { + binaryData.resize(p.data.size() * sizeof(T)); + std::memcpy(binaryData.data(), p.data.data(), binaryData.size()); + } + + if (binary) { + j["data"] = json::binary_t(binaryData); + } + else { + j["data"] = binaryData; + } + } template - void from_json(const json& j, DataComponent& p) { + void from_json(const json& j, DataComponent& p, bool binary) { int format; j.at("format").get_to(format); - j.at("data").get_to(p.data); - p.format = static_cast(format); + std::vector binaryData = j["data"]; + if (!binaryData.empty()) { + p.data.resize(binaryData.size() / sizeof(T)); + std::memcpy(p.data.data(), binaryData.data(), binaryData.size()); + } + } } diff --git a/src/engine/scene/Scene.cpp b/src/engine/scene/Scene.cpp index 06953cf5c..e118bb23b 100644 --- a/src/engine/scene/Scene.cpp +++ b/src/engine/scene/Scene.cpp @@ -634,8 +634,6 @@ namespace Atlas { if (!mesh.IsLoaded()) continue; for (auto& material : mesh->data.materials) { - if (!material.IsLoaded()) - Log::Warning("Nooooo"); if (material->HasBaseColorMap()) textures.insert(material->baseColorMap.Get()); if (material->HasOpacityMap()) diff --git a/src/engine/scene/components/ComponentSerializer.cpp b/src/engine/scene/components/ComponentSerializer.cpp index 703abddf3..0a17e4815 100644 --- a/src/engine/scene/components/ComponentSerializer.cpp +++ b/src/engine/scene/components/ComponentSerializer.cpp @@ -177,7 +177,7 @@ namespace Atlas::Scene::Components { j.at("resourcePath").get_to(resourcePath); p.mesh = ResourceManager::GetOrLoadResourceWithLoaderAsync(resourcePath, - ResourceOrigin::User, Loader::MeshLoader::LoadMesh, false); + ResourceOrigin::User, Loader::MeshLoader::LoadMesh, true); } }