172 lines
6.2 KiB
C++
172 lines
6.2 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include <XCEngine/Components/GameObject.h>
|
|
#include <XCEngine/Components/VolumeRendererComponent.h>
|
|
#include <XCEngine/Core/Asset/IResource.h>
|
|
#include <XCEngine/Core/Asset/ResourceManager.h>
|
|
#include <XCEngine/Core/IO/IResourceLoader.h>
|
|
#include <XCEngine/Core/Math/Bounds.h>
|
|
#include <XCEngine/Resources/Material/Material.h>
|
|
#include <XCEngine/Resources/Volume/VolumeField.h>
|
|
|
|
#include <chrono>
|
|
#include <sstream>
|
|
#include <thread>
|
|
|
|
using namespace XCEngine::Components;
|
|
using namespace XCEngine::Math;
|
|
using namespace XCEngine::Resources;
|
|
|
|
namespace {
|
|
|
|
VolumeField* CreateTestVolumeField(const char* name, const char* path) {
|
|
auto* volumeField = new VolumeField();
|
|
IResource::ConstructParams params = {};
|
|
params.name = name;
|
|
params.path = path;
|
|
params.guid = ResourceGUID::Generate(path);
|
|
volumeField->Initialize(params);
|
|
|
|
const unsigned char payload[8] = { 1, 3, 5, 7, 9, 11, 13, 15 };
|
|
EXPECT_TRUE(volumeField->Create(
|
|
VolumeStorageKind::NanoVDB,
|
|
payload,
|
|
sizeof(payload),
|
|
Bounds(Vector3::Zero(), Vector3::One()),
|
|
Vector3(0.5f, 0.5f, 0.5f)));
|
|
return volumeField;
|
|
}
|
|
|
|
Material* CreateTestMaterial(const char* name, const char* path) {
|
|
auto* material = new Material();
|
|
IResource::ConstructParams params = {};
|
|
params.name = name;
|
|
params.path = path;
|
|
params.guid = ResourceGUID::Generate(path);
|
|
material->Initialize(params);
|
|
return material;
|
|
}
|
|
|
|
class FakeAsyncVolumeFieldLoader : public IResourceLoader {
|
|
public:
|
|
ResourceType GetResourceType() const override { return ResourceType::VolumeField; }
|
|
|
|
XCEngine::Containers::Array<XCEngine::Containers::String> GetSupportedExtensions() const override {
|
|
XCEngine::Containers::Array<XCEngine::Containers::String> extensions;
|
|
extensions.PushBack("nvdb");
|
|
return extensions;
|
|
}
|
|
|
|
bool CanLoad(const XCEngine::Containers::String& path) const override {
|
|
(void)path;
|
|
return true;
|
|
}
|
|
|
|
LoadResult Load(
|
|
const XCEngine::Containers::String& path,
|
|
const ImportSettings* settings = nullptr) override {
|
|
(void)settings;
|
|
return LoadResult(CreateTestVolumeField("AsyncVolume", path.CStr()));
|
|
}
|
|
|
|
ImportSettings* GetDefaultSettings() const override {
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
bool PumpAsyncLoadsUntilIdle(
|
|
ResourceManager& manager,
|
|
std::chrono::milliseconds timeout = std::chrono::milliseconds(2000)) {
|
|
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();
|
|
}
|
|
|
|
TEST(VolumeRendererComponent_Test, SetResourcesCachesHandlesPathsAndFlags) {
|
|
GameObject gameObject("VolumeHolder");
|
|
auto* component = gameObject.AddComponent<VolumeRendererComponent>();
|
|
VolumeField* volumeField = CreateTestVolumeField("Cloud", "Volumes/cloud.nvdb");
|
|
Material* material = CreateTestMaterial("VolumeMaterial", "Materials/volume.mat");
|
|
|
|
component->SetVolumeField(volumeField);
|
|
component->SetMaterial(material);
|
|
component->SetCastShadows(false);
|
|
component->SetReceiveShadows(false);
|
|
|
|
EXPECT_EQ(component->GetVolumeField(), volumeField);
|
|
EXPECT_EQ(component->GetVolumeFieldPath(), "Volumes/cloud.nvdb");
|
|
EXPECT_EQ(component->GetMaterial(), material);
|
|
EXPECT_EQ(component->GetMaterialPath(), "Materials/volume.mat");
|
|
EXPECT_FALSE(component->GetCastShadows());
|
|
EXPECT_FALSE(component->GetReceiveShadows());
|
|
|
|
component->ClearVolumeField();
|
|
component->ClearMaterial();
|
|
delete volumeField;
|
|
delete material;
|
|
}
|
|
|
|
TEST(VolumeRendererComponent_Test, SerializeAndDeserializePreservesVirtualPathsAndFlags) {
|
|
VolumeRendererComponent source;
|
|
source.SetVolumeFieldPath("test://volumes/cloud.nvdb");
|
|
source.SetMaterialPath("test://materials/volume.material");
|
|
source.SetCastShadows(false);
|
|
source.SetReceiveShadows(true);
|
|
|
|
std::stringstream stream;
|
|
source.Serialize(stream);
|
|
const std::string serialized = stream.str();
|
|
EXPECT_NE(serialized.find("volumePath=test://volumes/cloud.nvdb;"), std::string::npos);
|
|
EXPECT_NE(serialized.find("materialPath=test://materials/volume.material;"), std::string::npos);
|
|
EXPECT_NE(serialized.find("castShadows=0;"), std::string::npos);
|
|
EXPECT_NE(serialized.find("receiveShadows=1;"), std::string::npos);
|
|
|
|
VolumeRendererComponent target;
|
|
std::stringstream deserializeStream(serialized);
|
|
target.Deserialize(deserializeStream);
|
|
|
|
EXPECT_EQ(target.GetVolumeFieldPath(), "test://volumes/cloud.nvdb");
|
|
EXPECT_EQ(target.GetMaterialPath(), "test://materials/volume.material");
|
|
EXPECT_FALSE(target.GetCastShadows());
|
|
EXPECT_TRUE(target.GetReceiveShadows());
|
|
EXPECT_FALSE(target.GetVolumeFieldAssetRef().IsValid());
|
|
EXPECT_FALSE(target.GetMaterialAssetRef().IsValid());
|
|
}
|
|
|
|
TEST(VolumeRendererComponent_Test, DeferredSceneDeserializeLoadsVolumeFieldAsyncByPath) {
|
|
ResourceManager& manager = ResourceManager::Get();
|
|
manager.Initialize();
|
|
|
|
IResourceLoader* originalLoader = manager.GetLoader(ResourceType::VolumeField);
|
|
FakeAsyncVolumeFieldLoader fakeLoader;
|
|
manager.RegisterLoader(&fakeLoader);
|
|
|
|
VolumeRendererComponent target;
|
|
const auto pendingBeforeDeserialize = manager.GetAsyncPendingCount();
|
|
{
|
|
ResourceManager::ScopedDeferredSceneLoad deferredLoadScope;
|
|
EXPECT_TRUE(manager.IsDeferredSceneLoadEnabled());
|
|
std::stringstream stream(
|
|
"volumePath=test://volumes/async.nvdb;volumeRef=;materialRef=;castShadows=1;receiveShadows=1;");
|
|
target.Deserialize(stream);
|
|
}
|
|
|
|
EXPECT_EQ(target.GetVolumeFieldPath(), "test://volumes/async.nvdb");
|
|
EXPECT_EQ(target.GetVolumeField(), nullptr);
|
|
EXPECT_GT(manager.GetAsyncPendingCount(), pendingBeforeDeserialize);
|
|
ASSERT_TRUE(PumpAsyncLoadsUntilIdle(manager));
|
|
ASSERT_NE(target.GetVolumeField(), nullptr);
|
|
EXPECT_EQ(target.GetVolumeFieldPath(), "test://volumes/async.nvdb");
|
|
EXPECT_EQ(target.GetVolumeField()->GetStorageKind(), VolumeStorageKind::NanoVDB);
|
|
|
|
manager.RegisterLoader(originalLoader);
|
|
manager.Shutdown();
|
|
}
|
|
|
|
} // namespace
|