TerrainPack.java 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package eu.tankernn.gameEngine.terrains;
  2. import static eu.tankernn.gameEngine.settings.Settings.TERRAIN_SIZE;
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.concurrent.Callable;
  9. import java.util.concurrent.ExecutionException;
  10. import java.util.concurrent.ExecutorService;
  11. import java.util.concurrent.Executors;
  12. import java.util.concurrent.Future;
  13. import org.apache.commons.lang3.tuple.Pair;
  14. import eu.tankernn.gameEngine.MainLoop;
  15. import eu.tankernn.gameEngine.loader.Loader;
  16. import eu.tankernn.gameEngine.loader.textures.TerrainTexturePack;
  17. import eu.tankernn.gameEngine.loader.textures.Texture;
  18. import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
  19. import eu.tankernn.gameEngine.util.IPositionable;
  20. public class TerrainPack {
  21. private Map<Pair<Integer, Integer>, Terrain> terrains = new HashMap<Pair<Integer, Integer>, Terrain>();
  22. private Map<Pair<Integer, Integer>, Future<TerrainModelData>> waitingData = new HashMap<Pair<Integer, Integer>, Future<TerrainModelData>>();
  23. private List<IPositionable> waitingForHeight = new ArrayList<IPositionable>();
  24. private ExecutorService executor = Executors.newCachedThreadPool();
  25. private int seed;
  26. private Loader loader;
  27. private TerrainTexturePack texturePack;
  28. // TODO Generate blendMap based on seed.
  29. private Texture blendMap;
  30. private int lastX = 0, lastZ = 0;
  31. public TerrainPack(Loader loader, TerrainTexturePack texturePack, Texture blendMap, int seed) {
  32. this.seed = seed;
  33. this.loader = loader;
  34. this.texturePack = texturePack;
  35. this.blendMap = blendMap;
  36. }
  37. public boolean addTerrain(Terrain terrain) {
  38. if (terrain != null) {
  39. terrains.put(terrain.getGridPosition(), terrain);
  40. return true;
  41. } else {
  42. return false;
  43. }
  44. }
  45. public List<Terrain> getList() {
  46. return (List<Terrain>) terrains.values();
  47. }
  48. public Pair<Integer, Integer> getGridPosByWorldPos(float x, float z) {
  49. return Pair.of((int) Math.floor(x / TERRAIN_SIZE), (int) Math.floor(z / TERRAIN_SIZE));
  50. }
  51. public Terrain getTerrainByWorldPos(float x, float z) {
  52. return terrains.get(getGridPosByWorldPos(x, z));
  53. }
  54. public float getTerrainHeightByWorldPos(float x, float z) {
  55. Terrain terrain = getTerrainByWorldPos(x, z);
  56. if (terrain != null)
  57. return terrain.getHeightOfTerrain(x, z);
  58. else
  59. return 0;
  60. }
  61. public void prepareRenderTerrains(MasterRenderer renderer) {
  62. for (Terrain terrain : terrains.values()) {
  63. renderer.processTerrain(terrain);
  64. }
  65. }
  66. /**
  67. * Generates the terrains in a 3x3 area around the specified position.
  68. *
  69. * @param pos
  70. * The object to get the position from
  71. */
  72. public void update(IPositionable pos) {
  73. Pair<Integer, Integer> currentTerrain = getGridPosByWorldPos(pos.getPosition().x, pos.getPosition().z);
  74. int newX = currentTerrain.getLeft();
  75. int newZ = currentTerrain.getRight();
  76. waitingData.values().removeIf(f -> {
  77. if (f.isDone()) {
  78. if (MainLoop.DEBUG)
  79. System.out.println("Adding terrain");
  80. try {
  81. TerrainModelData data = f.get();
  82. terrains.put(Pair.of(data.getGridX(), data.getGridZ()),
  83. new Terrain(data.getGridX(), data.getGridZ(), loader, texturePack, blendMap, data));
  84. } catch (InterruptedException | ExecutionException e) {
  85. e.printStackTrace();
  86. }
  87. return true;
  88. } else
  89. return false;
  90. });
  91. waitingForHeight.removeIf(p -> {
  92. if (!terrains.containsKey(getGridPosByWorldPos(p.getPosition().x, p.getPosition().z)))
  93. return false;
  94. p.getPosition().setY(getTerrainHeightByWorldPos(p.getPosition().x, p.getPosition().z));
  95. return true;
  96. });
  97. if (lastX != newX || lastZ != newZ || terrains.isEmpty()) {
  98. List<Pair<Integer, Integer>> toGenerate = new ArrayList<Pair<Integer, Integer>>();
  99. for (int x = newX - 1; x <= newX + 1; x++)
  100. for (int z = newZ - 1; z <= newZ + 1; z++)
  101. toGenerate.add(Pair.of(x, z));
  102. for (Pair<Integer, Integer> pair : toGenerate) {
  103. if (waitingData.containsKey(pair) | terrains.containsKey(pair) | pair.getLeft() < 0 | pair.getRight() < 0)
  104. continue;
  105. Callable<TerrainModelData> task = new Callable<TerrainModelData>() {
  106. @Override
  107. public TerrainModelData call() throws Exception {
  108. return new TerrainModelData(pair.getLeft(), pair.getRight(), seed);
  109. }
  110. };
  111. waitingData.put(pair, executor.submit(task));
  112. }
  113. for (Pair<Integer, Integer> pair : terrains.keySet()) {
  114. if (!toGenerate.contains(pair)) {
  115. terrains.get(pair).delete();
  116. }
  117. }
  118. terrains.keySet().retainAll(toGenerate);
  119. lastX = newX;
  120. lastZ = newZ;
  121. }
  122. }
  123. public void cleanUp() {
  124. executor.shutdown();
  125. }
  126. public void addWaitingForTerrainHeight(IPositionable... positionables) {
  127. waitingForHeight.addAll(Arrays.asList(positionables));
  128. }
  129. }