/// setup planes
const auto d = 4;
const auto dist = plane_t::distance_t(d);
const std::vector<plane_t> planes{plane_t{1, 0, 0, dist},   plane_t{0, 1, 0, dist},   plane_t{0, 0, 1, dist},
                                  plane_t{-1, 0, 0, -dist}, plane_t{0, -1, 0, -dist}, plane_t{0, 0, -1, -dist}};
const auto bounds = tg::aabb<3, geometry_t::pos_scalar_t>(tg::pos3(-(d + 2)), tg::pos3((d + 2)));

/// create and fill bsp
bsp_t bsp;
bsp.set_bounds(bounds);
auto prev = -1;
for (auto const& p : planes)
{
    auto inner = bsp.alloc_node();
    auto out = bsp.alloc_out();
    auto pidx = bsp.planes.add(p);
    bsp.nodes[size_t(inner)].plane_idx = pidx;
    bsp.nodes[size_t(inner)].child_pos = out;
    if (prev >= 0)
        bsp.nodes[size_t(prev)].child_neg = inner;
    prev = inner;
}
bsp.nodes[size_t(prev)].child_neg = bsp.alloc_in();

ob::view(bsp, ob::bsp_view_config().explosion_all());

pm::Mesh conv_hull;
auto conv_pos = pm::vertex_attribute<tg::pos3>(conv_hull);

/// extract
auto extractor = std::make_unique<ob::MeshExtractor<bsp_small_config<geometry_t, int>>>();
extractor->extract(bsp);
extractor->to_polymesh(conv_hull, conv_pos);

std::vector<pm::vertex_handle> to_delete;
for (auto s = 0; s < extractor->get_submesh_count(); ++s)
{
    if (extractor->submesh_label[s] == ob::bsp_node<>::label_in)
        continue;

    auto h0 = conv_hull.halfedges()[extractor->submesh_any_halfedge[s]];
    for (auto v : pm::vertex_component(h0.vertex_to()))
        to_delete.push_back(v);
}
for (auto v : to_delete)
    conv_hull.vertices().remove(v);
for (auto e : conv_hull.edges())
    TG_ASSERT(!e.is_boundary());

std::cout << "deleted: " << to_delete.size() << "/" << conv_pos.size() << std::endl;