#include "Test_Fixtures.h" #include #include #include #include #include #include #include #include #include namespace renderive::render_3D { TEST(Render3DSceneFrame, AttachOwnsMeshUntilDetach) { Scene scene; auto mesh = test::mesh_owner(); const auto id = mesh->identity(); std::weak_ptr 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 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->width = 1; image->height = 1; image->rgba8 = {255, 255, 255, 255}; auto texture = renderive_Owner::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); static_assert(std::is_copy_constructible_v); } 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(input), std::istreambuf_iterator()}; 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