#include #include #include #include namespace aethera::render_3d { namespace { template void verify_visual(Item valid, Item invalid) { EXPECT_TRUE(Visual::Specification::valid(valid)); EXPECT_FALSE(Visual::Specification::valid(invalid)); typename Visual::Builder builder; builder .template set([&](typename Visual::Frame& frame) { frame.items = {valid}; }); auto object = builder.build(); ASSERT_TRUE(object); ASSERT_TRUE(object->model_initialized()); object->template get([&](const typename Visual::Frame& frame) { ASSERT_EQ(frame.items.size(), 1U); EXPECT_EQ(frame.items.front(), valid); }); auto renderable = model_proxy_view(*object); ASSERT_TRUE(renderable); EXPECT_NO_THROW(renderable->advance()); EXPECT_TRUE(renderable->taskflow()); EXPECT_EQ(std::addressof(renderable->use()), std::addressof(Visual::Specification::datoviz_operations())); } } // namespace TEST(Render_3D_Visual, Migrated_Families_Use_Current_Model_And_Validate) { verify_visual(Point{}, Point{.diameter_px = 0.0F}); verify_visual(Splat{}, Splat{.sigma = {0.0F, 0.0F}}); verify_visual(Pixel{}, Pixel{.size_px = 0.0F}); verify_visual(Marker{}, Marker{.diameter_px = 0.0F}); verify_visual(Sphere{}, Sphere{.radius = 0.0F}); verify_visual(Segment{}, Segment{.width_px = 0.0F}); verify_visual(Vector_Glyph{}, Vector_Glyph{.width_px = 0.0F}); verify_visual(Primitive_Vertex{}, Primitive_Vertex{.position = {NAN, 0.0F, 0.0F}}); verify_visual(Mesh_Vertex{}, Mesh_Vertex{.normal = {NAN, 0.0F, 0.0F}}); verify_visual(Path_Vertex{}, Path_Vertex{.width_px = 0.0F}); verify_visual(Image{}, Image{.extent = {0.0F, 0.0F}}); verify_visual(Label{}, Label{.extent = {0.0F, 0.0F}}); verify_visual(Glyph{}, Glyph{.angle = NAN}); verify_visual(Text_Label{.text = "A"}, Text_Label{}); verify_visual(Voxel{}, Voxel{.value = NAN}); } TEST(Render_3D_Scene, Builder_Owns_Current_Renderable_Dag) { auto camera = Camera_3D::Builder{}.build(); auto axes = Axes_3D::Builder{}.build(); ASSERT_TRUE(camera); ASSERT_TRUE(axes); Dag_Relation::Builder dag_builder; dag_builder .add({1}, make_model_proxy()); auto dag = dag_builder.build(); ASSERT_TRUE(dag.has_value()); Render_Scene_3D::Builder scene_builder(*camera, *axes); scene_builder .relation([graph = std::move(*dag)](auto& relation) mutable { relation = std::move(graph); }); static_assert(std::same_as>); auto scene = scene_builder.build(); ASSERT_TRUE(scene); EXPECT_TRUE(scene->model_initialized()); auto& relation = aethera::detail::model_private(*scene).relation(); static_assert(std::same_as::Node, scene::Renderable>); std::size_t node_count{}; relation.for_each_topological([&](auto, auto&) { ++node_count; }); EXPECT_EQ(node_count, 1U); } TEST(Render_3D_Visual, Prepared_Data_Preserves_Datoviz_Attributes) { detail::Mesh_Prepared_Data mesh; detail::Mesh_Spec::prepare(std::vector{{.texture_coordinate = {0.25F, 0.75F}}}, mesh); ASSERT_EQ(mesh.texture_coordinates.size(), 1U); EXPECT_EQ(mesh.texture_coordinates.front(), (std::array{0.25F, 0.75F})); detail::Image_Prepared_Data image; detail::Image_Spec::prepare(std::vector{{.texture_rectangle = {0.1F, 0.2F, 0.8F, 0.9F}}}, image); EXPECT_EQ(image.texture_rectangles.front(), (std::array{0.1F, 0.2F, 0.8F, 0.9F})); detail::Glyph_Prepared_Data glyph; detail::Glyph_Spec::prepare(std::vector{{.bounds = {-1.0F, -2.0F, 3.0F, 4.0F}, .texture_coordinates = {0.0F, 0.1F, 0.9F, 1.0F}, .angle = 0.5F}}, glyph); EXPECT_EQ(glyph.bounds.front(), (std::array{-1.0F, -2.0F, 3.0F, 4.0F})); EXPECT_EQ(glyph.texture_coordinates.front(), (std::array{0.0F, 0.1F, 0.9F, 1.0F})); detail::Text_Prepared_Data text; detail::Text_Spec::prepare(std::vector{{.text = "dynamic", .size_px = 23.0F}}, text); ASSERT_EQ(text.strings.size(), 1U); EXPECT_EQ(text.strings.front(), "dynamic"); EXPECT_FLOAT_EQ(text.sizes.front(), 23.0F); } } // namespace aethera::render_3d