TerraForge3D  2.3.1
3D Terrain And Landscape Generator
NoiseLayer.cpp
1#include "NoiseLayers/NoiseLayer.h"
2
3#include "imgui.h"
4#include "FastNoiseLite.h"
5
6#define MAKE_IMGUI_ID(x) ("##NoiseLayer" + std::to_string(index) + x).c_str()
7#define MAKE_IMGUI_LABEL(x) (x + std::string("##NoiseLayer") + std::to_string(index)).c_str()
8
9static const char *noiseTypes[] = {"Perlin", "Cellular", "OpenSimplex2", "OpenSimplex2S", "Value", "Value Cubic"};
10static const char *fractalTypes[] = { "None", "FBm", "Ridged", "PingPong" };
11static const char *distFuncs[] = { "EuclideanSq", "Euclidean", "Manhattan", "Euclidean Manhattan Hybrid" };
12
13static void SetNoiseType(FastNoiseLite *noiseGen, int type)
14{
15 switch (type)
16 {
17 case 0:
18 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
19 break;
20
21 case 1:
22 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Cellular);
23 break;
24
25 case 2:
26 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_OpenSimplex2);
27 break;
28
29 case 3:
30 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_OpenSimplex2S);
31 break;
32
33 case 4:
34 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Value);
35 break;
36
37 case 5:
38 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_ValueCubic);
39 break;
40
41 default:
42 noiseGen->SetNoiseType(FastNoiseLite::NoiseType::NoiseType_Perlin);
43 break;
44 }
45}
46
47static void SetFractalType(FastNoiseLite *noiseGen, int type)
48{
49 switch (type)
50 {
51 case 0:
52 noiseGen->SetFractalType(FastNoiseLite::FractalType::FractalType_None);
53 break;
54
55 case 1:
56 noiseGen->SetFractalType(FastNoiseLite::FractalType::FractalType_FBm);
57 break;
58
59 case 2:
60 noiseGen->SetFractalType(FastNoiseLite::FractalType::FractalType_Ridged);
61 break;
62
63 case 3:
64 noiseGen->SetFractalType(FastNoiseLite::FractalType::FractalType_PingPong);
65 break;
66
67 default:
68 noiseGen->SetFractalType(FastNoiseLite::FractalType::FractalType_None);
69 break;
70 }
71}
72
73static void SetDistanceFunc(FastNoiseLite *noiseGen, int func)
74{
75 switch (func)
76 {
77 case 0:
78 noiseGen->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::CellularDistanceFunction_EuclideanSq);
79 break;
80
81 case 1:
82 noiseGen->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::CellularDistanceFunction_Euclidean);
83 break;
84
85 case 2:
86 noiseGen->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::CellularDistanceFunction_Manhattan);
87 break;
88
89 case 3:
90 noiseGen->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::CellularDistanceFunction_Hybrid);
91 break;
92
93 default:
94 noiseGen->SetCellularDistanceFunction(FastNoiseLite::CellularDistanceFunction::CellularDistanceFunction_EuclideanSq);
95 break;
96 }
97}
98
99
100NoiseLayer::NoiseLayer()
101{
102 enabled = false;
103 seed = 42;
104 frequency = 0.01f;
105 fractalType = 0;
106 distanceFunc = 0;
107 octaves = 3;
108 lacunarity = 2.0f;
109 gain = 0.5f;
110 weightedStrength = 0.0f; // should be within 0 to 1
111 pingPongStrength = 2.0f;
112 strength = 1.0f;
113 cellularJitter = 1.0f;
114 noiseGen = new FastNoiseLite();
115 name.reserve(1000);
116 name = "Noise Layer\0 ";
117 offset[0] = offset[1] = offset[2] = 0.0f;
118 noiseType = 0;
119 noiseTypeStr = noiseTypes[0];
120 fractalTypeStr = fractalTypes[0];
121 distFuncStr = distFuncs[0];
122}
123
124NoiseLayer::~NoiseLayer()
125{
126 delete noiseGen;
127}
128
129nlohmann::json NoiseLayer::Save()
130{
131 nlohmann::json data;
132 data["noiseType"] = noiseType;
133 data["frequency"] = frequency;
134 data["seed"] = seed;
135 data["lacunarity"] = lacunarity;
136 data["weightedStrength"] = weightedStrength;
137 data["octaves"] = octaves;
138 data["pingPongStrength"] = pingPongStrength;
139 data["gain"] = gain;
140 data["strength"] = strength;
141 data["fractalType"] = fractalType;
142 data["distanceFunc"] = distanceFunc;
143 data["cellularJitter"] = cellularJitter;
144 data["offsetX"] = offset[0];
145 data["offsetY"] = offset[1];
146 data["offsetZ"] = offset[2];
147 data["name"] = name;
148 data["enabled"] = enabled;
149 return data;
150}
151
152void NoiseLayer::Load(nlohmann::json data)
153{
154 frequency = data["frequency"];
155 noiseGen->SetFrequency(frequency);
156 seed = data["seed"];
157 noiseGen->SetSeed(seed);
158 lacunarity = data["lacunarity"];
159 noiseGen->SetFractalLacunarity(lacunarity);
160 weightedStrength = data["weightedStrength"];
161 noiseGen->SetFractalWeightedStrength(weightedStrength);
162 octaves = data["octaves"];
163 noiseGen->SetFractalOctaves(octaves);
164 pingPongStrength = data["pingPongStrength"];
165 noiseGen->SetFractalPingPongStrength(pingPongStrength);
166 gain = data["gain"];
167 noiseGen->SetFractalGain(gain);
168 strength = data["strength"];
169 fractalType = data["fractalType"];
170 distanceFunc = data["distanceFunc"];
171 cellularJitter = data["cellularJitter"];
172 name = data["name"];
173 enabled = data["enabled"];
174 offset[0] = data["offsetX"];
175 offset[1] = data["offsetY"];
176 offset[2] = data["offsetZ"];
177 noiseType = data["noiseType"];
178 noiseTypeStr = noiseTypes[noiseType];
179 fractalTypeStr = fractalTypes[fractalType];
180 distFuncStr = distFuncs[distanceFunc];
181 SetNoiseType(noiseGen, noiseType);
182 SetFractalType(noiseGen, fractalType);
183 SetDistanceFunc(noiseGen, distanceFunc);
184}
185
186float NoiseLayer::Evaluate(NoiseLayerInput input)
187{
188 return enabled ? noiseGen->GetNoise(input.x + offset[0], input.y + offset[1], input.z + offset[2]) * strength : 0.0f;
189}
190
191void NoiseLayer::Render(int index)
192{
193 ImGui::SameLine();
194 ImGui::Text(name.data());
195 ImGui::InputTextWithHint(MAKE_IMGUI_ID("Name Input"), "Name", name.data(), name.capacity());
196 ImGui::NewLine();
197 ImGui::Checkbox(MAKE_IMGUI_LABEL("Enabled"), &enabled);
198 ImGui::Text("Offsets:");
199 ImGui::DragFloat3(MAKE_IMGUI_ID("Offsets"), offset, 0.1f);
200 ImGui::Text("Noise Type : ");
201 ImGui::SameLine();
202
203 if (ImGui::BeginCombo(MAKE_IMGUI_ID("Noise Type Selector"), noiseTypeStr))
204 {
205 for (int n = 0; n < 6; n++)
206 {
207 bool isSelected = (noiseTypeStr == noiseTypes[n]);
208
209 if (ImGui::Selectable(noiseTypes[n], isSelected))
210 {
211 noiseTypeStr = noiseTypes[n];
212 noiseType = n;
213 SetNoiseType(noiseGen, noiseType);
214
215 if (isSelected)
216 {
217 ImGui::SetItemDefaultFocus();
218 }
219 }
220 }
221
222 ImGui::EndCombo();
223 }
224
225 ImGui::Text("Fractal Type : ");
226 ImGui::SameLine();
227
228 if (ImGui::BeginCombo(MAKE_IMGUI_ID("Fractal Type Selector"), fractalTypeStr))
229 {
230 for (int n = 0; n < 4; n++)
231 {
232 bool isSelected = (fractalTypeStr == fractalTypes[n]);
233
234 if (ImGui::Selectable(fractalTypes[n], isSelected))
235 {
236 fractalTypeStr = fractalTypes[n];
237 fractalType = n;
238 SetFractalType(noiseGen, fractalType);
239
240 if (isSelected)
241 {
242 ImGui::SetItemDefaultFocus();
243 }
244 }
245 }
246
247 ImGui::EndCombo();
248 }
249
250 if (ImGui::DragInt(MAKE_IMGUI_LABEL("Seed"), &seed))
251 {
252 noiseGen->SetSeed(seed);
253 }
254
255 if (ImGui::DragFloat(MAKE_IMGUI_LABEL("Frequency"), &frequency, 0.001f))
256 {
257 noiseGen->SetFrequency(frequency);
258 }
259
260 ImGui::DragFloat(MAKE_IMGUI_LABEL("Strength"), &strength, 0.1f);
261
262 if (fractalType != 0)
263 {
264 if (ImGui::DragInt(MAKE_IMGUI_LABEL("Octaves"), &octaves, 0.05f))
265 {
266 noiseGen->SetFractalOctaves(octaves);
267 }
268
269 if (ImGui::DragFloat(MAKE_IMGUI_LABEL("Lacunarity"), &lacunarity, 0.1f))
270 {
271 noiseGen->SetFractalLacunarity(lacunarity);
272 }
273
274 if (ImGui::DragFloat(MAKE_IMGUI_LABEL("Gain"), &gain, 0.1f))
275 {
276 noiseGen->SetFractalGain(gain);
277 }
278
279 if (ImGui::DragFloat(MAKE_IMGUI_LABEL("Weighted Strength"), &weightedStrength, 0.01f))
280 {
281 noiseGen->SetFractalWeightedStrength(weightedStrength);
282 }
283
284 if (ImGui::DragFloat(MAKE_IMGUI_LABEL("Ping Pong Strength"), &pingPongStrength, 0.01f))
285 {
286 noiseGen->SetFractalPingPongStrength(pingPongStrength);
287 }
288 }
289
290 if (noiseType == 1)
291 {
292 if (ImGui::DragFloat(MAKE_IMGUI_LABEL("Cellur Jitter"), &cellularJitter, 0.01f))
293 {
294 noiseGen->SetCellularJitter(cellularJitter);
295 }
296
297 ImGui::Text("Cellular Distance Function : ");
298 ImGui::SameLine();
299
300 if (ImGui::BeginCombo(MAKE_IMGUI_ID("Cellular Distance Function"), distFuncStr))
301 {
302 for (int n = 0; n < 4; n++)
303 {
304 bool isSelected = (distFuncStr == distFuncs[n]);
305
306 if (ImGui::Selectable(distFuncs[n], isSelected))
307 {
308 distFuncStr = distFuncs[n];
309 distanceFunc = n;
310 SetFractalType(noiseGen, distanceFunc);
311
312 if (isSelected)
313 {
314 ImGui::SetItemDefaultFocus();
315 }
316 }
317 }
318
319 ImGui::EndCombo();
320 }
321 }
322}
a class to store JSON values
Definition: json.hpp:17860