1 /***************************************************************************
2  *   Copyright (C) 2021 by Abderrahman Taha                                *
3  *                                                                         *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor,Boston, MA 02110-1301 USA             *
19  ***************************************************************************/
20 
21 #include "commun.h"
22 
23 static int p[512];
24 static int permutation[256] =
25 {
26     151, 160, 137, 91,  90,  15,  131, 13,  201, 95,  96,  53,  194, 233, 7,
27     225, 140, 36,  103, 30,  69,  142, 8,   99,  37,  240, 21,  10,  23,  190,
28     6,   148, 247, 120, 234, 75,  0,   26,  197, 62,  94,  252, 219, 203, 117,
29     35,  11,  32,  57,  177, 33,  88,  237, 149, 56,  87,  174, 20,  125, 136,
30     171, 168, 68,  175, 74,  165, 71,  134, 139, 48,  27,  166, 77,  146, 158,
31     231, 83,  111, 229, 122, 60,  211, 133, 230, 220, 105, 92,  41,  55,  46,
32     245, 40,  244, 102, 143, 54,  65,  25,  63,  161, 1,   216, 80,  73,  209,
33     76,  132, 187, 208, 89,  18,  169, 200, 196, 135, 130, 116, 188, 159, 86,
34     164, 100, 109, 198, 173, 186, 3,   64,  52,  217, 226, 250, 124, 123, 5,
35     202, 38,  147, 118, 126, 255, 82,  85,  212, 207, 206, 59,  227, 47,  16,
36     58,  17,  182, 189, 28,  42,  223, 183, 170, 213, 119, 248, 152, 2,   44,
37     154, 163, 70,  221, 153, 101, 155, 167, 43,  172, 9,   129, 22,  39,  253,
38     19,  98,  108, 110, 79,  113, 224, 232, 178, 185, 112, 104, 218, 246, 97,
39     228, 251, 34,  242, 193, 238, 210, 144, 12,  191, 179, 162, 241, 81,  51,
40     145, 235, 249, 14,  239, 107, 49,  192, 214, 31,  181, 199, 106, 157, 184,
41     84,  204, 176, 115, 121, 50,  45,  127, 4,   150, 254, 138, 236, 205, 93,
42     222, 114, 67,  29,  24,  72,  243, 141, 128, 195, 78,  66,  215, 61,  156,
43     180
44 };
45 
46 
47 
tinyrnd()48 float tinyrnd()
49 {
50     static unsigned trand = 0;
51     trand = 1664525u * trand + 1013904223u;
52     return (float(trand) / 4294967296.0f);
53 }
CellNoiseFunc(float x,float y,float z,int seed,int type,int CombineDist)54 float CellNoise::CellNoiseFunc(float x, float y, float z, int seed, int type, int CombineDist)
55 {
56     uint lastRandom, numberFeaturePoints;
57     float randomDiff[4];
58     int cubeX, cubeY, cubeZ;
59     float distanceArray[9];
60     float color = 0;
61     for (int i = 0; i < 9; i++)
62         distanceArray[i] = 6666;
63     int evalCubeX = int(floor(x));
64     int evalCubeY = int(floor(y));
65     int evalCubeZ = int(floor(z));
66 
67     for (int i = -1; i < 2; ++i)
68         for (int j = -1; j < 2; ++j)
69             for (int k = -1; k < 2; ++k)
70             {
71                 cubeX = evalCubeX + i;
72                 cubeY = evalCubeY + j;
73                 cubeZ = evalCubeZ + k;
74                 lastRandom = uint(lcgRandom(hash((cubeX + seed), (cubeY), (cubeZ))));
75                 numberFeaturePoints = uint(probLookup(lastRandom));
76                 for (uint l = 0; l < numberFeaturePoints; ++l)
77                 {
78                     lastRandom = uint(lcgRandom(int(lastRandom)));
79                     randomDiff[0] = float(lastRandom) / 0x100000000;
80 
81                     lastRandom = uint(lcgRandom(int(lastRandom)));
82                     randomDiff[1] = float(lastRandom) / 0x100000000;
83 
84                     lastRandom = uint(lcgRandom(int(lastRandom)));
85                     randomDiff[2] = float(lastRandom) / 0x100000000;
86 
87                     featurePoint[0] = randomDiff[0] + float(cubeX);
88                     featurePoint[1] = randomDiff[1] + float(cubeY);
89                     featurePoint[2] = randomDiff[2] + float(cubeZ);
90                     if (type == 1)
91                         insert(distanceArray,
92                                ManhattanDistanceFunc(x, y, z, featurePoint[0],
93                                                      featurePoint[1], featurePoint[2]));
94                     else if (type == 2 || type == 4)
95                         insert(distanceArray,
96                                EuclidianDistanceFunc(x, y, z, featurePoint[0],
97                                                      featurePoint[1], featurePoint[2]));
98                     else if (type == 3 || type == 5)
99                         insert(distanceArray,
100                                ChebyshevDistanceFunc(x, y, z, featurePoint[0],
101                                                      featurePoint[1], featurePoint[2]));
102                 }
103             }
104     if (CombineDist == 1)
105         color = distanceArray[1] - distanceArray[0];
106     else if (CombineDist == 2)
107         color = distanceArray[2] - distanceArray[0];
108     else
109         color = distanceArray[0];
110     if (color < 0)
111         color = 0;
112     if (color > 1)
113         color = 1;
114     return color;
115 }
EuclidianDistanceFunc(float x1,float y1,float z1,float x2,float y2,float z2)116 float CellNoise::EuclidianDistanceFunc(float x1, float y1, float z1, float x2, float y2, float z2)
117 {
118     return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
119 }
ManhattanDistanceFunc(float x1,float y1,float z1,float x2,float y2,float z2)120 float CellNoise::ManhattanDistanceFunc(float x1, float y1, float z1, float x2, float y2, float z2)
121 {
122     float tmp = std::abs(x1 - x2) + std::abs(y1 - y2) + std::abs(z1 - z2);
123     return tmp;
124 }
ChebyshevDistanceFunc(float x1,float y1,float z1,float x2,float y2,float z2)125 float CellNoise::ChebyshevDistanceFunc(float x1, float y1, float z1, float x2, float y2, float z2)
126 {
127     float diff[3];
128     diff[0] = x1 - x2;
129     diff[1] = y1 - y2;
130     diff[2] = z1 - z2;
131     return std::max(std::max(std::abs(diff[0]), std::abs(diff[1])),
132                     std::abs(diff[2]));
133 }
probLookup(uint value)134 int CellNoise::probLookup(uint value)
135 {
136     if (value < 393325350U)
137         return 1;
138     if (value < 1022645910U)
139         return 2;
140     if (value < 1861739990U)
141         return 3;
142     if (value < 2700834071U)
143         return 4;
144     if (value < 3372109335U)
145         return 5;
146     if (value < 3819626178U)
147         return 6;
148     if (value < 4075350088U)
149         return 7;
150     if (value < 4203212043U)
151         return 8;
152     return 9;
153 }
insert(float * arr,float value)154 void CellNoise::insert(float *arr, float value)
155 {
156     float temp;
157     for (int i = 8; i >= 0; i--)
158     {
159         if (value > arr[i])
160             break;
161         temp = arr[i];
162         arr[i] = value;
163         if (i == 0)
164         {
165             rd[0] = featurePoint[0];
166             rd[1] = featurePoint[1];
167             rd[2] = featurePoint[2];
168         }
169         if (i < 8)
170             arr[i + 1] = temp;
171     }
172 }
lcgRandom(int lastValue)173 int CellNoise::lcgRandom(int lastValue)
174 {
175     return int(((1103515245u * uint(lastValue) + 12345u) % 0x100000000u));
176 }
hash(int i,int j,int k)177 int CellNoise::hash(int i, int j, int k)
178 {
179     return ((((((OFFSET_BASIS^i)*FNV_PRIME)^j) * FNV_PRIME)^k)*FNV_PRIME);
180 }
ImprovedNoise(float xsize,float ysize,float zsize)181 ImprovedNoise::ImprovedNoise(float xsize, float ysize, float zsize)
182 {
183     correction = 1.0f / 100000000.0f;
184     passes = int(std::log(xsize) / std::log(MAGIC_SCALE) + 0.5f);
185     passes =
186         std::max(passes, int(std::log(ysize) / std::log(MAGIC_SCALE) + 0.5f));
187     passes =
188         std::max(passes, int(std::log(zsize) / std::log(MAGIC_SCALE) + 0.5f));
189     float factor = 1.0f;
190     for (int pass = 0; pass < passes; pass++, factor *= MAGIC_SCALE)
191         correction += factor * factor;
192     correction = 1.0f / std::sqrt(correction);
193 
194     for (int i = 0; i < 256; i++)
195         p[256 + i] = p[i] = permutation[i];
196 
197     for (int i = 0; i < 256; i++)
198     {
199         int k = int((tinyrnd() * (256 - i) + i));
200 
201         int l = p[i];
202 
203         p[i] = p[k];
204         p[k] = l;
205         p[i + 256] = p[i];
206     }
207 }
noise(float x,float y,float z)208 float ImprovedNoise::noise(float x, float y, float z)
209 {
210     int X = int(std::floor(x)) & 255, Y = int(std::floor(y)) & 255,
211         Z = int(std::floor(z)) & 255;
212     x -= std::floor(x);
213     y -= std::floor(y);
214     z -= std::floor(z);
215     float u = fade(x), v = fade(y), w = fade(z);
216     int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y,
217         BA = p[B] + Z, BB = p[B + 1] + Z;
218 
219     return lerp(
220                w,
221                lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)),
222                     lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))),
223                lerp(v,
224                     lerp(u, grad(p[AA + 1], x, y, z - 1),
225                          grad(p[BA + 1], x - 1, y, z - 1)),
226                     lerp(u, grad(p[AB + 1], x, y - 1, z - 1),
227                          grad(p[BB + 1], x - 1, y - 1, z - 1))));
228 }
fade(float f)229 float ImprovedNoise::fade(float f)
230 {
231     return f*f*f*(f*(f*6-15)+10); // t * t * (3.0 - 2.0 * t);
232 }
lerp(float t,float a,float b)233 float ImprovedNoise::lerp(float t, float a, float b)
234 {
235     return a + t*(b - a);
236 }
grad(int hash,float x,float y,float z)237 float ImprovedNoise::grad(int hash, float x, float y, float z)
238 {
239     int h = hash & 15;       // CONVERT LO 4 BITS OF HASH CODE
240     float u = h < 8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
241           v = h < 4 ? y : h == 12 || h == 14 ? x : z;
242     return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
243 }
FractalNoise3D(float x,float y,float z,int octNum,float lacunarity,float gain)244 float ImprovedNoise::FractalNoise3D(float x, float y, float z, int octNum,
245                                     float lacunarity, float gain)
246 {
247     float freq = 1.0, amp = 1.0, sum = 0;
248 
249     for (int i = 0; i < octNum; i++)
250     {
251         sum += noise(x * freq, y * freq, z * freq) * amp;
252         freq *= lacunarity;
253         amp *= gain;
254     }
255     return sum;
256 }
Marble(float x,float y,float z,int octNum)257 float ImprovedNoise::Marble(float x, float y, float z, int octNum)
258 {
259     float t = 0;
260     float factor = 1.0;
261     for (int pass = 0; pass < octNum; pass++, factor *= MAGIC_SCALE)
262     {
263         float r = 1.0f / factor;
264         t += noise(x * r, y * r, z * r) * factor;
265     }
266     return t * correction;
267 }
lookup(float x,float y,float z)268 float ImprovedNoise::lookup(float x, float y, float z)
269 {
270     float t = 0;
271     float factor = 1.0;
272     for (int pass = 0; pass < passes; pass++, factor *= MAGIC_SCALE)
273     {
274         float r = 1 / factor;
275         t += noise(x*r, y*r, z*r)*factor;
276     }
277     return t * correction;
278 }
279