Skip to content

Commit 1ebda07

Browse files
committed
Add Noise2.
Squashed commit of the following: commit ba971bdf1fabe7b89eb4b63702021d485a0affae Author: Karn Kaul <karnkaul@gmail.com> Date: Mon Sep 4 15:41:27 2023 -0700 Add Noise2. commit 1fba20e2313d1da29c3792717b3cd2ff0aae4836 Author: Karn Kaul <karnkaul@gmail.com> Date: Mon Sep 4 11:22:29 2023 -0700 Add data2.
1 parent 4cd31b1 commit 1ebda07

File tree

10 files changed

+160
-35
lines changed

10 files changed

+160
-35
lines changed

noiz/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ add_library(${PROJECT_NAME} INTERFACE)
44
add_library(noiz::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
55

66
target_sources(${PROJECT_NAME} PUBLIC FILE_SET HEADERS BASE_DIRS include FILES
7+
include/noiz/detail/data2.hpp
78
include/noiz/detail/generator.hpp
89
include/noiz/detail/grid2.hpp
910

1011
include/noiz/cell2.hpp
1112
include/noiz/index2.hpp
13+
include/noiz/noise2.hpp
1214
include/noiz/seed.hpp
1315
include/noiz/vec2.hpp
1416
)

noiz/include/noiz/cell2.hpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ struct Corner2 {
1010
Vec2<Type> gradient{};
1111
};
1212

13-
template <std::floating_point Type>
14-
struct Cell2 {
15-
Corner2<Type> left_top{};
16-
Corner2<Type> right_top{};
17-
Corner2<Type> left_bottom{};
18-
Corner2<Type> right_bottom{};
13+
template <typename Type>
14+
struct TCell2 {
15+
Type left_top{};
16+
Type right_top{};
17+
Type left_bottom{};
18+
Type right_bottom{};
1919
};
20+
21+
template <std::floating_point Type>
22+
using Cell2 = TCell2<Vec2<Type>>;
23+
24+
template <std::floating_point Type>
25+
using CornerCell2 = TCell2<Corner2<Type>>;
2026
} // namespace noiz

noiz/include/noiz/detail/data2.hpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
#include "generator.hpp"
3+
#include "grid2.hpp"
4+
5+
namespace noiz::detail {
6+
template <std::floating_point Type>
7+
auto make_populated_grid(Index2 const grid_extent, Seed seed = Generator::make_random_seed()) -> Grid2<Type> {
8+
auto ret = make_grid2<Type>(grid_extent);
9+
auto generator = Generator{seed};
10+
for (auto& corner : ret.corners) { generator.next(corner.gradient); }
11+
return ret;
12+
}
13+
14+
template <std::floating_point Type>
15+
constexpr auto compute_offsets(CornerCell2<Type> const& corner, Vec2<Type> const point) -> Cell2<Type> {
16+
return Cell2<Type>{
17+
.left_top = point - corner.left_top.location,
18+
.right_top = point - corner.right_top.location,
19+
.left_bottom = point - corner.left_bottom.location,
20+
.right_bottom = point - corner.right_bottom.location,
21+
};
22+
}
23+
24+
template <std::floating_point Type>
25+
constexpr auto compute_dot_products(CornerCell2<Type> const& corner, Cell2<Type> const& offset) -> TCell2<Type> {
26+
return TCell2<Type>{
27+
.left_top = dot(corner.left_top.gradient, offset.left_top),
28+
.right_top = dot(corner.right_top.gradient, offset.right_top),
29+
.left_bottom = dot(corner.left_bottom.gradient, offset.left_bottom),
30+
.right_bottom = dot(corner.right_bottom.gradient, offset.right_bottom),
31+
};
32+
}
33+
34+
template <std::floating_point Type>
35+
constexpr auto interpolate(Vec2<Type> const point, TCell2<Type> const& dot_products) -> Type {
36+
auto const uv = point.fract();
37+
auto const a = std::lerp(dot_products.left_top, dot_products.right_top, uv.x);
38+
auto const b = std::lerp(dot_products.left_bottom, dot_products.right_bottom, uv.x);
39+
return std::lerp(a, b, uv.y);
40+
}
41+
} // namespace noiz::detail

noiz/include/noiz/detail/grid2.hpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,29 @@ template <std::floating_point Type>
1717
template <std::floating_point Type>
1818
struct Grid2 {
1919
std::vector<Corner2<Type>> corners{};
20-
Index2 grid_size{};
20+
Index2 grid_extent{};
2121

22-
[[nodiscard]] auto at(CellIndex2 const index) const -> Cell2<Type> {
23-
return Cell2<Type>{corners.at(index.lt), corners.at(index.rt), corners.at(index.lb), corners.at(index.rb)};
22+
[[nodiscard]] auto at(CellIndex2 const index) const -> CornerCell2<Type> {
23+
return CornerCell2<Type>{corners.at(index.lt), corners.at(index.rt), corners.at(index.lb), corners.at(index.rb)};
2424
}
2525

26-
[[nodiscard]] auto at(Index2 index) const -> Cell2<Type> { return at(CellIndex2::make(index, grid_size)); }
26+
[[nodiscard]] auto at(Index2 index) const -> CornerCell2<Type> { return at(CellIndex2::make(index, grid_extent)); }
2727
};
2828

2929
template <std::floating_point Type>
30-
[[nodiscard]] auto make_grid2(Index2 grid_size) -> Grid2<Type> {
31-
auto const corner_count = (grid_size.x + 1) * (grid_size.y + 1);
30+
[[nodiscard]] auto make_grid2(Index2 grid_extent) -> Grid2<Type> {
31+
auto const corner_count = (grid_extent.x + 1) * (grid_extent.y + 1);
3232
if (corner_count <= 0) { return {}; }
3333

3434
auto ret = Grid2<Type>{
3535
.corners = std::vector<Corner2<Type>>(static_cast<std::size_t>(corner_count)),
36-
.grid_size = grid_size,
36+
.grid_extent = grid_extent,
3737
};
3838

39-
for (int row = 0; row <= grid_size.y; ++row) {
40-
for (int col = 0; col <= grid_size.x; ++col) {
39+
for (int row = 0; row <= grid_extent.y; ++row) {
40+
for (int col = 0; col <= grid_extent.x; ++col) {
4141
auto const index2 = Index2{.x = col, .y = row};
42-
auto const index = static_cast<std::size_t>(index2.flatten(grid_size));
42+
auto const index = static_cast<std::size_t>(index2.flatten(grid_extent));
4343
ret.corners.at(index).location = to_vec2<Type>(Index2{.x = col, .y = row});
4444
}
4545
}

noiz/include/noiz/index2.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ struct CellIndex2 {
2020
std::size_t lb{};
2121
std::size_t rb{};
2222

23-
static constexpr auto make(Index2 index, Index2 const grid_size) -> CellIndex2 {
24-
index = index.modulo(grid_size);
25-
auto const cell_index = index.flatten(grid_size);
23+
static constexpr auto make(Index2 index, Index2 const grid_extent) -> CellIndex2 {
24+
index = index.modulo(grid_extent);
25+
auto const cell_index = index.flatten(grid_extent);
2626
assert(cell_index >= 0);
2727
auto ret = CellIndex2{};
2828
ret.lt = static_cast<std::size_t>(cell_index);
2929
ret.rt = ret.lt + 1;
30-
ret.lb = ret.lt + static_cast<std::size_t>(grid_size.x + 1);
31-
ret.rb = ret.rt + static_cast<std::size_t>(grid_size.x + 1);
30+
ret.lb = ret.lt + static_cast<std::size_t>(grid_extent.x + 1);
31+
ret.rb = ret.rt + static_cast<std::size_t>(grid_extent.x + 1);
3232
return ret;
3333
}
3434
};

noiz/include/noiz/noise2.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
#include "detail/data2.hpp"
3+
4+
namespace noiz {
5+
using GridExtent2 = Index2;
6+
7+
template <std::floating_point Type>
8+
class Noise2 {
9+
public:
10+
static constexpr GridExtent2 grid_extent_v{256, 256};
11+
12+
explicit Noise2(GridExtent2 grid_extent = grid_extent_v) : Noise2(detail::Generator::make_random_seed(), grid_extent) {}
13+
14+
explicit Noise2(Seed generator_seed, GridExtent2 grid_extent) : m_grid(detail::make_populated_grid<Type>(grid_extent, generator_seed)) {}
15+
16+
[[nodiscard]] auto grid_extent() const -> GridExtent2 { return m_grid.grid_extent; }
17+
18+
[[nodiscard]] auto at(Vec2<Type> point) const -> Type {
19+
point = point.modulo(detail::to_vec2<Type>(m_grid.grid_extent));
20+
auto const corner = m_grid.at(detail::to_index2(point));
21+
auto const offset = detail::compute_offsets(corner, point);
22+
auto const dots = detail::compute_dot_products(corner, offset);
23+
return detail::interpolate(point, dots);
24+
}
25+
26+
private:
27+
detail::Grid2<Type> m_grid{};
28+
};
29+
30+
using Noise2f = Noise2<float>;
31+
using Noise2d = Noise2<double>;
32+
} // namespace noiz

noiz/include/noiz/vec2.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ struct Vec2 {
3737
return Vec2<Type>{.x = std::fmod(x, extent.x), .y = std::fmod(y, extent.y)};
3838
}
3939

40+
[[nodiscard]] constexpr auto fract() const -> Vec2<Type> { return Vec2<Type>{.x = x - std::floor(x), .y = y - std::floor(y)}; }
41+
4042
constexpr auto operator+=(Vec2 const rhs) -> Vec2& {
4143
x += rhs.x;
4244
y += rhs.y;

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ endfunction()
2626
add_noiz_test(vec2 test_vec2.cpp)
2727
add_noiz_test(generator test_generator.cpp)
2828
add_noiz_test(grid2 test_grid2.cpp)
29+
add_noiz_test(data2 test_data2.cpp)

tests/test_data2.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <noiz/detail/data2.hpp>
2+
#include <test/test.hpp>
3+
4+
namespace test {
5+
namespace {
6+
void noise_offsets() {
7+
auto const grid = noiz::detail::make_populated_grid<float>(noiz::Index2{5, 5}); // NOLINT
8+
auto const expect_equidistant = [](noiz::Cell2<float> const& offset) {
9+
EXPECT(compare(offset.left_top, noiz::Vec2f{0.5f, 0.5f})); // NOLINT
10+
EXPECT(compare(offset.right_top, noiz::Vec2f{-0.5f, 0.5f})); // NOLINT
11+
EXPECT(compare(offset.left_bottom, noiz::Vec2f{0.5f, -0.5f})); // NOLINT
12+
EXPECT(compare(offset.right_bottom, noiz::Vec2f{-0.5f, -0.5f})); // NOLINT
13+
};
14+
auto point = noiz::Vec2f{0.5f, 0.5f}; // NOLINT
15+
auto corner = grid.at(noiz::detail::to_index2(point));
16+
auto offset = noiz::detail::compute_offsets(corner, point.modulo(noiz::detail::to_vec2<float>(grid.grid_extent)));
17+
expect_equidistant(offset);
18+
19+
for (int i = 0; i < 10; ++i) { // NOLINT
20+
point.y += 1.0f;
21+
for (int j = 0; j < 10; ++j) { // NOLINT
22+
point.x += 1.0f;
23+
corner = grid.at(noiz::detail::to_index2(point));
24+
offset = noiz::detail::compute_offsets(corner, point.modulo(noiz::detail::to_vec2<float>(grid.grid_extent)));
25+
expect_equidistant(offset);
26+
}
27+
point.x = 0.5f; // NOLINT
28+
}
29+
}
30+
31+
auto run() -> bool {
32+
ADD_TEST(noise_offsets);
33+
34+
return run_tests();
35+
}
36+
} // namespace
37+
} // namespace test
38+
39+
auto main() -> int {
40+
if (!test::run()) { return EXIT_FAILURE; }
41+
}

tests/test_grid2.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,32 @@ void grid_make() {
99
}
1010

1111
void grid_cell_loc() {
12-
auto grid_size = noiz::Index2{3, 3};
13-
auto loc = noiz::CellIndex2::make({0, 0}, grid_size);
12+
auto grid_extent = noiz::Index2{3, 3};
13+
auto loc = noiz::CellIndex2::make({0, 0}, grid_extent);
1414
EXPECT(loc.lt == 0 && loc.rt == 1 && loc.lb == 4 && loc.rb == 5);
15-
loc = noiz::CellIndex2::make({1, 0}, grid_size);
15+
loc = noiz::CellIndex2::make({1, 0}, grid_extent);
1616
EXPECT(loc.lt == 1 && loc.rt == 2 && loc.lb == 5 && loc.rb == 6);
17-
loc = noiz::CellIndex2::make({2, 0}, grid_size);
17+
loc = noiz::CellIndex2::make({2, 0}, grid_extent);
1818
EXPECT(loc.lt == 2 && loc.rt == 3 && loc.lb == 6 && loc.rb == 7);
19-
loc = noiz::CellIndex2::make({0, 1}, grid_size);
19+
loc = noiz::CellIndex2::make({0, 1}, grid_extent);
2020
EXPECT(loc.lt == 4 && loc.rt == 5 && loc.lb == 8 && loc.rb == 9);
21-
loc = noiz::CellIndex2::make({1, 1}, grid_size);
21+
loc = noiz::CellIndex2::make({1, 1}, grid_extent);
2222
EXPECT(loc.lt == 5 && loc.rt == 6 && loc.lb == 9 && loc.rb == 10);
23-
loc = noiz::CellIndex2::make({2, 1}, grid_size);
23+
loc = noiz::CellIndex2::make({2, 1}, grid_extent);
2424
EXPECT(loc.lt == 6 && loc.rt == 7 && loc.lb == 10 && loc.rb == 11);
25-
loc = noiz::CellIndex2::make({0, 2}, grid_size);
25+
loc = noiz::CellIndex2::make({0, 2}, grid_extent);
2626
EXPECT(loc.lt == 8 && loc.rt == 9 && loc.lb == 12 && loc.rb == 13);
27-
loc = noiz::CellIndex2::make({1, 2}, grid_size);
27+
loc = noiz::CellIndex2::make({1, 2}, grid_extent);
2828
EXPECT(loc.lt == 9 && loc.rt == 10 && loc.lb == 13 && loc.rb == 14);
29-
loc = noiz::CellIndex2::make({2, 2}, grid_size);
29+
loc = noiz::CellIndex2::make({2, 2}, grid_extent);
3030
EXPECT(loc.lt == 10 && loc.rt == 11 && loc.lb == 14 && loc.rb == 15);
31-
loc = noiz::CellIndex2::make({3, 3}, grid_size);
31+
loc = noiz::CellIndex2::make({3, 3}, grid_extent);
3232
EXPECT(loc.lt == 0 && loc.rt == 1 && loc.lb == 4 && loc.rb == 5);
3333

34-
grid_size = noiz::Index2{4, 4};
35-
loc = noiz::CellIndex2::make({0, 0}, grid_size);
34+
grid_extent = noiz::Index2{4, 4};
35+
loc = noiz::CellIndex2::make({0, 0}, grid_extent);
3636
EXPECT(loc.lt == 0 && loc.rt == 1 && loc.lb == 5 && loc.rb == 6);
37-
loc = noiz::CellIndex2::make({1, 1}, grid_size);
37+
loc = noiz::CellIndex2::make({1, 1}, grid_extent);
3838
EXPECT(loc.lt == 6 && loc.rt == 7 && loc.lb == 11 && loc.rb == 12);
3939
}
4040

0 commit comments

Comments
 (0)