From f6beaf48ea7fb4ffef1836c122ea9f13003a0373 Mon Sep 17 00:00:00 2001 From: sebastian Date: Sun, 8 Feb 2026 13:31:05 +0100 Subject: [PATCH] ADD: Multiple Tree Types --- CMakeLists.txt | 2 ++ assets/trees/tree.png | Bin 0 -> 5392 bytes src/engine/renderer/model/AssetManager.cpp | 25 +++++++++++++ src/engine/renderer/model/AssetManager.h | 24 +++++++++++++ src/game/GameLayer.cpp | 10 ++++-- src/game/GameLayer.h | 2 -- src/game/hexWorld/MapGenerator.h | 40 ++++++++++++++++++--- 7 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 assets/trees/tree.png create mode 100644 src/engine/renderer/model/AssetManager.cpp create mode 100644 src/engine/renderer/model/AssetManager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d7931e..17b0f91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,8 @@ add_executable(Dicewars_Siedler src/main.cpp src/engine/renderer/TerrainRenderer.h src/engine/renderer/shaders/TerrainShader.cpp src/engine/renderer/shaders/TerrainShader.h + src/engine/renderer/model/AssetManager.cpp + src/engine/renderer/model/AssetManager.h ) target_include_directories(Dicewars_Siedler PRIVATE diff --git a/assets/trees/tree.png b/assets/trees/tree.png new file mode 100644 index 0000000000000000000000000000000000000000..a76bc86663a947e272b951b291c73f2de244e880 GIT binary patch literal 5392 zcmeHLYfzJC7Cs4(AYg)*T~jfM+iKNb5EZ3z2~w@fQlYlCSS$gg6(xqCNP^_5Y@x2& zxMf+i-0ZR?RLV^Vfd-Pew8T~+T7+N%NoW*A440xI_iP0FqccvYyWRb>!;kNKzw^$# zXP)Od=Q;1pcj}Gk9rL}GdI7-v$er8X1VFkzk>H7PEf2G9SzHSuS_^pKstHQRPS1cjTTcdST7C%s_V+6qmEI^d`4TYm8;d}C{au; zcfEv!BRXx@R;lv^{6^-ck40iB{phuM;J~`WZX_(<3cf1=*3SiV8qD>;#gU1xCSr2fTft`bg*?^3Fd5G|n0G?NNmb2nPSN+!6_!&4LiS4)nW39&)nxdLBe5L<4UqcVU+a+iI$28_D|ZbN`$xL#Sd z2cHe1>9}-10g4vy%{x>V?{}a|NcQHL_nwgtzprMF-SUNG&+GCb-GnA*bf4Hw=^-;& zOiSxNbzRkZ8Bs|I0c(vKfjgXrmJK#>SNGc6Cx~u|%l0d2$7_GEJW9K&lL+)`m`I!eJ~25m2jk zvzJywAHl&WD@xYsEUeG&1loe4h4$fuk`g}&Lw~2S2)=yYRfJ=u+<*i-_hsmy07(*9 zhBVzR5UBD6#8R}@bc%7AO=3zasVkL(YbP{Qt8!0B*spis&O7(><@e)O7Z=x*;MQV_ z-E;*b%nHxuu{K%i0{Hq&j%89#>6^l99a&m~d~BqE66C?$IoFr0gVJ@0hGLqi%|en$3ntPs&g<_Hfy7MhwIL28v%H zwo%wARw-%-)R>av{}>2zL|ZM_3=%$>X6@yR#JMLnVVWn=W^UTq+V6tdpAgR|nzLzEbF4yGPV83`;+Pfq&DK33EaM10OaCF=d7<2(rZk`xHAC44?YF-* z*{(FKZQS~JXBlNjSL+Qz9JhXeYq>BIhAj!}C0ON!s(fj7b(r1pt?_Cd>Bpjc!{CXY z)cCfy;oJs$jg#f2i-YS+ss(*P03V# zkm?JD_Mp~&TW#o^j^3roR;CJTR4>5Qr6~LRqh{MU;(Ag5+1)g9mrb=-J!cRU@|&dQ z``fG|M7~IBuT`q~HIiGLhj*_TYNgp92-)U1CSyX=qZB-nw^PC$?bq7%g=%I_nJp=c z8ka!hPM2wE*jDyd=7cc(5VoZG3p~dVqb{%21~%7+(QVtSdcN9U1Lv`fP?@2hapOkL=QKV9RZdG4+QJXf-by+Qe)yy^$+;XY^7vl6QU`bj2@KO!H$M#OB{aVaF(P2uxX1O@n4l6KR{w ze3~(T{2A7f6zj1pL-}bDwIujFW5GLAJby4NZ0eNJIP#4> zXYjl|jb>G92^2x8_%nM?w@4^uv0|(mos~b(uQ~oe!Ta3`_^5>h9fQu>L#_7kG&_Gm z0H)>aX{Op-#lV)O=heomv?QV?L=&Xzj%uIK_HStA+8Txia^Bvzs-5dRw(f2^t0Va< z`Ujf`>PfcVqhK`Q0d+~P-lT9E_gKfggBr)fvZJhn`J!Fz&b+PeP!$Qj8_+VASK_h* zt~q6kobDP4LiFZcaZVN_O`H`Y68c?yC)yJF`~BZ*Nha{R1Nv1Fd+Re*^KfV6)KIc( zSjvwbHP;w#7Krnb89S_nT2i-$~n`b8+YV^l?y$Hq1o|$Tee@Ky?nMwZj3>CNMhnDS8<=9C`LZ6Y~=x*ZI<~jw8bywf7-Fd zD`rIWQsE&D?eky-TzrD!+*`B!d~yO5ohWe?_X&!lUNimm zY0`xEY!m-lH~c*RQ%&^59tRoFj1Q>G2i{L8q7je#YtE# + +#include "../loader/OBJLoader.h" + + +std::shared_ptr AssetManager::loadModel(const std::string &name, const std::string &objPath, const std::string &texturePath, Loader &loader) { + if (models.contains(name)) { + return models[name]; + } + + auto model = OBJLoader::loadModel(objPath, texturePath, loader); + models[name] = model; + return model; +} + +std::shared_ptr AssetManager::getModel(const std::string &name) { + assert(models.contains(name) && "Model not found!"); + return models.at(name); +} diff --git a/src/engine/renderer/model/AssetManager.h b/src/engine/renderer/model/AssetManager.h new file mode 100644 index 0000000..171749c --- /dev/null +++ b/src/engine/renderer/model/AssetManager.h @@ -0,0 +1,24 @@ +// +// Created by sebastian on 08.02.26. +// + +#ifndef ASSETMANAGER_H +#define ASSETMANAGER_H +#include +#include + +#include "TexturedModel.h" +#include "../loader/Loader.h" + + +class AssetManager { +public: + static std::shared_ptr loadModel(const std::string& name, const std::string& objPath, const std::string& texturePath, Loader& loader); + static std::shared_ptr getModel(const std::string& name); +private: + static inline std::unordered_map> models; +}; + + + +#endif //ASSETMANAGER_H diff --git a/src/game/GameLayer.cpp b/src/game/GameLayer.cpp index cec13f5..c6c6041 100644 --- a/src/game/GameLayer.cpp +++ b/src/game/GameLayer.cpp @@ -11,6 +11,7 @@ #include "../engine/renderer/textures/ModelTexture.h" #include "../engine/toolbox/MathUtils.h" #include "../engine/layer/entities/Light.h" +#include "../engine/renderer/model/AssetManager.h" #include "hexWorld/HexModelFactory.h" #include "hexWorld/MapGenerator.h" @@ -31,9 +32,12 @@ void GameLayer::onAttach() hexModelWood = std::make_shared(HexModelFactory::createTexturedHexModel(loader, 10.0f, RessourceType::WOOD)); map = std::make_unique(); - treeModel = std::make_unique(*OBJLoader::loadModel("assets/trees/lowPolyTree.obj", "assets/trees/lowPolyTree.png", loader)); - treeEntity = std::make_unique(Entity(treeModel, glm::vec3(0,0,0), 0,0,0, 0.5f)); - MapGenerator::generateHexMap(*map, 10,10,10.f, mapEntities, treeModel); + AssetManager::loadModel("lowPolyTree", "assets/trees/lowPolyTree.obj", "assets/trees/lowPolyTree.png", loader); + AssetManager::loadModel("lowPolyTree2", "assets/trees/tree.obj", "assets/trees/tree.png", loader); + + //treeModel = std::make_unique(*OBJLoader::loadModel("assets/trees/lowPolyTree.obj", "assets/trees/lowPolyTree.png", loader)); + //treeEntity = std::make_unique(Entity(treeModel, glm::vec3(0,0,0), 0,0,0, 0.5f)); + MapGenerator::generateHexMap(*map, 10,10,10.f, mapEntities); printf("Generated Terrain with %lu Tiles!\n", map->tiles.size()); } diff --git a/src/game/GameLayer.h b/src/game/GameLayer.h index ad00cf1..e5ccafc 100644 --- a/src/game/GameLayer.h +++ b/src/game/GameLayer.h @@ -36,8 +36,6 @@ private: std::shared_ptr hexModelWood; std::vector> tileEntities; - std::shared_ptr treeModel; - std::unique_ptr treeEntity; std::vector> mapEntities; std::unique_ptr map; diff --git a/src/game/hexWorld/MapGenerator.h b/src/game/hexWorld/MapGenerator.h index b1ed0e4..2a248eb 100644 --- a/src/game/hexWorld/MapGenerator.h +++ b/src/game/hexWorld/MapGenerator.h @@ -9,10 +9,11 @@ #include "HexTile.h" #include "Map.h" +#include "../../engine/renderer/model/AssetManager.h" class MapGenerator { public: - static void generateHexMap(Map& map, int width, int height, float hexRadius, std::vector>& mapEntities, const std::shared_ptr& treeModel) { + static void generateHexMap(Map& map, int width, int height, float hexRadius, std::vector>& mapEntities) { // Zufallsgenerator initialisieren (einmal) std::random_device rd; // Zufälliger Seed std::mt19937 gen(rd()); // Mersenne Twister Generator @@ -24,6 +25,12 @@ public: float xOffset = hexRadius * std::sqrt(3.0f); float zOffset = hexRadius * 1.5f; + std::shared_ptr treeModel = AssetManager::getModel("lowPolyTree"); + std::shared_ptr treeModel2 = AssetManager::getModel("lowPolyTree2"); + std::vector> treeModels = {treeModel, treeModel2}; + + std::uniform_int_distribution treeModelDistribution(0, treeModels.size() - 1); + for (int r = 0; r < height; ++r) { for (int q = 0; q < width; ++q) { HexTile tile; @@ -43,17 +50,40 @@ public: int treeCount = 3 + (int) (dis(gen) * 3); std::uniform_real_distribution offsetDis(-hexRadius * 0.5f, hexRadius * 0.5f); + float minDistance = 3.0f; // Minimaler Abstand zwischen Bäumen + for (int i = 0; i < treeCount; ++i) { - glm::vec3 treePos = tile.worldPos; - treePos.x += offsetDis(gen); - treePos.z += offsetDis(gen); + glm::vec3 treePos; + bool validPos = false; - std::shared_ptr treeEntity = std::make_shared(Entity(treeModel, treePos, 0,0,0,.4f)); + // versuche zufällige Position, bis Abstand stimmt oder max Versuche erreicht + int attempts = 0; + const int maxAttempts = 10; + while (!validPos && attempts < maxAttempts) { + treePos = tile.worldPos; + treePos.x += offsetDis(gen); + treePos.z += offsetDis(gen); + + validPos = true; + for (const auto& otherTree : tile.entitiesOnTile) { + if (glm::distance(treePos, otherTree->getPosition()) < minDistance) { + validPos = false; + break; + } + } + attempts++; + } + + if (!validPos) continue; // zu viele Versuche, überspringen + + int treeModelIndex = treeModelDistribution(gen); + auto treeEntity = std::make_shared(treeModels[treeModelIndex], treePos, 0, 0, 0, 1.f); mapEntities.push_back(treeEntity); tile.entitiesOnTile.push_back(treeEntity); } + } map.tiles.push_back(tile);