TDME2 1.9.121
TerrainEditorTabView.cpp
Go to the documentation of this file.
2
3#include <string>
4
5#include <tdme/tdme.h>
14#include <tdme/engine/Engine.h>
17#include <tdme/engine/Light.h>
21#include <tdme/engine/Timing.h>
25#include <tdme/gui/GUI.h>
26#include <tdme/math/Vector3.h>
37
38using std::string;
39
41
61using tdme::gui::GUI;
72
73TerrainEditorTabView::TerrainEditorTabView(EditorView* editorView, const string& tabId, Prototype* prototype)
74{
75 this->editorView = editorView;
76 this->tabId = tabId;
77 this->popUps = editorView->getPopUps();
78 this->prototype = prototype;
79 engine = Engine::createOffScreenInstance(512, 512, true, true, true);
80 engine->setSceneColor(Color4(125.0f / 255.0f, 125.0f / 255.0f, 125.0f / 255.0f, 1.0f));
81 for (auto i = 1; i < engine->getLightCount(); i++) engine->getLightAt(i)->setEnabled(false);
82 {
83 auto light0 = engine->getLightAt(0);
84 light0->setAmbient(Color4(0.7f, 0.7f, 0.7f, 1.0f));
85 light0->setDiffuse(Color4(0.3f, 0.3f, 0.3f, 1.0f));
86 light0->setSpecular(Color4(1.0f, 1.0f, 1.0f, 1.0f));
87 light0->setPosition(Vector4(0.0f, 20000.0f, 0.0f, 0.0f));
88 light0->setSpotDirection(Vector3(0.0f, 0.0f, 0.0f).sub(Vector3(light0->getPosition().getX(), light0->getPosition().getY(), light0->getPosition().getZ())).normalize());
89 light0->setConstantAttenuation(0.5f);
90 light0->setLinearAttenuation(0.0f);
91 light0->setQuadraticAttenuation(0.0f);
92 light0->setSpotExponent(0.0f);
93 light0->setSpotCutOff(180.0f);
94 light0->setEnabled(true);
95 }
98}
99
101 delete cameraInputHandler;
102 delete prototype;
104 delete engine;
105}
106
108{
109 brushMoved = false;
110 for (auto i = 0; i < engine->getGUI()->getMouseEvents().size(); i++) {
111 auto& event = engine->getGUI()->getMouseEvents()[i];
112 if (event.isProcessed() == true) continue;
113
114 if (event.getType() == GUIMouseEvent::MOUSEEVENT_WHEEL_MOVED) {
115 if (event.isShiftDown() == true) {
116 setBrushScale(Math::clamp(brushScale + 0.1 * event.getWheelY(), 0.1f, 100.0f));
117 event.setProcessed(true);
118 }
119 if (event.isControlDown() == true) {
120 setBrushDensityStrength(Math::clamp(brushDensityStrength + 0.1 * event.getWheelY(), 0.1f, 100.0f));
121 event.setProcessed(true);
122 }
123 } else
124 if (event.getType() == GUIMouseEvent::MOUSEEVENT_MOVED) {
125 brushMoved = true;
126 engine->getEntityByMousePosition(event.getXUnscaled(), event.getYUnscaled(), brushCenterPosition);
127 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP && rampMode == 0) {
129 //
130 auto brushEnabled = rampVertices[1].clone().sub(rampVertices[0]).computeLength() > 0.1f;
131 brushCenterPosition = rampVertices[0].clone().add(rampVertices[1]).scale(0.5f);
132 engine->setShaderParameter("terraineditor", "brushEnabled", brushEnabled);
133 if (brushEnabled == true) {
134 auto brushRotation = -(Vector3::computeAngle(rampVertices[1].clone().sub(rampVertices[0]).setY(0.0f).normalize(), Vector3(0.0f, 0.0f, -1.0f), Vector3(0.0f, 1.0f, 0.0f)) - 180.0f);
135 if (Math::abs(rampVertices[0].getY() - rampVertices[1].getY()) > Math::EPSILON && rampVertices[0].getY() < rampVertices[1].getY()) brushRotation = brushRotation + 180.0f;
136 engine->setShaderParameter("terraineditor", "brushRotation", brushRotation);
137 engine->setShaderParameter("terraineditor", "brushScale",
138 Vector2(
139 (brushScale * 5.0f) / engine->getShaderParameter("terraineditor", "brushDimension").getVector2Value().getX(),
140 1.0f / (engine->getShaderParameter("terraineditor", "brushDimension").getVector2Value().getY() / rampVertices[1].clone().sub(rampVertices[0]).computeLength())
141 )
142 );
143 }
144 }
145 } else
146 if (event.getButton() == MOUSE_BUTTON_RIGHT) {
147 if (event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
148 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP) {
149 rampMode = -1;
150 engine->setShaderParameter("terraineditor", "brushEnabled", false);
151 engine->setShaderParameter("terraineditor", "brushRotation", 0.0f);
152 engine->setShaderParameter("terraineditor", "brushScale", Vector2(1.0f, 1.0f));
153 }
154 event.setProcessed(true);
155 }
156 } else
157 if (event.getButton() == MOUSE_BUTTON_LEFT) {
158 if (event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
159 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP) {
160 if (engine->getEntityByMousePosition(event.getXUnscaled(), event.getYUnscaled(), brushCenterPosition) != nullptr &&
162 //
163 rampMode++;
165 if (rampMode == 0) {
166 // no op
167 } else
168 if (rampMode == 1) {
169 // place ramp
170 brushCenterPosition = rampVertices[0].clone().add(rampVertices[1]).scale(0.5f);
175 engine->getShaderParameter("terraineditor", "brushRotation").getFloatValue(),
176 engine->getShaderParameter("terraineditor", "brushScale").getVector2Value(),
177 Math::min(rampHeight[0], rampHeight[1]),
178 Math::max(rampHeight[0], rampHeight[1])
179 );
180 //
181 rampMode = -1;
182 engine->setShaderParameter("terraineditor", "brushEnabled", false);
183 engine->setShaderParameter("terraineditor", "brushRotation", 0.0f);
184 engine->setShaderParameter("terraineditor", "brushScale", Vector2(1.0f, 1.0f));
185 }
186 }
187 } else {
190 brushingEnabled = false;
192 }
193 event.setProcessed(true);
194 } else
195 if (event.getType() == GUIMouseEvent::MOUSEEVENT_PRESSED ||
196 event.getType() == GUIMouseEvent::MOUSEEVENT_DRAGGED) {
197 brushMoved = true;
198 if (terrainEditorTabController->getTerrainBrushOperation() != Terrain2::BRUSHOPERATION_RAMP) {
199 engine->getEntityByMousePosition(event.getXUnscaled(), event.getYUnscaled(), brushCenterPosition);
200 }
201 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP) {
202 // no op
203 } else
204 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_WATER_ADD) {
206 vector<Model*> waterModels;
207 Vector3 waterReflectionEnvironmentMappingPosition;
208 terrainEditorTabController->createWater(terrainBoundingBox, brushCenterPosition, waterModels, waterReflectionEnvironmentMappingPosition);
209 brushingEnabled = false;
211 //
212 for (auto waterModel: waterModels) {
213 auto waterObject3D = new Object3D(waterModel->getId(), waterModel);
214 waterObject3D->setRenderPass(Entity::RENDERPASS_WATER);
215 waterObject3D->setShader("water");
216 waterObject3D->setDistanceShader("water");
217 waterObject3D->setContributesShadows(false);
218 waterObject3D->setReceivesShadows(false);
219 waterObject3D->setReflectionEnvironmentMappingId("sky_environment_mapping");
220 waterObject3D->setReflectionEnvironmentMappingPosition(waterReflectionEnvironmentMappingPosition);
221 waterObject3D->setPickable(true);
222 engine->addEntity(waterObject3D);
223 }
224 }
225 } else
226 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_WATER_DELETE) {
227 auto selectedEntity = engine->getEntityByMousePosition(event.getXUnscaled(), event.getYUnscaled());
228 if (selectedEntity != nullptr && StringTools::startsWith(selectedEntity->getId(), "water.") == true) {
229 auto waterBeginIdx = selectedEntity->getId().find('.', selectedEntity->getId().find('.') + 1) + 1;
230 auto waterEndIdx = selectedEntity->getId().find('.', waterBeginIdx + 1);
231 auto waterPositionMapIdx = Integer::parse(StringTools::substring(selectedEntity->getId(), waterBeginIdx, waterEndIdx));
232 terrainEditorTabController->deleteWater(waterPositionMapIdx);
233 } else {
234 brushingEnabled = true;
235 }
236 } else {
237 brushingEnabled = true;
238 }
239 event.setProcessed(true);
240 }
241 }
242 }
243 for (auto i = 0; i < engine->getGUI()->getKeyboardEvents().size(); i++) {
244 auto& event = engine->getGUI()->getKeyboardEvents()[i];
245 if (event.isProcessed() == true) continue;
246 if (event.getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_TYPED) continue;
247 auto isKeyDown = event.getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED;
248 if (event.getKeyCode() == GUIKeyboardEvent::KEYCODE_ESCAPE) {
249 if (isKeyDown == true) {
250 if (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP) {
251 rampMode = -1;
252 engine->setShaderParameter("terraineditor", "brushEnabled", false);
253 engine->setShaderParameter("terraineditor", "brushRotation", 0.0f);
254 engine->setShaderParameter("terraineditor", "brushScale", Vector2(1.0f, 1.0f));
255 }
256 }
257 event.setProcessed(true);
258 }
259 }
261}
262
264{
265 //
266 engine->setShaderParameter("terraineditor", "brushPosition", Vector2(brushCenterPosition.getX(), brushCenterPosition.getZ()));
267
268 //
269 updateSky();
270
271 //
273
274 // actually do the brushing
276 if (terrainEditorTabController->getTerrainBrushOperation() != Terrain2::BRUSHOPERATION_NONE) {
278 }
279 if (terrainEditorTabController->getFoliageBrushOperation() != Terrain2::BRUSHOPERATION_NONE) {
280 if (brushMoved == true) {
282 }
283 }
284 }
285
286 //
287 engine->display();
288}
289
291{
292 try {
295 skySpherePrototype = PrototypeReader::read("resources/engine/models", "sky_sphere.tmodel");
296 skyDomePrototype = PrototypeReader::read("resources/engine/models", "sky_dome.tmodel");
297 skyPanoramaPrototype = PrototypeReader::read("resources/engine/models", "sky_panorama.tmodel");
298 } catch (Exception& exception) {
299 Console::print(string("TerrainEditorTabView::initialize(): An error occurred: "));
300 Console::println(string(exception.what()));
301 }
302 // TODO: load settings
304}
305
307{
308 engine->dispose();
309}
310
312}
313
315 return engine;
316}
317
324}
325
328}
329
334}
335
336void TerrainEditorTabView::saveFile(const string& pathName, const string& fileName)
337{
338 PrototypeWriter::write(pathName, fileName, prototype);
339}
340
342 // sky sphere
343 auto skySphere = new Object3D("sky_sphere", skySpherePrototype->getModel());
344 skySphere->setRenderPass(Entity::RENDERPASS_NOFRUSTUMCULLING);
345 skySphere->setShader("sky");
346 skySphere->setFrustumCulling(false);
347 skySphere->setTranslation(Vector3(0.0f, 0.0f, 0.0f));
348 skySphere->setScale(Vector3(300.0f/200.0f, 300.0f/200.0f, 300.0f/200.0f));
349 skySphere->update();
350 skySphere->setContributesShadows(false);
351 skySphere->setReceivesShadows(false);
352 skySphere->setExcludeEffectPass(Engine::EFFECTPASS_LIGHTSCATTERING);
353 engine->addEntity(skySphere);
354
355 // sky dome
356 auto skyDome = new Object3D("sky_dome", skyDomePrototype->getModel());
357 skyDome->setRenderPass(Entity::RENDERPASS_NOFRUSTUMCULLING);
358 skyDome->setShader("sky");
359 skyDome->setFrustumCulling(false);
360 skyDome->setTranslation(Vector3(0.0f, 0.0f, 0.0f));
361 skyDome->setScale(Vector3(295.0f/190.0f, 295.0f/190.0f, 295.0f/190.0f));
362 skyDome->getModel()->getMaterials().begin()->second->getSpecularMaterialProperties()->setDiffuseTextureMaskedTransparency(true);
363 skyDome->update();
364 skyDome->setContributesShadows(false);
365 skyDome->setReceivesShadows(false);
366 skyDome->setEffectColorMul(Color4(1.0f, 1.0f, 1.0f, 0.7f));
367 skyDome->setExcludeEffectPass(Engine::EFFECTPASS_LIGHTSCATTERING);
368 engine->addEntity(skyDome);
369
370 // sky panorama
371 auto skyPanorama = new Object3D("sky_panorama", skyPanoramaPrototype->getModel());
372 skyPanorama->setRenderPass(Entity::RENDERPASS_NOFRUSTUMCULLING);
373 skyPanorama->setShader("sky");
374 skyPanorama->setFrustumCulling(false);
375 skyPanorama->setTranslation(Vector3(0.0f, 0.0f, 0.0f));
376 skyPanorama->setScale(Vector3(280.0f/190.0f, 280.0f/180.0f, 280.0f/180.0f));
377 skyPanorama->addRotation(Vector3(0.0f, 1.0f, 0.0f), 0.0f);
378 skyPanorama->update();
379 skyPanorama->setContributesShadows(false);
380 skyPanorama->setReceivesShadows(false);
381 skyPanorama->setExcludeEffectPass(Engine::EFFECTPASS_LIGHTSCATTERING);
382 engine->addEntity(skyPanorama);
383
384 auto environmentMapping = new EnvironmentMapping("sky_environment_mapping", Engine::getEnvironmentMappingWidth(), Engine::getEnvironmentMappingHeight(), BoundingBox(Vector3(-30.0f, 0.0f, -30.0f), Vector3(30.0f, 60.0f, -30.0f)));
385 environmentMapping->setFrustumCulling(false);
386 environmentMapping->setRenderPassMask(Entity::RENDERPASS_NOFRUSTUMCULLING);
387 environmentMapping->setTimeRenderUpdateFrequency(33LL);
388 environmentMapping->update();
389 engine->addEntity(environmentMapping);
390}
391
393 auto skySphere = engine->getEntity("sky_sphere");
394 skySphere->setTranslation(engine->getCamera()->getLookFrom());
395 skySphere->update();
396
397 auto skyDome = static_cast<Object3D*>(engine->getEntity("sky_dome"));
399 skyDome->setTextureMatrix((Matrix2D3x3()).identity().translate(Vector2(0.0f, skyDomeTranslation * 0.01f)));
400 skyDome->update();
401
402 auto skyPanorama = engine->getEntity("sky_panorama");
403 skyPanorama->setTranslation(engine->getCamera()->getLookFrom());
404 skyPanorama->setRotationAngle(0, skyDomeTranslation * 1.0f * 0.1f);
405 skyPanorama->update();
406
407 auto environmentMapping = engine->getEntity("sky_environment_mapping");
408 environmentMapping->setTranslation(engine->getCamera()->getLookFrom());
409 environmentMapping->update();
410
411 skyDomeTranslation+= 1.0f / 60.0;
412}
413
415 engine->reset();
416 for (auto terrainModel: terrainModels) delete terrainModel;
418 terrainModels.clear();
419 unsetWater();
420 initSky();
421}
422
424 reset();
425
426 //
427 partitionFoliageIdx.clear();
429
430 //
432
433 //
434 if (terrainModels.empty() == false) {
435 auto idx = 0;
436 for (auto terrainModel: terrainModels) {
437 auto terrainObject3D = new Object3D("terrain." + to_string(idx), terrainModel);
438 terrainObject3D->setNeedsPreRender(true);
439 terrainObject3D->setRenderPass(Entity::RENDERPASS_TERRAIN);
440 terrainObject3D->setShader("terraineditor");
441 terrainObject3D->setDistanceShader("terraineditor");
442 terrainObject3D->setContributesShadows(true);
443 terrainObject3D->setReceivesShadows(true);
444 terrainObject3D->setPickable(true);
445 engine->addEntity(terrainObject3D);
446 idx++;
447 }
448
449 Vector3 sceneCenter = terrainBoundingBox.getCenter();
450 sceneCenter.set(Vector3(sceneCenter.getX(), terrainBoundingBox.getMax().getY() + 3.0f, sceneCenter.getZ()));
452 }
453
454 //
455 if (waters.empty() == false) {
456 for (auto& it: waters) {
457 auto& water = it.second;
458 for (auto waterModel: water.waterModels) {
459 auto waterObject3D = new Object3D(waterModel->getId(), waterModel);
460 waterObject3D->setRenderPass(Entity::RENDERPASS_WATER);
461 waterObject3D->setShader("water");
462 waterObject3D->setDistanceShader("water");
463 waterObject3D->setContributesShadows(false);
464 waterObject3D->setReceivesShadows(false);
465 waterObject3D->setReflectionEnvironmentMappingId("sky_environment_mapping");
466 waterObject3D->setReflectionEnvironmentMappingPosition(water.waterReflectionEnvironmentMappingPosition);
467 waterObject3D->setPickable(true);
468 engine->addEntity(waterObject3D);
469 }
470 }
471 }
472
473 //
474 initSky();
475
476 //
478}
479
481 for (auto& it: waters) {
482 for (auto waterModel: it.second.waterModels) {
483 engine->removeEntity(waterModel->getId());
484 delete waterModel;
485 }
486 }
487 this->waters.clear();
488}
489
491 if (prototype == nullptr) return;
492
493 //
494 auto& foliageMaps = prototype->getTerrain()->getFoliageMaps();
495
496 //
497 auto partitionIdx = 0;
498 for (auto& foliageMapPartition: foliageMaps) {
499 engine->removeEntity("foliage.entityhierarchy." + to_string(partitionIdx));
500 auto shaderParameterIdx = 0;
501 while (engine->removeEntity("foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(shaderParameterIdx)) == true) shaderParameterIdx++;
502 auto partitionPrototypeInstanceCount = 0;
503 for (auto& foliageMapPartitionIt: foliageMapPartition) {
504 partitionPrototypeInstanceCount+= foliageMapPartitionIt.second.size();
505 }
506 if (partitionPrototypeInstanceCount > 0) {
507 unordered_map<string, Object3DRenderGroup*> object3DRenderGroupByShaderParameters;
508 for (auto& foliageMapPartitionIt: foliageMapPartition) {
509 auto prototypeIdx = foliageMapPartitionIt.first;
510 auto& transformationsVector = foliageMapPartitionIt.second;
511 if (transformationsVector.empty() == false) {
512 auto foliagePrototype = prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
513 Object3DRenderGroup* foliagePartitionObject3DRenderGroup = nullptr;
514 auto foliagePartitionObject3DRenderGroupIt = object3DRenderGroupByShaderParameters.find(foliagePrototype->getShaderParameters().getShaderParametersHash());
515 if (foliagePartitionObject3DRenderGroupIt != object3DRenderGroupByShaderParameters.end()) {
516 foliagePartitionObject3DRenderGroup = foliagePartitionObject3DRenderGroupIt->second;
517 }
518 if (foliagePartitionObject3DRenderGroup == nullptr) {
519 foliagePartitionObject3DRenderGroup = new Object3DRenderGroup(
520 "foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(object3DRenderGroupByShaderParameters.size()),
521 1,
522 25.0f,
523 50.0f,
524 4,
525 16,
526 false
527 );
528 foliagePartitionObject3DRenderGroup->setContributesShadows(true);
529 foliagePartitionObject3DRenderGroup->setReceivesShadows(true);
530 foliagePartitionObject3DRenderGroup->setShader(foliagePrototype->getShader());
531 auto shaderParametersDefault = Engine::getShaderParameterDefaults(foliagePrototype->getShader());
532 for (auto& parameterIt: shaderParametersDefault) {
533 auto& parameterName = parameterIt.first;
534 auto parameterValue = foliagePrototype->getShaderParameters().getShaderParameter(parameterName);
535 foliagePartitionObject3DRenderGroup->setShaderParameter(parameterName, parameterValue);
536 }
537 engine->addEntity(foliagePartitionObject3DRenderGroup);
538 object3DRenderGroupByShaderParameters[foliagePrototype->getShaderParameters().getShaderParametersHash()] = foliagePartitionObject3DRenderGroup;
539 }
540 for (auto& transformations: transformationsVector) {
541 foliagePartitionObject3DRenderGroup->addObject(foliagePrototype->getModel(), transformations);
542 }
543 }
544 }
545 for (auto& object3DRenderGroupByShaderParametersIt: object3DRenderGroupByShaderParameters) {
546 object3DRenderGroupByShaderParametersIt.second->updateRenderGroup();
547 }
548 }
549 partitionIdx++;
550 }
551}
552
553void TerrainEditorTabView::addTemporaryFoliage(const vector<unordered_map<int, vector<Transformations>>>& newFoliageMaps) {
554 if (prototype == nullptr) return;
555
556 //
557 auto& foliageMaps = prototype->getTerrain()->getFoliageMaps();
558
559 //
560 auto partitionIdx = 0;
561 for (auto& foliageMapPartition: newFoliageMaps) {
562 auto partitionPrototypeInstanceCount = 0;
563 for (auto& foliageMapPartitionIt: foliageMapPartition) {
564 partitionPrototypeInstanceCount+= foliageMapPartitionIt.second.size();
565 }
566 if (partitionPrototypeInstanceCount > 0) {
567 //
568 temporaryPartitionIdxs.insert(partitionIdx);
569
570 //
571 auto foliagePartitionObject3DRenderGroup = engine->getEntity("foliage.object3drendergroup." + to_string(partitionIdx) + ".0");
572 if (foliagePartitionObject3DRenderGroup != nullptr) {
573 auto shaderParameterIdx = 0;
574 while (engine->removeEntity("foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(shaderParameterIdx)) == true) shaderParameterIdx++;
575 recreateTemporaryFoliage(partitionIdx);
576 }
577 auto foliagePartitionEntityHierarchy = dynamic_cast<EntityHierarchy*>(engine->getEntity("foliage.entityhierarchy." + to_string(partitionIdx)));
578 if (foliagePartitionEntityHierarchy == nullptr) {
579 foliagePartitionEntityHierarchy = new EntityHierarchy("foliage.entityhierarchy." + to_string(partitionIdx));
580 foliagePartitionEntityHierarchy->setContributesShadows(true);
581 foliagePartitionEntityHierarchy->setReceivesShadows(true);
582 engine->addEntity(foliagePartitionEntityHierarchy);
583 }
584 for (auto& foliageMapPartitionIt: foliageMapPartition) {
585 auto prototypeIdx = foliageMapPartitionIt.first;
586 auto& transformationsVector = foliageMapPartitionIt.second;
587 if (transformationsVector.empty() == false) {
588 auto foliagePrototype = prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
589 auto& foliageIdx = partitionFoliageIdx[partitionIdx];
590 for (auto& transformations: transformationsVector) {
591 auto foliageEntity = SceneConnector::createEntity(foliagePrototype, foliagePartitionEntityHierarchy->getId() + "." + to_string(prototypeIdx) + "." + to_string(foliageIdx), transformations, 1, foliagePartitionEntityHierarchy);
592 foliagePartitionEntityHierarchy->addEntity(foliageEntity);
593 foliageIdx++;
594 }
595 }
596 }
597 foliagePartitionEntityHierarchy->update();
598 }
599 partitionIdx++;
600 }
601}
602
603void TerrainEditorTabView::updateTemporaryFoliage(const unordered_set<int>& partitionIdxSet) {
604 if (prototype == nullptr) return;
605
606 //
607 auto& foliageMaps = prototype->getTerrain()->getFoliageMaps();
608
609 //
610 auto partitionIdx = 0;
611 for (auto partitionIdx: partitionIdxSet) {
612 auto& foliageMapPartition = foliageMaps[partitionIdx];
613 auto partitionPrototypeInstanceCount = 0;
614 for (auto& foliageMapPartitionIt: foliageMapPartition) {
615 partitionPrototypeInstanceCount+= foliageMapPartitionIt.second.size();
616 }
617 if (partitionPrototypeInstanceCount > 0) {
618 //
619 temporaryPartitionIdxs.insert(partitionIdx);
620
621 //
622 auto foliagePartitionObject3DRenderGroup = engine->getEntity("foliage.object3drendergroup." + to_string(partitionIdx) + ".0");
623 auto foliagePartitionEntityHierarchy = dynamic_cast<EntityHierarchy*>(engine->getEntity("foliage.entityhierarchy." + to_string(partitionIdx)));
624 if (foliagePartitionObject3DRenderGroup != nullptr || foliagePartitionEntityHierarchy == nullptr) {
625 auto shaderParameterIdx = 0;
626 while (engine->removeEntity("foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(shaderParameterIdx)) == true) shaderParameterIdx++;
627 recreateTemporaryFoliage(partitionIdx);
628 }
629 if (foliagePartitionEntityHierarchy == nullptr) foliagePartitionEntityHierarchy = dynamic_cast<EntityHierarchy*>(engine->getEntity("foliage.entityhierarchy." + to_string(partitionIdx)));
630 auto foliageIdx = 0;
631 for (auto& foliageMapPartitionIt: foliageMapPartition) {
632 auto& transformationsVector = foliageMapPartitionIt.second;
633 for (auto i = 0; i < transformationsVector.size(); i++) {
634 foliagePartitionEntityHierarchy->getEntities()[foliageIdx]->fromTransformations(transformationsVector[i]);
635 foliageIdx++;
636 }
637 }
638 foliagePartitionEntityHierarchy->update();
639 }
640 partitionIdx++;
641 }
642}
643
645 if (prototype == nullptr) return;
646
647 //
648 temporaryPartitionIdxs.insert(partitionIdx);
649
650 //
651 auto& foliageMaps = prototype->getTerrain()->getFoliageMaps();
652
653 //
654 auto& foliageMapPartition = foliageMaps[partitionIdx];
655 engine->removeEntity("foliage.entityhierarchy." + to_string(partitionIdx));
656 auto shaderParameterIdx = 0;
657 while (engine->removeEntity("foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(shaderParameterIdx)) == true) shaderParameterIdx++;
658 auto partitionPrototypeInstanceCount = 0;
659 for (auto& foliageMapPartitionIt: foliageMapPartition) {
660 partitionPrototypeInstanceCount+= foliageMapPartitionIt.second.size();
661 }
662 if (partitionPrototypeInstanceCount > 0) {
663 auto foliagePartitionEntityHierarchy = new EntityHierarchy("foliage.entityhierarchy." + to_string(partitionIdx));
664 foliagePartitionEntityHierarchy->setContributesShadows(true);
665 foliagePartitionEntityHierarchy->setReceivesShadows(true);
666 engine->addEntity(foliagePartitionEntityHierarchy);
667 for (auto& foliageMapPartitionIt: foliageMapPartition) {
668 auto prototypeIdx = foliageMapPartitionIt.first;
669 auto foliagePrototype = prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
670 auto& transformationsVector = foliageMapPartitionIt.second;
671 auto& foliageIdx = partitionFoliageIdx[partitionIdx];
672 for (auto& transformations: transformationsVector) {
673 auto foliageEntity = SceneConnector::createEntity(foliagePrototype, foliagePartitionEntityHierarchy->getId() + "." + to_string(prototypeIdx) + "." + to_string(foliageIdx), transformations, 1, foliagePartitionEntityHierarchy);
674 foliagePartitionEntityHierarchy->addEntity(foliageEntity);
675 foliageIdx++;
676 }
677 }
678 foliagePartitionEntityHierarchy->update();
679 }
680}
681
682void TerrainEditorTabView::recreateFoliage(const unordered_set<int>& partitionIdxSet) {
683 if (prototype == nullptr) return;
684
685 //
686 auto& foliageMaps = prototype->getTerrain()->getFoliageMaps();
687
688 //
689 for (auto partitionIdx: partitionIdxSet) {
690 auto& foliageMapPartition = foliageMaps[partitionIdx];
691 engine->removeEntity("foliage.entityhierarchy." + to_string(partitionIdx));
692 auto shaderParameterIdx = 0;
693 while (engine->removeEntity("foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(shaderParameterIdx)) == true) shaderParameterIdx++;
694 auto partitionPrototypeInstanceCount = 0;
695 for (auto& foliageMapPartitionIt: foliageMapPartition) {
696 partitionPrototypeInstanceCount+= foliageMapPartitionIt.second.size();
697 }
698 if (partitionPrototypeInstanceCount > 0) {
699 unordered_map<string, Object3DRenderGroup*> object3DRenderGroupByShaderParameters;
700 for (auto& foliageMapPartitionIt: foliageMapPartition) {
701 auto prototypeIdx = foliageMapPartitionIt.first;
702 auto& transformationsVector = foliageMapPartitionIt.second;
703 if (transformationsVector.empty() == false) {
704 auto foliagePrototype = prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
705 Object3DRenderGroup* foliagePartitionObject3DRenderGroup = nullptr;
706 auto foliagePartitionObject3DRenderGroupIt = object3DRenderGroupByShaderParameters.find(foliagePrototype->getShaderParameters().getShaderParametersHash());
707 if (foliagePartitionObject3DRenderGroupIt != object3DRenderGroupByShaderParameters.end()) {
708 foliagePartitionObject3DRenderGroup = foliagePartitionObject3DRenderGroupIt->second;
709 }
710 if (foliagePartitionObject3DRenderGroup == nullptr) {
711 foliagePartitionObject3DRenderGroup = new Object3DRenderGroup(
712 "foliage.object3drendergroup." + to_string(partitionIdx) + "." + to_string(object3DRenderGroupByShaderParameters.size()),
713 1,
714 25.0f,
715 50.0f,
716 4,
717 16,
718 false
719 );
720 foliagePartitionObject3DRenderGroup->setContributesShadows(true);
721 foliagePartitionObject3DRenderGroup->setReceivesShadows(true);
722 foliagePartitionObject3DRenderGroup->setShader(foliagePrototype->getShader());
723 auto shaderParametersDefault = Engine::getShaderParameterDefaults(foliagePrototype->getShader());
724 for (auto& parameterIt: shaderParametersDefault) {
725 auto& parameterName = parameterIt.first;
726 auto parameterValue = foliagePrototype->getShaderParameters().getShaderParameter(parameterName);
727 foliagePartitionObject3DRenderGroup->setShaderParameter(parameterName, parameterValue);
728 }
729 engine->addEntity(foliagePartitionObject3DRenderGroup);
730 object3DRenderGroupByShaderParameters[foliagePrototype->getShaderParameters().getShaderParametersHash()] = foliagePartitionObject3DRenderGroup;
731 }
732 for (auto& transformations: transformationsVector) {
733 foliagePartitionObject3DRenderGroup->addObject(foliagePrototype->getModel(), transformations);
734 }
735 }
736 }
737 for (auto& object3DRenderGroupByShaderParametersIt: object3DRenderGroupByShaderParameters) {
738 object3DRenderGroupByShaderParametersIt.second->updateRenderGroup();
739 }
740 }
741 }
742}
743
745 auto& water = waters[waterIdx];
746 for (auto waterModel: water.waterModels) {
747 engine->removeEntity(waterModel->getId());
748 delete waterModel;
749 }
750 waters.erase(waterIdx);
751}
752
753void TerrainEditorTabView::addWater(int waterIdx, vector<Model*> waterModels, const Vector3& waterReflectionEnvironmentMappingPosition) {
754 auto& water = waters[waterIdx];
755 for (auto waterModel: water.waterModels) {
756 engine->removeEntity(waterModel->getId());
757 delete waterModel;
758 }
759 water.waterModels = waterModels;
760 water.waterReflectionEnvironmentMappingPosition = waterReflectionEnvironmentMappingPosition;
761}
762
764 for (auto terrainModel: this->terrainModels) delete terrainModel;
766 this->terrainModels.clear();
767 this->partitionFoliageIdx.clear();
768}
769
770void TerrainEditorTabView::setTerrain(BoundingBox& terrainBoundingBox, vector<Model*> terrainModels) {
771 unsetTerrain();
772 this->terrainBoundingBox = terrainBoundingBox;
773 this->terrainModels = terrainModels;
774 this->partitionFoliageIdx.resize(terrainModels.size());
775}
776
777void TerrainEditorTabView::setBrush(Texture* texture, float scale, float densityStrength) {
778 unsetBrush();
779 if (texture != nullptr) texture->acquireReference();
780 brushTexture = texture;
781 //
782 brushScale = scale;
783 auto _scale = terrainEditorTabController->getTerrainBrushOperation() != Terrain2::BRUSHOPERATION_RAMP?scale:1.0f;
784 engine->setShaderParameter("terraineditor", "brushDimension", Vector2(static_cast<int>(texture->getTextureWidth()) * _scale, static_cast<int>(texture->getTextureHeight()) * _scale));
785 engine->setShaderParameter("terraineditor", "brushTexture", brushTexture == nullptr?0:engine->getTextureManager()->addTexture(brushTexture));
787 "terraineditor",
788 "brushEnabled",
789 (terrainEditorTabController->getTerrainBrushOperation() != Terrain2::BRUSHOPERATION_NONE && terrainEditorTabController->getTerrainBrushOperation() != Terrain2::BRUSHOPERATION_RAMP) ||
790 terrainEditorTabController->getFoliageBrushOperation() != Terrain2::BRUSHOPERATION_NONE
791 );
792 rampMode = -1;
793 brushDensityStrength = densityStrength;
794}
795
797 if (brushTexture == nullptr ||
798 terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP ||
799 terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_WATER_ADD ||
800 (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_NONE && terrainEditorTabController->getFoliageBrushOperation() == Terrain2::BRUSHOPERATION_NONE)) return;
801 engine->setShaderParameter("terraineditor", "brushDimension", Vector2(static_cast<int>(brushTexture->getTextureWidth()) * scale, static_cast<int>(brushTexture->getTextureHeight()) * scale));
802 brushScale = scale;
804}
805
807 if (brushTexture == nullptr ||
808 terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_RAMP ||
809 terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_WATER_ADD ||
810 (terrainEditorTabController->getTerrainBrushOperation() == Terrain2::BRUSHOPERATION_NONE && terrainEditorTabController->getFoliageBrushOperation() == Terrain2::BRUSHOPERATION_NONE)) return;
811 brushDensityStrength = densityStrength;
813}
814
816 if (brushTexture != nullptr) {
819 brushTexture = nullptr;
820 engine->setShaderParameter("terraineditor", "brushEnabled", false);
821 }
822}
#define MOUSE_BUTTON_LEFT
#define MOUSE_BUTTON_RIGHT
const Vector3 & getLookFrom() const
Definition: Camera.h:213
Engine main class.
Definition: Engine.h:122
bool removeEntity(const string &id)
Removes an entity.
Definition: Engine.cpp:451
Timing * getTiming()
Definition: Engine.h:900
int32_t getLightCount()
Definition: Engine.h:941
void display()
Renders the scene.
Definition: Engine.cpp:1269
Light * getLightAt(int32_t idx)
Returns light at idx (0 <= idx < 8)
Definition: Engine.h:950
void setShaderParameter(const string &shaderId, const string &parameterName, const ShaderParameter &parameterValue)
Set shader parameter for given shader id and parameter name.
Definition: Engine.h:812
Entity * getEntityByMousePosition(int32_t mouseX, int32_t mouseY, EntityPickingFilter *filter=nullptr, Node **object3DNode=nullptr, ParticleSystemEntity **particleSystemEntity=nullptr)
Retrieves entity by mouse position.
Definition: Engine.h:1068
static TextureManager * getTextureManager()
Definition: Engine.h:564
void addEntity(Entity *entity)
Adds an entity by id.
Definition: Engine.cpp:364
const ShaderParameter getShaderParameter(const string &shaderId, const string &parameterName)
Returns shader parameter for given shader id and parameter name, if the value does not exist,...
Definition: Engine.h:792
void dispose()
Shutdown the engine.
Definition: Engine.cpp:1907
Entity * getEntity(const string &id)
Returns a entity by given id.
Definition: Engine.h:981
void reset()
Removes all entities and caches.
Definition: Engine.cpp:652
void setSceneColor(const Color4 &sceneColor)
Set scene color.
Definition: Engine.h:965
Camera * getCamera()
Definition: Engine.h:907
Entity hierarchy to be used with engine class.
const vector< Entity * > & getEntities()
virtual const string & getId()=0
virtual void setTranslation(const Vector3 &translation)=0
Set translation.
Environment mapping entity.
Light representation.
Definition: Light.h:32
void setEnabled(bool enabled)
Set enabled.
Definition: Light.h:82
void setAmbient(const Color4 &ambient)
Set ambient light component.
Definition: Light.h:97
Object 3D render group for static objects that might be animated by shaders.
void setShader(const string &id)
Set shader id.
void setReceivesShadows(bool receivesShadows) override
Enable/disable receives shadows.
void addObject(Model *model, const Transformations &transformations)
Adds a instance to this render group.
void setShaderParameter(const string &parameterName, const ShaderParameter &parameterValue)
Set shader parameter for given parameter name.
void setContributesShadows(bool contributesShadows) override
Enable/disable contributes shadows.
Object 3D to be used with engine class.
Definition: Object3D.h:60
void setTranslation(const Vector3 &translation) override
Set translation.
Definition: Object3D.h:271
Scene engine/physics connector.
const Vector2 getVector2Value() const
Timing class.
Definition: Timing.h:17
int64_t getDeltaTime()
Gets the time passed between last and current frame.
Definition: Timing.h:83
float getAvarageFPS()
Definition: Timing.h:100
const string & getId() const
Definition: Texture.h:60
Color 4 definition.
Definition: Color4.h:20
Represents a material.
Definition: Material.h:21
Represents specular material properties.
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:25
const Vector3 & getCenter() const
Definition: BoundingBox.h:120
vector< unordered_map< int, vector< Transformations > > > & getFoliageMaps()
Prototype * getFoliagePrototype(int prototypeIdx)
Get foliage prototype by given index.
Prototype definition.
Definition: Prototype.h:49
PrototypeTerrain * getTerrain()
Definition: Prototype.h:561
void removeTexture(const string &textureId)
Removes a texture from manager / open gl stack.
TextureManager_TextureManaged * addTexture(const string &id, bool &created)
Adds a texture to manager.
GUI module class.
Definition: GUI.h:66
vector< GUIMouseEvent > & getMouseEvents()
Definition: GUI.h:212
vector< GUIKeyboardEvent > & getKeyboardEvents()
Definition: GUI.h:219
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:57
3x3 2D Matrix class
Definition: Matrix2D3x3.h:22
2D vector 2 class
Definition: Vector2.h:19
float getY() const
Definition: Vector2.h:111
float getX() const
Definition: Vector2.h:94
3D vector 3 class
Definition: Vector3.h:22
float getY() const
Definition: Vector3.h:119
float getX() const
Definition: Vector3.h:103
float getZ() const
Definition: Vector3.h:136
Vector3 & normalize()
Normalize the vector.
Definition: Vector3.h:288
Vector3 & set(float x, float y, float z)
Set up vector.
Definition: Vector3.h:73
3D vector 4 class
Definition: Vector4.h:19
void restoreOutlinerState(const TabView::OutlinerState &outlinerState)
Restore outliner state.
void storeOutlinerState(TabView::OutlinerState &outlinerState)
Store outliner state.
void setDetailsContent(const string &xml)
Set details content.
void handleInputEvents() override
Handle input events that have not yet been processed.
void setSceneCenter(const Vector3 &sceneCenter)
Set scene center.
void updateInfoText(const MutableString &text)
Update info text line.
void applyTerrainBrush(BoundingBox &terrainBoundingBox, vector< Model * > &terrainModels, const Vector3 &brushCenterPosition, int64_t deltaTime)
Apply current brush to terrain at given brush center position.
bool determineCurrentBrushHeight(BoundingBox &terrainBoundingBox, vector< Model * > terrainModels, const Vector3 &brushCenterPosition)
Determine current brush flatten height.
void setBrushDensityStrength(float densityStrength)
Set brush density/strength.
bool determineRampHeight(BoundingBox &terrainBoundingBox, vector< Model * > terrainModels, const Vector3 &position, float &height)
Determine ramp height.
void applyRampTerrainBrush(BoundingBox &terrainBoundingBox, vector< Model * > &terrainModels, const Vector3 &position, float rotation, const Vector2 &scale, float minHeight, float maxHeight)
Apply current brush to terrain at given brush center position.
void createWater(BoundingBox &terrainBoundingBox, const Vector3 &brushCenterPosition, vector< Model * > &waterModels, Vector3 &waterReflectionEnvironmentMappingPosition)
Create water using a auto fill like algorithm.
void applyFoliageBrush(BoundingBox &terrainBoundingBox, const Vector3 &brushCenterPosition, int64_t deltaTime)
Apply current brush to foliage at given brush center position.
void saveFile(const string &pathName, const string &fileName)
Saving prototype as tmodel prototype.
void recreateFoliage(const unordered_set< int > &partitionIdxSet)
Recreate foliage using render groups at given partition indices that has been transformed to temporar...
void addWater(int waterIdx, vector< Model * > waterModels, const Vector3 &waterReflectionEnvironmentMappingPosition)
Add water.
void updateTemporaryFoliage(const unordered_set< int > &partitionIdxSet)
Update temporary foliage.
void addFoliage()
Add foliage using render groups at given partition indices.
void setBrushDensityStrength(float densityStrength)
Set brush density/strength.
void handleInputEvents() override
Handle input events that have not yet been processed.
void addTemporaryFoliage(const vector< unordered_map< int, vector< Transformations > > > &newFoliageMaps)
Add temporary foliage.
void recreateTemporaryFoliage(const unordered_set< int > &partitionIdxSet)
Recreate temporary foliage at given partition indices.
void setBrush(Texture *texture, float scale, float densityStrength)
Set brush.
void setTerrain(BoundingBox &terrainBoundingBox, vector< Model * > terrainModels)
Set terrain models.
EditorScreenController * getScreenController()
Definition: EditorView.h:57
Console class.
Definition: Console.h:26
Integer class.
Definition: Integer.h:26
Mutable string class.
Definition: MutableString.h:16
MutableString & append(char c)
Append character.
void releaseReference()
releases a reference, thus decrementing the counter and delete it if reference counter is zero
Definition: Reference.cpp:20
void acquireReference()
acquires a reference, incrementing the counter
Definition: Reference.cpp:16
String tools class.
Definition: StringTools.h:20
Terrain 2 utility.
Definition: Terrain2.h:33
std::exception Exception
Exception base class.
Definition: Exception.h:19