TerraForge3D  2.3.1
3D Terrain And Landscape Generator
MeshGeneratorManager.cpp
1#include "Generators/MeshGeneratorManager.h"
2
3#include "Utils/Utils.h"
4#include "Base/Base.h"
5#include "Data/ApplicationState.h"
6
7#include "Generators/ClearMeshGenerator.h"
8#include "Generators/CPUNoiseLayersGenerator.h"
9#include "Generators/GPUNoiseLayerGenerator.h"
10#include "Generators/CPUNodeEditor/CPUNodeEditor.h"
11
12#include "Base/UIFontManager.h"
13
14#include "Profiler.h"
15#include "Platform.h"
16
17MeshGeneratorManager::MeshGeneratorManager(ApplicationState *as)
18 :appState(as)
19{
20 isRemeshing = &appState->states.remeshing;
21 kernels = new ComputeKernel();
22 clearMeshGen = new ClearMeshGenerator(appState, kernels);
23 LoadKernels();
24}
25
26MeshGeneratorManager::~MeshGeneratorManager()
27{
28 delete clearMeshGen;
29 delete kernels;
30}
31
32void MeshGeneratorManager::Generate()
33{
34 if (*isRemeshing)
35 {
36 return;
37 }
38
39 if (appState->mode == ApplicationMode::TERRAIN)
40 {
41 appState->models.coreTerrain->UploadToGPU();
42 }
43
44 else if (appState->mode == ApplicationMode::CUSTOM_BASE)
45 {
46 appState->models.customBase->UploadToGPU();
47 }
48
49 *isRemeshing = true;
50 std::thread worker([this]
51 {
52 START_PROFILER();
53
54 if(!clearMeshGen->useGPU)
55 {
56 clearMeshGen->Generate(nullptr);
57 ExecuteCPUGenerators();
58 ExecuteKernels();
59 }
60
61 else
62 {
63 ExecuteKernels();
64 ExecuteCPUGenerators();
65 }
66
67 if(!appState->states.useGPUForNormals )
68 {
69 if (appState->mode == ApplicationMode::TERRAIN)
70 {
71 appState->models.coreTerrain->mesh->RecalculateNormals();
72 }
73
74 else if (appState->mode == ApplicationMode::CUSTOM_BASE)
75 {
76 appState->models.customBase->mesh->RecalculateNormals();
77 }
78 }
79 END_PROFILER(time);
80 *isRemeshing = false;
81 });
82 worker.detach();
83}
84
85void MeshGeneratorManager::GenerateSync()
86{
87 while (appState->states.remeshing);
88
89 *isRemeshing = true;
90// if(!clearMeshGen->useGPU)
91// {
92// clearMeshGen->Generate(nullptr);
93// ExecuteCPUGenerators();
94// ExecuteKernels();
95// }
96// else
97// {
98 ExecuteKernels();
99 ExecuteCPUGenerators();
100// }
101
102 if (appState->mode == ApplicationMode::TERRAIN)
103 {
104 appState->models.coreTerrain->mesh->RecalculateNormals();
105 appState->models.coreTerrain->UploadToGPU();
106 }
107
108 else if (appState->mode == ApplicationMode::CUSTOM_BASE)
109 {
110 appState->models.customBase->mesh->RecalculateNormals();
111 appState->models.customBase->UploadToGPU();
112 }
113
114 *isRemeshing = false;
115}
116
117void MeshGeneratorManager::ShowSettings()
118{
119 if (windowStat)
120 {
121 ImGui::Begin("Mesh Generators", &windowStat);
122 ImGui::PushFont(GetUIFont("OpenSans-Semi-Bold"));
123 ImGui::Text("Base Mesh Generators");
124 ImGui::PopFont();
125
126 if (ImGui::CollapsingHeader("Auto Base Mesh Gen (GPU)", clearMeshGen->uiActive))
127 {
128 clearMeshGen->ShowSettings();
129 }
130
131 ImGui::Separator();
132 ImGui::PushFont(GetUIFont("OpenSans-Semi-Bold"));
133 ImGui::Text("CPU Noise Layer Generators");
134 ImGui::PopFont();
135
136 for (int i = 0; i < cpuNoiseLayers.size(); i++)
137 {
138 if (ImGui::CollapsingHeader((cpuNoiseLayers[i]->name + "##CPUNL" + std::to_string(i)).c_str()))
139 {
140 cpuNoiseLayers[i]->ShowSetting(i);
141
142 if (ImGui::Button(("Delete##CPUNOUSELAYER" + std::to_string(i)).c_str()))
143 {
144 while (*isRemeshing);
145
146 cpuNoiseLayers.erase(cpuNoiseLayers.begin() + i);
147 break;
148 }
149 }
150
151 ImGui::Separator();
152 }
153
154 if (ImGui::Button("Add##CPULAYER"))
155 {
156 while (*isRemeshing);
157
158 cpuNoiseLayers.push_back(new CPUNoiseLayersGenerator(appState));
159 }
160
161 ImGui::Separator();
162 ImGui::PushFont(GetUIFont("OpenSans-Semi-Bold"));
163 ImGui::Text("GPU Noise Layer Generators");
164 ImGui::PopFont();
165
166 for (int i = 0; i < gpuNoiseLayers.size(); i++)
167 {
168 if (ImGui::CollapsingHeader((gpuNoiseLayers[i]->name + "##GPUNL" + std::to_string(i)).c_str()))
169 {
170 gpuNoiseLayers[i]->ShowSetting(i);
171
172 if (ImGui::Button(("Delete##GPUNOUSELAYER" + std::to_string(i)).c_str()))
173 {
174 while (*isRemeshing);
175
176 gpuNoiseLayers.erase(gpuNoiseLayers.begin() + i);
177 break;
178 }
179 }
180
181 ImGui::Separator();
182 }
183
184 if (ImGui::Button("Add##GPUNL"))
185 {
186 while (*isRemeshing);
187
188 gpuNoiseLayers.push_back(new GPUNoiseLayerGenerator(appState, kernels));
189 }
190
191 ImGui::Separator();
192 ImGui::PushFont(GetUIFont("OpenSans-Semi-Bold"));
193 ImGui::Text("CPU Node Editor Generators");
194 ImGui::PopFont();
195
196 for (int i = 0; i < cpuNodeEditors.size(); i++)
197 {
198 if (ImGui::CollapsingHeader((cpuNodeEditors[i]->name + "##CPUNE" + std::to_string(i)).c_str()))
199 {
200 cpuNodeEditors[i]->ShowSetting(i);
201
202 if (ImGui::Button(("Delete##CPNE" + std::to_string(i)).c_str()))
203 {
204 while (*isRemeshing);
205
206 cpuNodeEditors.erase(cpuNodeEditors.begin() + i);
207 break;
208 }
209 }
210
211 ImGui::Separator();
212 }
213
214 if (ImGui::Button("Add##CPUNE"))
215 {
216 while (*isRemeshing);
217
218 cpuNodeEditors.push_back(new CPUNodeEditor(appState));
219 }
220
221 ImGui::Separator();
222 ImGui::Text("Time : %lf ms", time);
223 ImGui::End();
224 }
225
226 for (int i = 0; i < cpuNoiseLayers.size(); i++)
227 {
228 cpuNoiseLayers[i]->Update();
229 }
230
231 for (int i = 0; i < gpuNoiseLayers.size(); i++)
232 {
233 gpuNoiseLayers[i]->Update();
234 }
235
236 for (int i = 0; i < cpuNodeEditors.size(); i++)
237 {
238 cpuNodeEditors[i]->Update();
239 }
240}
241
242void MeshGeneratorManager::GenerateForTerrain()
243{
244 int res = appState->globals.resolution;
245 float scale = appState->globals.scale;
246 Model *mod = appState->models.coreTerrain;
247
248 for (int i = 0; i < mod->mesh->vertexCount; i++)
249 {
250 float elev = 0.0f;
251 NodeInputParam inp;
252 inp.x = mod->mesh->vert[i].position.x;
253 inp.y = 0.0f;
254 inp.z = mod->mesh->vert[i].position.z;
255 inp.minX = 0.0f;
256 inp.minY = 0.0f;
257 inp.minZ = 0.0f;
258 inp.maxX = scale;
259 inp.maxY = scale;
260 inp.maxZ = scale;
261 inp.texX = mod->mesh->vert[i].texCoord.x;
262 inp.texY = mod->mesh->vert[i].texCoord.y;
263
264 for (int j = 0; j < cpuNoiseLayers.size(); j++)
265 {
266 if(cpuNoiseLayers[j]->enabled)
267 {
268 elev += cpuNoiseLayers[j]->EvaluateAt(inp.x, inp.y, inp.z);
269 }
270 }
271
272 for(int j = 0 ; j<cpuNodeEditors.size(); j++)
273 {
274 if(cpuNodeEditors[j]->enabled)
275 {
276 elev += cpuNodeEditors[j]->EvaluateAt(inp);
277 }
278 }
279
280 mod->mesh->vert[i].position.y += elev;
281 mod->mesh->vert[i].extras1.x += elev;
282 }
283}
284
285void MeshGeneratorManager::GenerateForCustomBase()
286{
287 Model *customModel = appState->models.customBase;
288 Model *customModelCopy = appState->models.customBaseCopy;
289 float scale = appState->globals.scale;
290 appState->stats.vertexCount = customModel->mesh->vertexCount;
291
292 for (int i = 0; i < customModel->mesh->vertexCount; i++)
293 {
294 Vert tmp = customModelCopy->mesh->vert[i];
295 float elev = 0.0f;
296 NodeInputParam inp;
297 inp.x = tmp.position.x;
298 inp.y = 0.0f;
299 inp.z = tmp.position.z;
300 inp.minX = 0.0f;
301 inp.minY = 0.0f;
302 inp.minZ = 0.0f;
303 inp.maxX = scale;
304 inp.maxY = scale;
305 inp.maxZ = scale;
306 inp.texX = tmp.texCoord.x;
307 inp.texY = tmp.texCoord.y;
308
309 for (int j = 0; j < cpuNoiseLayers.size(); j++)
310 {
311 if(cpuNoiseLayers[j]->enabled)
312 {
313 elev += cpuNoiseLayers[j]->EvaluateAt(inp.x, inp.y, inp.z);
314 }
315 }
316
317 for(int j = 0 ; j<cpuNodeEditors.size(); j++)
318 {
319 if(cpuNodeEditors[j]->enabled)
320 {
321 elev += cpuNodeEditors[j]->EvaluateAt(inp);
322 }
323 }
324
325 tmp.position *= scale;
326 tmp.position += elev * tmp.normal;
327 customModel->mesh->vert[i].extras1.x += elev;
328 customModel->mesh->vert[i].position += tmp.position;
329 }
330}
331
332void MeshGeneratorManager::ExecuteKernels()
333{
334 if (appState->mode == ApplicationMode::TERRAIN)
335 {
336 if (appState->models.coreTerrain->mesh->res != appState->globals.resolution || appState->models.coreTerrain->mesh->sc != appState->globals.scale)
337 {
338 appState->models.coreTerrain->mesh->res = appState->globals.resolution;
339 appState->models.coreTerrain->mesh->sc = appState->globals.scale;
340 appState->models.coreTerrain->mesh->GeneratePlane(appState->globals.resolution, appState->globals.scale);
341 }
342
343 kernels->CreateBuffer("mesh", CL_MEM_READ_WRITE, appState->models.coreTerrain->mesh->vertexCount * sizeof(Vert));
344 kernels->WriteBuffer("mesh", true, appState->models.coreTerrain->mesh->vertexCount * sizeof(Vert), appState->models.coreTerrain->mesh->vert);
345
346 if(clearMeshGen->useGPU)
347 {
348 clearMeshGen->Generate(kernels);
349 }
350
351 for (int i = 0; i < gpuNoiseLayers.size(); i++)
352 {
353 if (gpuNoiseLayers[i]->enabled)
354 {
355 gpuNoiseLayers[i]->Generate(kernels);
356 }
357 }
358
359 if(clearMeshGen->useGPUForNormals)
360 {
361 kernels->CreateBuffer("indices", CL_MEM_READ_WRITE, appState->models.coreTerrain->mesh->indexCount * sizeof(int));
362 kernels->WriteBuffer("indices", true, appState->models.coreTerrain->mesh->indexCount * sizeof(int), appState->models.coreTerrain->mesh->indices);
363 kernels->SetKernelArg("gen_normals", 0, "mesh");
364 kernels->SetKernelArg("gen_normals", 1, "indices");
365 int ls = 512;
366 int ic = appState->models.coreTerrain->mesh->indexCount;
367
368 while(ic % ls != 0)
369 {
370 ls /= 2;
371 }
372
373 kernels->ExecuteKernel("gen_normals", cl::NDRange(ls), cl::NDRange(ic));
374 kernels->SetKernelArg("normalize_normals", 0, "mesh");
375 kernels->ExecuteKernel("normalize_normals", cl::NDRange(1), cl::NDRange(appState->models.coreTerrain->mesh->vertexCount));
376 }
377
378 kernels->ReadBuffer("mesh", true, appState->models.coreTerrain->mesh->vertexCount * sizeof(Vert), appState->models.coreTerrain->mesh->vert);
379 }
380
381 else if (appState->mode == ApplicationMode::CUSTOM_BASE)
382 {
383 kernels->CreateBuffer("mesh", CL_MEM_READ_WRITE, appState->models.customBase->mesh->vertexCount * sizeof(Vert));
384 kernels->WriteBuffer("mesh", true, appState->models.customBase->mesh->vertexCount * sizeof(Vert), appState->models.customBase->mesh->vert);
385 kernels->CreateBuffer("mesh_copy", CL_MEM_READ_WRITE, appState->models.customBase->mesh->vertexCount * sizeof(Vert));
386 kernels->WriteBuffer("mesh_copy", true, appState->models.customBase->mesh->vertexCount * sizeof(Vert), appState->models.customBaseCopy->mesh->vert);
387
388 if(clearMeshGen->useGPU)
389 {
390 clearMeshGen->Generate(kernels);
391 }
392
393 for (int i = 0; i < gpuNoiseLayers.size(); i++)
394 {
395 if (gpuNoiseLayers[i]->enabled)
396 {
397 gpuNoiseLayers[i]->Generate(kernels);
398 }
399 }
400
401 if(clearMeshGen->useGPUForNormals)
402 {
403 kernels->CreateBuffer("indices", CL_MEM_READ_WRITE, appState->models.customBase->mesh->indexCount * sizeof(int));
404 kernels->WriteBuffer("indices", true, appState->models.customBase->mesh->indexCount * sizeof(int), appState->models.customBase->mesh->indices);
405 kernels->SetKernelArg("gen_normals", 0, "mesh");
406 kernels->SetKernelArg("gen_normals", 1, "indices");
407 int ls = 512;
408 int ic = appState->models.customBase->mesh->indexCount;
409
410 while(ic % ls != 0)
411 {
412 ls /= 2;
413 }
414
415 kernels->ExecuteKernel("gen_normals", cl::NDRange(ls), cl::NDRange(ic));
416 kernels->SetKernelArg("normalize_normals", 0, "mesh");
417 kernels->ExecuteKernel("normalize_normals", cl::NDRange(1), cl::NDRange(appState->models.customBase->mesh->vertexCount));
418 }
419
420 kernels->ReadBuffer("mesh", true, appState->models.customBase->mesh->vertexCount * sizeof(Vert), appState->models.customBase->mesh->vert);
421 }
422}
423
424void MeshGeneratorManager::ExecuteCPUGenerators()
425{
426 if (appState->mode == ApplicationMode::TERRAIN)
427 {
428 GenerateForTerrain();
429 }
430
431 else if (appState->mode == ApplicationMode::CUSTOM_BASE)
432 {
433 GenerateForCustomBase();
434 }
435}
436
437void MeshGeneratorManager::LoadKernels()
438{
439 bool tmp = false;
440 std::string source = ReadShaderSourceFile(GetExecutableDir() + PATH_SEPARATOR "Data" PATH_SEPARATOR "kernels" PATH_SEPARATOR "generators" PATH_SEPARATOR "generators.cl", &tmp);
441 kernels->AddSoruce(source);
442 kernels->BuildProgram("-I" + appState->globals.kernelsIncludeDir + " -cl-fast-relaxed-math -cl-mad-enable");
443 kernels->AddKernel("clear_mesh_terrain");
444 kernels->AddKernel("clear_mesh_custom_base");
445 kernels->AddKernel("noise_layer_terrain");
446 kernels->AddKernel("noise_layer_custom_base");
447 kernels->AddKernel("gen_normals");
448 kernels->AddKernel("normalize_normals");
449}
450
451nlohmann::json MeshGeneratorManager::Save()
452{
453 nlohmann::json data, tmp;
454 data["cmg"] = clearMeshGen->Save();
455
456 for (int i = 0; i < cpuNoiseLayers.size(); i++)
457 {
458 tmp.push_back(cpuNoiseLayers[i]->Save());
459 }
460
461 data["cpunl"] = tmp;
462 tmp = nlohmann::json();
463
464 for (int i = 0; i < gpuNoiseLayers.size(); i++)
465 {
466 tmp.push_back(gpuNoiseLayers[i]->Save());
467 }
468
469 data["gpunl"] = tmp;
470 tmp = nlohmann::json();
471
472 for (int i = 0; i < cpuNodeEditors.size(); i++)
473 {
474 tmp.push_back(cpuNodeEditors[i]->Save());
475 }
476
477 data["cpune"] = tmp;
478 return data;
479}
480
481void MeshGeneratorManager::Load(nlohmann::json data)
482{
483 while (*isRemeshing);
484
485 clearMeshGen->Load(data["cmg"]);
486
487 for (int i = 0; i < cpuNoiseLayers.size(); i++)
488 {
489 delete cpuNoiseLayers[i];
490 }
491
492 cpuNoiseLayers.clear();
493
494 for (int i = 0; i < data["cpunl"].size(); i++)
495 {
496 cpuNoiseLayers.push_back(new CPUNoiseLayersGenerator(appState));
497 cpuNoiseLayers.back()->Load(data["cpunl"][i]);
498 }
499
500 for (int i = 0; i < gpuNoiseLayers.size(); i++)
501 {
502 delete gpuNoiseLayers[i];
503 }
504
505 gpuNoiseLayers.clear();
506
507 for (int i = 0; i < data["gpunl"].size(); i++)
508 {
509 gpuNoiseLayers.push_back(new GPUNoiseLayerGenerator(appState, kernels));
510 gpuNoiseLayers.back()->Load(data["gpunl"][i]);
511 }
512
513 for (int i = 0; i < cpuNodeEditors.size(); i++)
514 {
515 delete cpuNodeEditors[i];
516 }
517
518 cpuNodeEditors.clear();
519
520 for (int i = 0; i < data["cpune"].size(); i++)
521 {
522 cpuNodeEditors.push_back(new CPUNodeEditor(appState));
523 cpuNodeEditors.back()->Load(data["cpune"][i]);
524 }
525}
Definition: Model.h:9
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:22912
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:23148
a class to store JSON values
Definition: json.hpp:17860
basic_json<> json
default JSON class
Definition: json.hpp:3411
Definition: Mesh.h:13