TerraForge3D  2.3.1
3D Terrain And Landscape Generator
MaskLayerHelper.h
1#include <cmath>
2#include <string>
3
4#include "imgui/imgui.h"
5#include "FastNoiseLite.h"
6
7#include "GeneratorMask.h"
8
9#define MAKE_IMGUI_ID(label, id) (label + std::string("##GMSKNL") + id).c_str()
10
11// MATH UTILS
12
13#define SQUARE(x) (x) * (x)
14
15#define MIN(x, y) ((x) < (y)) ? (x) : (y)
16#define MAX(x, y) ((x) > (y)) ? (x) : (y)
17
18#define MATH_E 2.718281828459045
19#define MATH_PI 3.1415926535897932384626433832795
20
21#define M_PI_4 (MATH_PI/4.0)
22
23#define Aatan 0.0776509570923569
24#define Batan -0.287434475393028
25#define Catan (M_PI_4 - Aatan - Batan)
26
27inline float Fast2ArcTan(float x)
28{
29 float xx = x * x;
30 return ((Aatan * xx + Batan) * xx + Catan) * x;
31}
32
33inline float smoothMin(float a, float b, float k)
34{
35 k = MAX(0, k);
36 // https://www.iquilezles.org/www/articles/smin/smin.htm
37 float h = MAX(0, MIN(1, (b - a + k) / (2 * k)));
38 return a * h + b * (1 - h) - k * h * (1 - h);
39}
40
41// Smooth maximum of two values, controlled by smoothing factor k
42// When k = 0, this behaves identically to max(a, b)
43inline float smoothMax(float a, float b, float k)
44{
45 k = MIN(0, -k);
46 float h = MAX(0, MIN(1, (b - a + k) / (2 * k)));
47 return a * h + b * (1 - h) - k * h * (1 - h);
48}
49
50
51// MATH UTILS
52
53static FastNoiseLite noiseGen;
54
55inline void ShowHillMaskSettingS(GeneratorMask *mask, std::string id)
56{
57 ImGui::Text("Mode : Hill");
58 ImGui::DragFloat3(MAKE_IMGUI_ID("Position", id), mask->pos, 0.01f);
59 ImGui::DragFloat(MAKE_IMGUI_ID("Radius", id), &mask->d1[0], 0.01f);
60 ImGui::DragFloat(MAKE_IMGUI_ID("Height", id), &mask->d1[1], 0.01f);
61 ImGui::DragFloat2(MAKE_IMGUI_ID("Noise Offset", id), &mask->d2[0], 0.01f);
62 ImGui::DragFloat(MAKE_IMGUI_ID("Noise Strength", id), &mask->d2[3], 0.01f);
63 ImGui::DragFloat(MAKE_IMGUI_ID("Noise Frequency", id), &mask->d2[2], 0.01f);
64 ImGui::Text("Axis (0:XZ, 1:YX, 2:XY) : %f", mask->d1[3]);
65
66 if(ImGui::Button( MAKE_IMGUI_ID("Change Axis", id) ) )
67 {
68 mask->d1[3] += 1.0f;
69
70 if(mask->d1[3] == 3.0f)
71 {
72 mask->d1[3] = 0.0f;
73 }
74 }
75}
76
77inline float EvaluateHillMask(GeneratorMask *mask, float x, float y, float z)
78{
79 float X;
80 float Y;
81
82 if(mask->d1[3] == 0.0f)
83 {
84 X = x - mask->pos[0];
85 Y = z - mask->pos[2];
86 }
87
88 else if(mask->d1[3] == 1.0f)
89 {
90 X = y - mask->pos[1];
91 Y = z - mask->pos[2];
92 }
93
94 else if(mask->d1[3] == 2.0f)
95 {
96 X = x - mask->pos[0];
97 Y = y - mask->pos[1];
98 }
99
100 float theta = atan(Y/X);
101 theta *= theta;
102 X = X * X;
103 Y = Y * Y;
104 noiseGen.SetFrequency(mask->d2[2]);
105 float invR = 1.0f / (mask->d1[0] + noiseGen.GetNoise(sin(theta) + mask->d2[0], cos(theta) + mask->d2[1]) * mask->d2[3]);
106 float h = pow(MATH_E, -(X + Y) * invR);
107 return h * (mask->d1[1] + mask->pos[1]);
108}
109
110inline void ShowCratorMaskSettingS(GeneratorMask *mask, std::string id)
111{
112 ImGui::Text("Mode : Crater");
113 ImGui::DragFloat3(MAKE_IMGUI_ID("Position", id), mask->pos, 0.01f);
114 ImGui::DragFloat(MAKE_IMGUI_ID("Radius", id), &mask->d1[0], 0.01f);
115 ImGui::DragFloat(MAKE_IMGUI_ID("Floor", id), &mask->d3[3], 0.01f);
116 ImGui::DragFloat(MAKE_IMGUI_ID("Rim Width", id), &mask->d1[3], 0.01f);
117 ImGui::DragFloat(MAKE_IMGUI_ID("Rim Steepness", id), &mask->d3[0], 0.01f);
118 ImGui::DragFloat(MAKE_IMGUI_ID("Smoothness", id), &mask->d3[1], 0.01f);
119}
120
121inline float EvaluateCratorMask(GeneratorMask *mask, float x, float y, float z)
122{
123 float X = (x - mask->pos[0]);
124 float Y = (z - mask->pos[2]);
125 float l = sqrt(X*X + Y*Y) / mask->d1[0];
126 float cavity = (l * l - 1);
127 float rimX = MIN(l - 1 - mask->d1[3], 0.0f);
128 float rim = mask->d3[0] * rimX * rimX;
129 float cratershape = smoothMax(cavity, mask->d3[3], mask->d3[1]);
130 cratershape = smoothMin(cratershape, rim, mask->d3[1]);
131 return cratershape * mask->d1[0] ;
132 //return crater * mask->d3[2];
133 return 0.0f;
134}
135
136inline void ShowCliffMaskSettingS(GeneratorMask *mask, std::string id)
137{
138 ImGui::Text("Mode : Cliff");
139 ImGui::DragFloat3(MAKE_IMGUI_ID("Position", id), mask->pos, 0.01f);
140 ImGui::DragFloat(MAKE_IMGUI_ID("Depth", id), &mask->d1[0], 0.01f);
141 ImGui::DragFloat(MAKE_IMGUI_ID("Height", id), &mask->d1[1], 0.01f);
142 ImGui::DragFloat(MAKE_IMGUI_ID("Steepness", id), &mask->d1[2], 0.01f);
143 ImGui::DragFloat(MAKE_IMGUI_ID("Angle", id), &mask->d2[3], 0.01f);
144 ImGui::Text("Axis (0:XY, 1:YZ, 2:ZX) : %f", mask->d1[3]);
145
146 if(ImGui::Button( MAKE_IMGUI_ID("Change Axis", id) ) )
147 {
148 mask->d1[3] += 1.0f;
149
150 if(mask->d1[3] == 3.0f)
151 {
152 mask->d1[3] = 0.0f;
153 }
154 }
155}
156
157
158inline float EvaluateCliffMask(GeneratorMask *mask, float x, float y, float z)
159{
160 float X;
161 float Y;
162
163 if(mask->d1[3] == 0.0f)
164 {
165 X = x - mask->pos[0];
166 Y = y - mask->pos[1];
167 }
168
169 else if(mask->d1[3] == 1.0f)
170 {
171 X = y - mask->pos[1];
172 Y = z - mask->pos[2];
173 }
174
175 else if(mask->d1[3] == 2.0f)
176 {
177 X = z - mask->pos[2];
178 Y = x - mask->pos[0];
179 }
180
181 float steepness = mask->d1[2];
182 float height = mask->d1[1];
183 float depth = mask->d1[0];
184 float f = -steepness*X*X + height;
185 float g = height;
186
187 if(X >= 0)
188 {
189 g = depth;
190 }
191
192 return MAX(f, g);
193}
194
195inline void ShowPlatueMaskSettingS(GeneratorMask *mask, std::string id)
196{
197 ImGui::Text("Mode : Platue");
198 ImGui::DragFloat3(MAKE_IMGUI_ID("Position", id), mask->pos, 0.01f);
199 ImGui::DragFloat(MAKE_IMGUI_ID("Depth", id), &mask->d1[0], 0.01f);
200 ImGui::DragFloat(MAKE_IMGUI_ID("Height", id), &mask->d1[1], 0.01f);
201 ImGui::DragFloat(MAKE_IMGUI_ID("Steepness", id), &mask->d1[2], 0.01f);
202 ImGui::DragFloat(MAKE_IMGUI_ID("Angle", id), &mask->d2[3], 0.01f);
203}
204
205inline float EvaluatePlataueMask(GeneratorMask *mask, float x, float y, float z)
206{
207 float X;
208 float Y;
209
210 if(mask->d1[3] == 0.0f)
211 {
212 X = x - mask->pos[0];
213 Y = y - mask->pos[1];
214 }
215
216 else if(mask->d1[3] == 1.0f)
217 {
218 X = y - mask->pos[1];
219 Y = z - mask->pos[2];
220 }
221
222 else if(mask->d1[3] == 2.0f)
223 {
224 X = z - mask->pos[2];
225 Y = x - mask->pos[0];
226 }
227
228 float steepness = mask->d1[2];
229 float height = mask->d1[1];
230 float depth = mask->d1[0];
231 float f = -steepness*X*X + height;
232 float g = height;
233
234 if(X >= 0)
235 {
236 g = depth;
237 }
238
239 return MAX(f, g);
240}