139 lines
3.3 KiB
C++
139 lines
3.3 KiB
C++
#pragma once
|
|
|
|
#include <psemek/geom/box.hpp>
|
|
#include <psemek/geom/simplex.hpp>
|
|
|
|
#include <vector>
|
|
#include <cstdint>
|
|
|
|
namespace psemek::geom
|
|
{
|
|
|
|
template <typename T, std::size_t N>
|
|
std::vector<point<T, N>> vertices(box<T, N> const & b)
|
|
{
|
|
std::vector<point<T, N>> result;
|
|
|
|
for (std::size_t mask = 0; mask < (1 << N); ++mask)
|
|
{
|
|
point<T, N> p;
|
|
for (std::size_t i = 0; i < N; ++i)
|
|
{
|
|
p[i] = (mask & (1 << i)) ? b[i].max : b[i].min;
|
|
}
|
|
result.push_back(p);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename Index = std::uint32_t, typename T, std::size_t N>
|
|
std::vector<segment<Index>> edges(box<T, N> const &)
|
|
{
|
|
static_assert(N > 0); // who knows?..
|
|
|
|
std::vector<segment<Index>> result;
|
|
|
|
for (std::size_t i = 0; i < N; ++i)
|
|
{
|
|
for (std::size_t mask = 0; mask < (1 << (N - 1)); ++mask)
|
|
{
|
|
auto const lo = mask & ((1 << i) - 1);
|
|
auto const hi = mask ^ lo;
|
|
|
|
auto const idx0 = lo | (hi << 1);
|
|
auto const idx1 = idx0 | (1 << i);
|
|
|
|
result.push_back({static_cast<Index>(idx0), static_cast<Index>(idx1)});
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename Index = std::uint32_t, typename T>
|
|
std::vector<triangle<Index>> faces(box<T, 2> const &)
|
|
{
|
|
std::vector<triangle<Index>> result;
|
|
result.push_back({0, 1, 2});
|
|
result.push_back({2, 1, 3});
|
|
return result;
|
|
}
|
|
|
|
template <typename Index = std::uint32_t, typename T>
|
|
std::vector<triangle<Index>> faces(box<T, 3> const &)
|
|
{
|
|
std::vector<triangle<Index>> result;
|
|
// -Z
|
|
result.push_back({0, 2, 1});
|
|
result.push_back({1, 2, 3});
|
|
// +Z
|
|
result.push_back({4, 5, 6});
|
|
result.push_back({6, 5, 7});
|
|
// -Y
|
|
result.push_back({0, 1, 4});
|
|
result.push_back({4, 1, 5});
|
|
// +Y
|
|
result.push_back({2, 6, 3});
|
|
result.push_back({6, 7, 3});
|
|
// -X
|
|
result.push_back({0, 4, 2});
|
|
result.push_back({2, 4, 6});
|
|
// +X
|
|
result.push_back({1, 3, 5});
|
|
result.push_back({3, 7, 5});
|
|
return result;
|
|
}
|
|
|
|
template <typename Vertex, typename Index, std::size_t N>
|
|
std::vector<simplex<Vertex, N>> deindex(std::vector<Vertex> const & vertices, std::vector<simplex<Index, N>> const & simplices)
|
|
{
|
|
std::vector<simplex<Vertex, N>> result;
|
|
result.reserve(simplices.size());
|
|
for (auto const & s : simplices)
|
|
{
|
|
result.emplace_back();
|
|
for (std::size_t i = 0; i <= N; ++i)
|
|
result.back()[i] = vertices[s[i]];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
namespace detail
|
|
{
|
|
|
|
template <typename F, typename G, std::size_t ... I>
|
|
auto map_index_sequence(F && f, G && g, std::index_sequence<I...>)
|
|
{
|
|
return f(g(I)...);
|
|
}
|
|
|
|
}
|
|
|
|
template <typename T, std::size_t N, typename Index>
|
|
std::vector<vector<T, N + 1>> flat_normals(std::vector<point<T, N + 1>> const & vertices, std::vector<simplex<Index, N>> const & simplices)
|
|
{
|
|
std::vector<vector<T, N + 1>> result;
|
|
result.reserve(simplices.size());
|
|
for (auto const & s : simplices)
|
|
{
|
|
auto const n = detail::map_index_sequence([&](auto const & ... vs){ return normal(vs...); }, [&](std::size_t i){ return vertices[s[i]]; }, std::make_index_sequence<N + 1>{});
|
|
result.push_back(n);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename Index = std::uint32_t, typename Vertex>
|
|
std::vector<triangle<Index>> triangulate_convex(std::vector<Vertex> const & v)
|
|
{
|
|
std::vector<triangle<Index>> result;
|
|
|
|
for (std::size_t i = 1; i + 1 < v.size(); ++i)
|
|
{
|
|
result.push_back({static_cast<Index>(0), static_cast<Index>(i), static_cast<Index>(i + 1)});
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|