diff --git a/libs/pcg/include/psemek/pcg/lazy_perlin.hpp b/libs/pcg/include/psemek/pcg/lazy_perlin.hpp index 0413ef13..fbe6d4ff 100644 --- a/libs/pcg/include/psemek/pcg/lazy_perlin.hpp +++ b/libs/pcg/include/psemek/pcg/lazy_perlin.hpp @@ -59,6 +59,28 @@ namespace psemek::pcg } + template + struct lazy_perlin_view + { + using value_type = T; + static constexpr auto dimension = N; + + lazy_perlin_view() = default; + + lazy_perlin_view(std::size_t grid_size, geom::vector const & view_origin, util::array, N> subgrid) + : grid_size_(grid_size) + , origin_(view_origin) + , subgrid_(std::move(subgrid)) + {} + + T operator()(geom::vector p) const; + + private: + int grid_size_; + geom::vector origin_; + util::array, N> subgrid_; + }; + template struct lazy_perlin { @@ -74,6 +96,8 @@ namespace psemek::pcg T operator()(geom::vector p) const; + auto subview(geom::box const & box) const; + private: int const grid_size_; mutable std::unordered_map, geom::vector> grid_; @@ -133,12 +157,51 @@ namespace psemek::pcg } }; + template + T lazy_perlin_view::operator()(geom::vector p) const + { + return detail::perlin_impl(p, grid_size_, [this](auto const & c){ + return subgrid_(c - origin_); + }, [this](auto p){ + for (std::size_t i = 0; i < N; ++i) + { + p[i] = std::max(p[i], origin_[i]); + p[i] = std::min(p[i], origin_[i] + subgrid_.dim(i)); + } + return p; + }); + } + template T lazy_perlin::operator()(geom::vector p) const { return detail::perlin_impl(p, grid_size_, [this](auto const & c){ return grid_at(c); }, [](auto const & p){ return p; }); } + template + auto lazy_perlin::subview(geom::box const & box) const + { + geom::vector subgrid_origin; + std::array subgrid_dimensions; + for (std::size_t i = 0; i < N; ++i) + { + subgrid_origin[i] = std::floor(box[i].min / grid_size_); + int subgrid_max = std::ceil(box[i].max / grid_size_); + subgrid_dimensions[i] = subgrid_max - subgrid_origin[i] + 1; + } + + util::array, N> subgrid(subgrid_dimensions); + for (auto const idx : subgrid.indices()) + { + geom::vector id; + for (std::size_t i = 0; i < N; ++i) + id[i] = subgrid_origin[i] + idx[i]; + subgrid(idx) = grid_at(id); + } + + return lazy_perlin_view(grid_size_, subgrid_origin, std::move(subgrid)); + } + template T bounded_lazy_perlin::operator()(geom::vector p) const {