130 lines
5.2 KiB
C++
130 lines
5.2 KiB
C++
#include "Test_Fixtures.h"
|
|
|
|
#include <render_3D/base/Object_Access_p.h>
|
|
#include <render_3D/scene/Scene.h>
|
|
#include <render_3D/scene/Scene_Frame.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iterator>
|
|
#include <string>
|
|
#include <type_traits>
|
|
|
|
namespace renderive::render_3D {
|
|
|
|
TEST(Render3DSceneFrame, AttachOwnsMeshUntilDetach) {
|
|
Scene scene;
|
|
auto mesh = test::mesh_owner();
|
|
const auto id = mesh->identity();
|
|
std::weak_ptr<Mesh> lifetime = mesh.share();
|
|
|
|
scene.update([&](Scene_Edit& edit) { edit.attach(mesh); });
|
|
mesh.reset();
|
|
EXPECT_FALSE(lifetime.expired());
|
|
|
|
const auto frame = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(frame.mesh_structure_changes.size(), 1U);
|
|
EXPECT_EQ(frame.mesh_structure_changes.front().operation, Mesh_Structure_Operation::attach);
|
|
ASSERT_EQ(frame.mesh_updates.size(), 1U);
|
|
EXPECT_EQ(frame.mesh_updates.front().id, id);
|
|
EXPECT_FALSE(lifetime.expired());
|
|
|
|
scene.update([&](Scene_Edit& edit) { edit.detach(id); });
|
|
EXPECT_TRUE(lifetime.expired());
|
|
const auto detached = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(detached.mesh_structure_changes.size(), 1U);
|
|
EXPECT_EQ(detached.mesh_structure_changes.front().operation, Mesh_Structure_Operation::detach);
|
|
}
|
|
|
|
|
|
TEST(Render3DSceneFrame, AttachOwnsTextUntilDetach) {
|
|
Scene scene;
|
|
auto text = test::text_owner();
|
|
const auto id = text->identity();
|
|
std::weak_ptr<Text> lifetime = text.share();
|
|
scene.update([&](Scene_Edit& edit) { edit.attach(text); });
|
|
text.reset();
|
|
EXPECT_FALSE(lifetime.expired());
|
|
const auto frame = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(frame.text_structure_changes.size(), 1U);
|
|
ASSERT_EQ(frame.text_updates.size(), 1U);
|
|
EXPECT_EQ(frame.text_structure_changes.front().operation, Text_Structure_Operation::attach);
|
|
EXPECT_EQ(frame.text_updates.front().id, id);
|
|
scene.update([&](Scene_Edit& edit) { edit.detach(id); });
|
|
EXPECT_TRUE(lifetime.expired());
|
|
const auto detached = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(detached.text_structure_changes.size(), 1U);
|
|
EXPECT_EQ(detached.text_structure_changes.front().operation, Text_Structure_Operation::detach);
|
|
}
|
|
|
|
TEST(Render3DSceneFrame, PublishedFrameIsIndependentFromLaterCacheMutation) {
|
|
Scene scene;
|
|
auto mesh = test::mesh_owner();
|
|
scene.update([&](Scene_Edit& edit) { edit.attach(mesh); });
|
|
const auto first = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(first.mesh_updates.size(), 1U);
|
|
|
|
Matrix4 translated;
|
|
translated.elements[13] = 3.0F;
|
|
mesh->place(translated);
|
|
EXPECT_NE(first.mesh_updates.front().transform, translated);
|
|
|
|
const auto second = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(second.mesh_updates.size(), 1U);
|
|
EXPECT_EQ(second.mesh_updates.front().transform, translated);
|
|
EXPECT_NE(first.mesh_updates.front().transform, second.mesh_updates.front().transform);
|
|
}
|
|
|
|
TEST(Render3DSceneFrame, ImplRelationshipsBecomePointerFreeFrameValues) {
|
|
Scene scene;
|
|
auto image = std::make_shared<Image_Data>();
|
|
image->width = 1;
|
|
image->height = 1;
|
|
image->rgba8 = {255, 255, 255, 255};
|
|
auto texture = renderive_Owner<Texture>::make(Texture_Properties{image});
|
|
auto material = test::material_owner();
|
|
material->use_texture(texture);
|
|
auto mesh = test::mesh_owner(test::triangle_geometry(), material);
|
|
auto camera = test::camera_owner();
|
|
scene.update([&](Scene_Edit& edit) {
|
|
edit.attach(mesh);
|
|
edit.set_camera(camera);
|
|
});
|
|
|
|
const auto frame = detail::Object_Access::make_frame(scene);
|
|
ASSERT_EQ(frame.texture_updates.size(), 1U);
|
|
ASSERT_EQ(frame.material_updates.size(), 1U);
|
|
ASSERT_EQ(frame.mesh_updates.size(), 1U);
|
|
ASSERT_TRUE(frame.camera_change);
|
|
EXPECT_TRUE(frame.camera_change->active);
|
|
EXPECT_EQ(frame.material_updates.front().texture_id, texture->identity());
|
|
EXPECT_EQ(frame.mesh_updates.front().material_id, material->identity());
|
|
EXPECT_EQ(frame.mesh_updates.front().geometry, detail::Object_Access::rendered(*mesh).properties.geometry);
|
|
|
|
static_assert(!std::is_pointer_v<decltype(Mesh_Frame_State::geometry)>);
|
|
static_assert(std::is_copy_constructible_v<Scene3D_Frame_Data>);
|
|
}
|
|
|
|
TEST(Render3DSceneFrame, PublicFrameHeaderDoesNotExposeImplOrBackendTypes) {
|
|
const auto path = std::filesystem::path(__FILE__).parent_path().parent_path() /
|
|
"render_3D" / "scene" / "Scene_Frame.h";
|
|
std::ifstream input(path, std::ios::binary);
|
|
ASSERT_TRUE(input.good());
|
|
const std::string source{
|
|
std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>()};
|
|
EXPECT_EQ(source.find("Dvz"), std::string::npos);
|
|
EXPECT_EQ(source.find("::Impl"), std::string::npos);
|
|
EXPECT_EQ(source.find("Snapshot"), std::string::npos);
|
|
EXPECT_EQ(source.find("Mesh*"), std::string::npos);
|
|
EXPECT_EQ(source.find("Camera*"), std::string::npos);
|
|
EXPECT_EQ(source.find("Material*"), std::string::npos);
|
|
EXPECT_EQ(source.find("Texture*"), std::string::npos);
|
|
EXPECT_EQ(source.find("Text*"), std::string::npos);
|
|
EXPECT_EQ(source.find("renderive_Owner"), std::string::npos);
|
|
EXPECT_EQ(source.find("_p.h"), std::string::npos);
|
|
}
|
|
|
|
} // namespace renderive::render_3D
|