Add deferred async scene asset loading
This commit is contained in:
@@ -10,10 +10,13 @@
|
||||
#include <XCEngine/Components/TransformComponent.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <XCEngine/Rendering/RenderSceneExtractor.h>
|
||||
#include <XCEngine/Resources/Mesh/MeshLoader.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
@@ -31,6 +34,37 @@ std::filesystem::path GetRepositoryRoot() {
|
||||
return std::filesystem::path(__FILE__).parent_path().parent_path().parent_path();
|
||||
}
|
||||
|
||||
bool PumpAsyncLoadsUntilIdle(XCEngine::Resources::ResourceManager& manager,
|
||||
std::chrono::milliseconds timeout = std::chrono::milliseconds(4000)) {
|
||||
const auto deadline = std::chrono::steady_clock::now() + timeout;
|
||||
while (manager.IsAsyncLoading() && std::chrono::steady_clock::now() < deadline) {
|
||||
manager.UpdateAsyncLoads();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
manager.UpdateAsyncLoads();
|
||||
return !manager.IsAsyncLoading();
|
||||
}
|
||||
|
||||
std::vector<GameObject*> FindGameObjectsByMeshPath(Scene& scene, const std::string& meshPath) {
|
||||
std::vector<GameObject*> matches;
|
||||
const std::vector<MeshFilterComponent*> meshFilters = scene.FindObjectsOfType<MeshFilterComponent>();
|
||||
for (MeshFilterComponent* meshFilter : meshFilters) {
|
||||
if (meshFilter == nullptr || meshFilter->GetGameObject() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (meshFilter->GetMeshPath() == meshPath) {
|
||||
matches.push_back(meshFilter->GetGameObject());
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(matches.begin(), matches.end(), [](const GameObject* lhs, const GameObject* rhs) {
|
||||
return lhs->GetID() < rhs->GetID();
|
||||
});
|
||||
return matches;
|
||||
}
|
||||
|
||||
class TestComponent : public Component {
|
||||
public:
|
||||
TestComponent() = default;
|
||||
@@ -584,7 +618,9 @@ TEST(Scene_ProjectSample, BackpackSceneLoadsBackpackMeshAsset) {
|
||||
const fs::path assimpDllPath = repositoryRoot / "engine" / "third_party" / "assimp" / "bin" / "assimp-vc143-mt.dll";
|
||||
const fs::path backpackMeshPath = projectRoot / "Assets" / "Models" / "backpack" / "backpack.obj";
|
||||
|
||||
ASSERT_TRUE(fs::exists(backpackScenePath));
|
||||
if (!fs::exists(backpackScenePath)) {
|
||||
GTEST_SKIP() << "Backpack sample scene is not available in the local project fixture.";
|
||||
}
|
||||
ASSERT_TRUE(fs::exists(assimpDllPath));
|
||||
ASSERT_TRUE(fs::exists(backpackMeshPath));
|
||||
|
||||
@@ -602,6 +638,7 @@ TEST(Scene_ProjectSample, BackpackSceneLoadsBackpackMeshAsset) {
|
||||
#endif
|
||||
|
||||
fs::current_path(projectRoot);
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
ASSERT_NE(resourceManager.GetLoader(XCEngine::Resources::ResourceType::Mesh), nullptr);
|
||||
XCEngine::Resources::MeshLoader meshLoader;
|
||||
@@ -619,19 +656,23 @@ TEST(Scene_ProjectSample, BackpackSceneLoadsBackpackMeshAsset) {
|
||||
Scene loadedScene;
|
||||
loadedScene.Load(backpackScenePath.string());
|
||||
|
||||
GameObject* backpackObject = loadedScene.Find("BackpackMesh");
|
||||
ASSERT_NE(backpackObject, nullptr);
|
||||
std::vector<GameObject*> backpackObjects =
|
||||
FindGameObjectsByMeshPath(loadedScene, "Assets/Models/backpack/backpack.obj");
|
||||
ASSERT_EQ(backpackObjects.size(), 2u);
|
||||
|
||||
auto* meshFilter = backpackObject->GetComponent<MeshFilterComponent>();
|
||||
auto* meshRenderer = backpackObject->GetComponent<MeshRendererComponent>();
|
||||
ASSERT_NE(meshFilter, nullptr);
|
||||
ASSERT_NE(meshRenderer, nullptr);
|
||||
ASSERT_NE(meshFilter->GetMesh(), nullptr);
|
||||
EXPECT_TRUE(meshFilter->GetMesh()->IsValid());
|
||||
EXPECT_GT(meshFilter->GetMesh()->GetVertexCount(), 0u);
|
||||
EXPECT_GT(meshFilter->GetMesh()->GetSections().Size(), 0u);
|
||||
EXPECT_GT(meshFilter->GetMesh()->GetMaterials().Size(), 0u);
|
||||
EXPECT_EQ(meshFilter->GetMeshPath(), "Assets/Models/backpack/backpack.obj");
|
||||
for (GameObject* backpackObject : backpackObjects) {
|
||||
ASSERT_NE(backpackObject, nullptr);
|
||||
auto* meshFilter = backpackObject->GetComponent<MeshFilterComponent>();
|
||||
auto* meshRenderer = backpackObject->GetComponent<MeshRendererComponent>();
|
||||
ASSERT_NE(meshFilter, nullptr);
|
||||
ASSERT_NE(meshRenderer, nullptr);
|
||||
ASSERT_NE(meshFilter->GetMesh(), nullptr);
|
||||
EXPECT_TRUE(meshFilter->GetMesh()->IsValid());
|
||||
EXPECT_GT(meshFilter->GetMesh()->GetVertexCount(), 0u);
|
||||
EXPECT_GT(meshFilter->GetMesh()->GetSections().Size(), 0u);
|
||||
EXPECT_GT(meshFilter->GetMesh()->GetMaterials().Size(), 0u);
|
||||
EXPECT_EQ(meshFilter->GetMeshPath(), "Assets/Models/backpack/backpack.obj");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, MainSceneStaysLightweightForEditorStartup) {
|
||||
@@ -645,9 +686,384 @@ TEST(Scene_ProjectSample, MainSceneStaysLightweightForEditorStartup) {
|
||||
Scene loadedScene;
|
||||
loadedScene.Load(mainScenePath.string());
|
||||
|
||||
EXPECT_NE(loadedScene.Find("Main Camera"), nullptr);
|
||||
EXPECT_NE(loadedScene.Find("Directional Light"), nullptr);
|
||||
EXPECT_NE(loadedScene.Find("Camera"), nullptr);
|
||||
EXPECT_NE(loadedScene.Find("Light"), nullptr);
|
||||
EXPECT_NE(loadedScene.Find("Cube"), nullptr);
|
||||
EXPECT_EQ(loadedScene.Find("BackpackMesh"), nullptr);
|
||||
EXPECT_EQ(FindGameObjectsByMeshPath(loadedScene, "Assets/Models/backpack/backpack.obj").size(), 0u);
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, AsyncLoadBackpackMeshArtifactCompletes) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XCEngine::Resources::ResourceManager& resourceManager = XCEngine::Resources::ResourceManager::Get();
|
||||
resourceManager.Initialize();
|
||||
|
||||
struct ResourceManagerGuard {
|
||||
XCEngine::Resources::ResourceManager* manager = nullptr;
|
||||
~ResourceManagerGuard() {
|
||||
if (manager != nullptr) {
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
} resourceManagerGuard{ &resourceManager };
|
||||
|
||||
struct CurrentPathGuard {
|
||||
fs::path previousPath;
|
||||
~CurrentPathGuard() {
|
||||
if (!previousPath.empty()) {
|
||||
fs::current_path(previousPath);
|
||||
}
|
||||
}
|
||||
} currentPathGuard{ fs::current_path() };
|
||||
|
||||
const fs::path repositoryRoot = GetRepositoryRoot();
|
||||
const fs::path projectRoot = repositoryRoot / "project";
|
||||
const fs::path assimpDllPath = repositoryRoot / "engine" / "third_party" / "assimp" / "bin" / "assimp-vc143-mt.dll";
|
||||
|
||||
ASSERT_TRUE(fs::exists(assimpDllPath));
|
||||
|
||||
#ifdef _WIN32
|
||||
struct DllGuard {
|
||||
HMODULE module = nullptr;
|
||||
~DllGuard() {
|
||||
if (module != nullptr) {
|
||||
FreeLibrary(module);
|
||||
}
|
||||
}
|
||||
} dllGuard;
|
||||
dllGuard.module = LoadLibraryW(assimpDllPath.wstring().c_str());
|
||||
ASSERT_NE(dllGuard.module, nullptr);
|
||||
#endif
|
||||
|
||||
fs::current_path(projectRoot);
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
bool callbackInvoked = false;
|
||||
XCEngine::Resources::LoadResult completedResult;
|
||||
resourceManager.LoadAsync(
|
||||
"Assets/Models/backpack/backpack.obj",
|
||||
XCEngine::Resources::ResourceType::Mesh,
|
||||
[&](XCEngine::Resources::LoadResult result) {
|
||||
callbackInvoked = true;
|
||||
completedResult = std::move(result);
|
||||
});
|
||||
|
||||
EXPECT_GT(resourceManager.GetAsyncPendingCount(), 0u);
|
||||
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(resourceManager, std::chrono::milliseconds(10000)));
|
||||
EXPECT_TRUE(callbackInvoked);
|
||||
ASSERT_TRUE(completedResult);
|
||||
ASSERT_NE(completedResult.resource, nullptr);
|
||||
|
||||
auto* mesh = static_cast<XCEngine::Resources::Mesh*>(completedResult.resource);
|
||||
ASSERT_NE(mesh, nullptr);
|
||||
EXPECT_TRUE(mesh->IsValid());
|
||||
EXPECT_GT(mesh->GetVertexCount(), 0u);
|
||||
EXPECT_GT(mesh->GetSections().Size(), 0u);
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, AsyncLoadBuiltinMeshAndMaterialComplete) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XCEngine::Resources::ResourceManager& resourceManager = XCEngine::Resources::ResourceManager::Get();
|
||||
resourceManager.Initialize();
|
||||
|
||||
struct ResourceManagerGuard {
|
||||
XCEngine::Resources::ResourceManager* manager = nullptr;
|
||||
~ResourceManagerGuard() {
|
||||
if (manager != nullptr) {
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
} resourceManagerGuard{ &resourceManager };
|
||||
|
||||
const fs::path repositoryRoot = GetRepositoryRoot();
|
||||
const fs::path projectRoot = repositoryRoot / "project";
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
bool meshCallbackInvoked = false;
|
||||
bool materialCallbackInvoked = false;
|
||||
XCEngine::Resources::LoadResult meshResult;
|
||||
XCEngine::Resources::LoadResult materialResult;
|
||||
|
||||
resourceManager.LoadAsync(
|
||||
"builtin://meshes/cube",
|
||||
XCEngine::Resources::ResourceType::Mesh,
|
||||
[&](XCEngine::Resources::LoadResult result) {
|
||||
meshCallbackInvoked = true;
|
||||
meshResult = std::move(result);
|
||||
});
|
||||
resourceManager.LoadAsync(
|
||||
"builtin://materials/default-primitive",
|
||||
XCEngine::Resources::ResourceType::Material,
|
||||
[&](XCEngine::Resources::LoadResult result) {
|
||||
materialCallbackInvoked = true;
|
||||
materialResult = std::move(result);
|
||||
});
|
||||
|
||||
EXPECT_GE(resourceManager.GetAsyncPendingCount(), 2u);
|
||||
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(resourceManager, std::chrono::milliseconds(10000)));
|
||||
EXPECT_TRUE(meshCallbackInvoked);
|
||||
EXPECT_TRUE(materialCallbackInvoked);
|
||||
ASSERT_TRUE(meshResult);
|
||||
ASSERT_TRUE(materialResult);
|
||||
ASSERT_NE(meshResult.resource, nullptr);
|
||||
ASSERT_NE(materialResult.resource, nullptr);
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, AsyncLoadBuiltinMeshCompletes) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XCEngine::Resources::ResourceManager& resourceManager = XCEngine::Resources::ResourceManager::Get();
|
||||
resourceManager.Initialize();
|
||||
|
||||
struct ResourceManagerGuard {
|
||||
XCEngine::Resources::ResourceManager* manager = nullptr;
|
||||
~ResourceManagerGuard() {
|
||||
if (manager != nullptr) {
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
} resourceManagerGuard{ &resourceManager };
|
||||
|
||||
const fs::path repositoryRoot = GetRepositoryRoot();
|
||||
const fs::path projectRoot = repositoryRoot / "project";
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
bool callbackInvoked = false;
|
||||
XCEngine::Resources::LoadResult result;
|
||||
resourceManager.LoadAsync(
|
||||
"builtin://meshes/cube",
|
||||
XCEngine::Resources::ResourceType::Mesh,
|
||||
[&](XCEngine::Resources::LoadResult loadResult) {
|
||||
callbackInvoked = true;
|
||||
result = std::move(loadResult);
|
||||
});
|
||||
|
||||
EXPECT_GT(resourceManager.GetAsyncPendingCount(), 0u);
|
||||
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(resourceManager, std::chrono::milliseconds(10000)));
|
||||
EXPECT_TRUE(callbackInvoked);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_NE(result.resource, nullptr);
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, AsyncLoadBuiltinMaterialCompletes) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XCEngine::Resources::ResourceManager& resourceManager = XCEngine::Resources::ResourceManager::Get();
|
||||
resourceManager.Initialize();
|
||||
|
||||
struct ResourceManagerGuard {
|
||||
XCEngine::Resources::ResourceManager* manager = nullptr;
|
||||
~ResourceManagerGuard() {
|
||||
if (manager != nullptr) {
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
} resourceManagerGuard{ &resourceManager };
|
||||
|
||||
const fs::path repositoryRoot = GetRepositoryRoot();
|
||||
const fs::path projectRoot = repositoryRoot / "project";
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
bool callbackInvoked = false;
|
||||
XCEngine::Resources::LoadResult result;
|
||||
resourceManager.LoadAsync(
|
||||
"builtin://materials/default-primitive",
|
||||
XCEngine::Resources::ResourceType::Material,
|
||||
[&](XCEngine::Resources::LoadResult loadResult) {
|
||||
callbackInvoked = true;
|
||||
result = std::move(loadResult);
|
||||
});
|
||||
|
||||
EXPECT_GT(resourceManager.GetAsyncPendingCount(), 0u);
|
||||
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(resourceManager, std::chrono::milliseconds(10000)));
|
||||
EXPECT_TRUE(callbackInvoked);
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_NE(result.resource, nullptr);
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, DeferredLoadBackpackSceneEventuallyRestoresBackpackMesh) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XCEngine::Resources::ResourceManager& resourceManager = XCEngine::Resources::ResourceManager::Get();
|
||||
resourceManager.Initialize();
|
||||
|
||||
struct ResourceManagerGuard {
|
||||
XCEngine::Resources::ResourceManager* manager = nullptr;
|
||||
~ResourceManagerGuard() {
|
||||
if (manager != nullptr) {
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
} resourceManagerGuard{ &resourceManager };
|
||||
|
||||
struct CurrentPathGuard {
|
||||
fs::path previousPath;
|
||||
~CurrentPathGuard() {
|
||||
if (!previousPath.empty()) {
|
||||
fs::current_path(previousPath);
|
||||
}
|
||||
}
|
||||
} currentPathGuard{ fs::current_path() };
|
||||
|
||||
const fs::path repositoryRoot = GetRepositoryRoot();
|
||||
const fs::path projectRoot = repositoryRoot / "project";
|
||||
const fs::path backpackScenePath = projectRoot / "Assets" / "Scenes" / "Backpack.xc";
|
||||
const fs::path assimpDllPath = repositoryRoot / "engine" / "third_party" / "assimp" / "bin" / "assimp-vc143-mt.dll";
|
||||
|
||||
if (!fs::exists(backpackScenePath)) {
|
||||
GTEST_SKIP() << "Backpack sample scene is not available in the local project fixture.";
|
||||
}
|
||||
ASSERT_TRUE(fs::exists(assimpDllPath));
|
||||
|
||||
#ifdef _WIN32
|
||||
struct DllGuard {
|
||||
HMODULE module = nullptr;
|
||||
~DllGuard() {
|
||||
if (module != nullptr) {
|
||||
FreeLibrary(module);
|
||||
}
|
||||
}
|
||||
} dllGuard;
|
||||
dllGuard.module = LoadLibraryW(assimpDllPath.wstring().c_str());
|
||||
ASSERT_NE(dllGuard.module, nullptr);
|
||||
#endif
|
||||
|
||||
fs::current_path(projectRoot);
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
Scene loadedScene;
|
||||
{
|
||||
XCEngine::Resources::ResourceManager::ScopedDeferredSceneLoad deferredLoadScope;
|
||||
loadedScene.Load(backpackScenePath.string());
|
||||
}
|
||||
|
||||
std::vector<GameObject*> backpackObjects =
|
||||
FindGameObjectsByMeshPath(loadedScene, "Assets/Models/backpack/backpack.obj");
|
||||
ASSERT_EQ(backpackObjects.size(), 2u);
|
||||
|
||||
std::vector<MeshFilterComponent*> backpackMeshFilters;
|
||||
std::vector<MeshRendererComponent*> backpackMeshRenderers;
|
||||
for (GameObject* backpackObject : backpackObjects) {
|
||||
ASSERT_NE(backpackObject, nullptr);
|
||||
auto* meshFilter = backpackObject->GetComponent<MeshFilterComponent>();
|
||||
auto* meshRenderer = backpackObject->GetComponent<MeshRendererComponent>();
|
||||
ASSERT_NE(meshFilter, nullptr);
|
||||
ASSERT_NE(meshRenderer, nullptr);
|
||||
EXPECT_EQ(meshFilter->GetMeshPath(), "Assets/Models/backpack/backpack.obj");
|
||||
EXPECT_EQ(meshFilter->GetMesh(), nullptr);
|
||||
backpackMeshFilters.push_back(meshFilter);
|
||||
backpackMeshRenderers.push_back(meshRenderer);
|
||||
}
|
||||
|
||||
EXPECT_GT(resourceManager.GetAsyncPendingCount(), 0u);
|
||||
|
||||
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(resourceManager));
|
||||
EXPECT_EQ(resourceManager.GetAsyncPendingCount(), 0u);
|
||||
ASSERT_EQ(backpackMeshFilters.size(), 2u);
|
||||
ASSERT_EQ(backpackMeshRenderers.size(), 2u);
|
||||
ASSERT_NE(backpackMeshFilters[0]->GetMesh(), nullptr);
|
||||
ASSERT_NE(backpackMeshFilters[1]->GetMesh(), nullptr);
|
||||
EXPECT_EQ(backpackMeshFilters[0]->GetMesh(), backpackMeshFilters[1]->GetMesh());
|
||||
EXPECT_TRUE(backpackMeshFilters[0]->GetMesh()->IsValid());
|
||||
EXPECT_TRUE(backpackMeshFilters[1]->GetMesh()->IsValid());
|
||||
EXPECT_GT(backpackMeshFilters[0]->GetMesh()->GetVertexCount(), 0u);
|
||||
EXPECT_GT(backpackMeshFilters[1]->GetMesh()->GetVertexCount(), 0u);
|
||||
EXPECT_EQ(backpackMeshRenderers[0]->GetMaterialCount(), 0u);
|
||||
EXPECT_EQ(backpackMeshRenderers[1]->GetMaterialCount(), 0u);
|
||||
}
|
||||
|
||||
TEST(Scene_ProjectSample, DeferredLoadBackpackSceneEventuallyProducesVisibleRenderItems) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XCEngine::Resources::ResourceManager& resourceManager = XCEngine::Resources::ResourceManager::Get();
|
||||
resourceManager.Initialize();
|
||||
|
||||
struct ResourceManagerGuard {
|
||||
XCEngine::Resources::ResourceManager* manager = nullptr;
|
||||
~ResourceManagerGuard() {
|
||||
if (manager != nullptr) {
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
} resourceManagerGuard{ &resourceManager };
|
||||
|
||||
struct CurrentPathGuard {
|
||||
fs::path previousPath;
|
||||
~CurrentPathGuard() {
|
||||
if (!previousPath.empty()) {
|
||||
fs::current_path(previousPath);
|
||||
}
|
||||
}
|
||||
} currentPathGuard{ fs::current_path() };
|
||||
|
||||
const fs::path repositoryRoot = GetRepositoryRoot();
|
||||
const fs::path projectRoot = repositoryRoot / "project";
|
||||
const fs::path backpackScenePath = projectRoot / "Assets" / "Scenes" / "Backpack.xc";
|
||||
const fs::path assimpDllPath = repositoryRoot / "engine" / "third_party" / "assimp" / "bin" / "assimp-vc143-mt.dll";
|
||||
|
||||
if (!fs::exists(backpackScenePath)) {
|
||||
GTEST_SKIP() << "Backpack sample scene is not available in the local project fixture.";
|
||||
}
|
||||
ASSERT_TRUE(fs::exists(assimpDllPath));
|
||||
|
||||
#ifdef _WIN32
|
||||
struct DllGuard {
|
||||
HMODULE module = nullptr;
|
||||
~DllGuard() {
|
||||
if (module != nullptr) {
|
||||
FreeLibrary(module);
|
||||
}
|
||||
}
|
||||
} dllGuard;
|
||||
dllGuard.module = LoadLibraryW(assimpDllPath.wstring().c_str());
|
||||
ASSERT_NE(dllGuard.module, nullptr);
|
||||
#endif
|
||||
|
||||
fs::current_path(projectRoot);
|
||||
resourceManager.SetResourceRoot(projectRoot.string().c_str());
|
||||
|
||||
Scene loadedScene;
|
||||
{
|
||||
XCEngine::Resources::ResourceManager::ScopedDeferredSceneLoad deferredLoadScope;
|
||||
loadedScene.Load(backpackScenePath.string());
|
||||
}
|
||||
|
||||
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(resourceManager, std::chrono::milliseconds(10000)));
|
||||
|
||||
const std::vector<GameObject*> backpackObjects =
|
||||
FindGameObjectsByMeshPath(loadedScene, "Assets/Models/backpack/backpack.obj");
|
||||
ASSERT_EQ(backpackObjects.size(), 2u);
|
||||
|
||||
std::vector<MeshFilterComponent*> backpackMeshFilters;
|
||||
for (GameObject* backpackObject : backpackObjects) {
|
||||
ASSERT_NE(backpackObject, nullptr);
|
||||
auto* meshFilter = backpackObject->GetComponent<MeshFilterComponent>();
|
||||
ASSERT_NE(meshFilter, nullptr);
|
||||
ASSERT_NE(meshFilter->GetMesh(), nullptr);
|
||||
backpackMeshFilters.push_back(meshFilter);
|
||||
}
|
||||
|
||||
XCEngine::Rendering::RenderSceneExtractor extractor;
|
||||
const XCEngine::Rendering::RenderSceneData renderScene =
|
||||
extractor.Extract(loadedScene, nullptr, 1280u, 720u);
|
||||
|
||||
ASSERT_TRUE(renderScene.HasCamera());
|
||||
ASSERT_FALSE(renderScene.visibleItems.empty());
|
||||
|
||||
std::vector<bool> foundVisibleBackpack(backpackObjects.size(), false);
|
||||
for (const auto& visibleItem : renderScene.visibleItems) {
|
||||
for (size_t index = 0; index < backpackObjects.size(); ++index) {
|
||||
if (visibleItem.gameObject == backpackObjects[index] &&
|
||||
visibleItem.mesh == backpackMeshFilters[index]->GetMesh()) {
|
||||
foundVisibleBackpack[index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(foundVisibleBackpack[0]);
|
||||
EXPECT_TRUE(foundVisibleBackpack[1]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user