]> git.localhorst.tv Git - blank.git/blob - src/noise.cpp
first attempt at world generation
[blank.git] / src / noise.cpp
1 #include "noise.hpp"
2
3 #include <cmath>
4
5
6 namespace blank {
7
8
9 SimplexNoise::SimplexNoise(unsigned int seed)
10 : grad({
11         {  1.0f,  1.0f,  0.0f },
12         { -1.0f,  1.0f,  0.0f },
13         {  1.0f, -1.0f,  0.0f },
14         { -1.0f, -1.0f,  0.0f },
15         {  1.0f,  0.0f,  1.0f },
16         { -1.0f,  0.0f,  1.0f },
17         {  1.0f,  0.0f, -1.0f },
18         { -1.0f,  0.0f, -1.0f },
19         {  0.0f,  1.0f,  1.0f },
20         {  0.0f, -1.0f,  1.0f },
21         {  0.0f,  1.0f, -1.0f },
22         {  0.0f, -1.0f, -1.0f },
23 }) {
24         unsigned int val = seed;
25         for (size_t i = 0; i < 256; ++i) {
26                 val = 2346765 * val + 6446345;
27                 perm[i] = val % 256;
28         }
29 }
30
31
32 float SimplexNoise::operator ()(const glm::vec3 &in) const {
33         float skew = (in.x + in.y + in.z) / 3.0f;
34
35         glm::vec3 skewed(std::floor(in.x + skew), std::floor(in.y + skew), std::floor(in.z + skew));
36         float tr = (skewed.x + skewed.y + skewed.z) / 6.0f;
37
38         glm::vec3 unskewed(skewed.x - tr, skewed.y - tr, skewed.z - tr);
39         glm::vec3 offset[4];
40         offset[0] = in - unskewed;
41
42         glm::vec3 second, third;
43
44         if (offset[0].x >= offset[0].y) {
45                 if (offset[0].y >= offset[0].z) {
46                         second = { 1.0f, 0.0f, 0.0f };
47                         third = { 1.0f, 1.0f, 0.0f };
48                 } else if (offset[0].x >= offset[0].z) {
49                         second = { 1.0f, 0.0f, 0.0f };
50                         third = { 1.0f, 0.0f, 1.0f };
51                 } else {
52                         second = { 0.0f, 0.0f, 1.0f };
53                         third = { 1.0f, 0.0f, 1.0f };
54                 }
55         } else if (offset[0].y < offset[0].z) {
56                 second = { 0.0f, 0.0f, 1.0f };
57                 third = { 0.0f, 1.0f, 1.0f };
58         } else if (offset[0].x < offset[0].z) {
59                 second = { 0.0f, 1.0f, 0.0f };
60                 third = { 0.0f, 1.0f, 1.0f };
61         } else {
62                 second = { 0.0f, 1.0f, 0.0f };
63                 third = { 1.0f, 1.0f, 0.0f };
64         }
65
66         offset[1] = offset[0] - second + glm::vec3(1.0f/6.0f);
67         offset[2] = offset[0] - third + glm::vec3(1.0f/3.0f);
68         offset[3] = offset[0] - glm::vec3(0.5f);
69
70         size_t index[3] = {
71                 unsigned(skewed.x) % 256,
72                 unsigned(skewed.y) % 256,
73                 unsigned(skewed.z) % 256,
74         };
75         size_t corner[4] = {
76                 Perm(index[0] + Perm(index[1] + Perm(index[2]))),
77                 Perm(index[0] + second.x + Perm(index[1] + second.y + Perm(index[2] + second.z))),
78                 Perm(index[0] + third.x + Perm(index[1] + third.y + Perm(index[2] + third.z))),
79                 Perm(index[0] + 1 + Perm(index[1] + 1 + Perm(index[2] + 1))),
80         };
81         float n[4];
82         float t[4];
83         for (size_t i = 0; i < 4; ++i) {
84                 t[i] = 0.6f - dot(offset[i], offset[i]);
85                 if (t[i] < 0.0f) {
86                         n[i] = 0.0f;
87                 } else {
88                         t[i] *= t[i];
89                         n[i] = t[i] * t[i] * dot(Grad(corner[i]), offset[i]);
90                 }
91         }
92
93         return 32.0f * (n[0] + n[1] + n[2] + n[3]);
94 }
95
96
97 unsigned char SimplexNoise::Perm(size_t idx) const {
98         return perm[idx % 256];
99 }
100
101 const glm::vec3 &SimplexNoise::Grad(size_t idx) const {
102         return grad[idx % 12];
103 }
104
105 }