World.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include <cmath>
  2. #include "client/World.h"
  3. #include "client/rendering/Engine.h"
  4. #include "client/rendering/Mesh.h"
  5. #include "common/BlockStorage.h"
  6. #include "rendering/FileTexture.h"
  7. #include "utils/List.h"
  8. #include "utils/Logger.h"
  9. #include "utils/Random.h"
  10. static BlockStorage blocks{7, 7};
  11. static List<Entity*> entities;
  12. static Mesh mesh;
  13. static FileTexture texture;
  14. static bool dirty = true;
  15. bool World::init() {
  16. mesh.init();
  17. Error error = texture.load("resources/textures.png", 4);
  18. if(error.has()) {
  19. LOG_ERROR(error.message);
  20. }
  21. return error.has();
  22. }
  23. void World::addEntity(Entity* e) {
  24. entities.add(e);
  25. }
  26. void World::removeEntity(Entity* e) {
  27. for(int i = 0; i < entities.getLength(); i++) {
  28. if(entities[i] == e) {
  29. entities.removeBySwap(i);
  30. return;
  31. }
  32. }
  33. }
  34. static List<Box> getBoxes(const Box& box) {
  35. int minX = floorf(box.getMin()[0]);
  36. int minY = floorf(box.getMin()[1]);
  37. int minZ = floorf(box.getMin()[2]);
  38. int maxX = floorf(box.getMax()[0]);
  39. int maxY = floorf(box.getMax()[1]);
  40. int maxZ = floorf(box.getMax()[2]);
  41. List<Box> boxes;
  42. for(int x = minX; x <= maxX; x++) {
  43. for(int y = minY; y <= maxY; y++) {
  44. for(int z = minZ; z <= maxZ; z++) {
  45. Block::addBoxes(blocks.get(x, y, z), boxes,
  46. Vector3(static_cast<float>(x),
  47. static_cast<float>(y),
  48. static_cast<float>(z)));
  49. }
  50. }
  51. }
  52. return boxes;
  53. }
  54. static Vector3 limitMove(const Entity& e, Vector3 move) {
  55. Box box = e.getBox();
  56. List<Box> boxes = getBoxes(box.expand(move));
  57. if(boxes.getLength() == 0) {
  58. return move;
  59. }
  60. Vector3 realMove;
  61. constexpr float step = 0.05f;
  62. while(move[0] != 0.0f || move[1] != 0.0f || move[2] != 0.0f) {
  63. for(int i = 0; i < 3; i++) {
  64. Vector3 old = realMove;
  65. if(move[i] > step) {
  66. realMove[i] += step;
  67. move[i] -= step;
  68. } else if(move[i] < -step) {
  69. realMove[i] -= step;
  70. move[i] += step;
  71. } else if(move[i] != 0.0f) {
  72. realMove[i] += move[i];
  73. move[i] = 0.0f;
  74. }
  75. Box moved = box.offset(realMove);
  76. for(const Box& box : boxes) {
  77. if(box.collidesWith(moved)) {
  78. move[i] = 0.0f;
  79. realMove = old;
  80. break;
  81. }
  82. }
  83. }
  84. }
  85. return realMove;
  86. }
  87. void World::tick() {
  88. for(Entity* e : entities) {
  89. e->tick();
  90. if(!e->skip) {
  91. Vector3 move = limitMove(*e, e->getVelocity());
  92. e->move(move);
  93. }
  94. }
  95. }
  96. static bool isAir(int x, int y, int z) {
  97. return blocks.get(x, y, z) == 0;
  98. }
  99. static void addCube(TypedBuffer<Mesh::Triangle>& buffer, float x, float y,
  100. float z) {
  101. Vector3 v000(x, y, z);
  102. Vector3 v001(x, y, z + 1);
  103. Vector3 v010(x, y + 1, z);
  104. Vector3 v011(x, y + 1, z + 1);
  105. Vector3 v100(x + 1, y, z);
  106. Vector3 v101(x + 1, y, z + 1);
  107. Vector3 v110(x + 1, y + 1, z);
  108. Vector3 v111(x + 1, y + 1, z + 1);
  109. Vector2 t1(0.1875f, 0.0f);
  110. Vector2 t2(0.25f, 0.0f);
  111. Vector2 t3(0.25f, 0.0625f);
  112. Vector2 t4(0.1875f, 0.0625f);
  113. if(isAir(x, y - 1, z)) {
  114. Vector2 tb(0.125f, 0.0625f);
  115. buffer.add({{v000, {0.125f, 0.0f}}, {v100, t1}, {v001, tb}});
  116. buffer.add({{v100, t1}, {v101, t4}, {v001, tb}});
  117. }
  118. if(isAir(x, y + 1, z)) {
  119. Vector2 tt(0.3125f, 0.0f);
  120. buffer.add({{v010, t2}, {v011, t3}, {v110, tt}});
  121. buffer.add({{v110, tt}, {v011, t3}, {v111, {0.3125f, 0.0625f}}});
  122. }
  123. if(isAir(x - 1, y, z)) {
  124. buffer.add({{v000, t4}, {v001, t3}, {v010, t1}});
  125. buffer.add({{v001, t3}, {v011, t2}, {v010, t1}});
  126. }
  127. if(isAir(x + 1, y, z)) {
  128. buffer.add({{v100, t3}, {v110, t2}, {v101, t4}});
  129. buffer.add({{v101, t4}, {v110, t2}, {v111, t1}});
  130. }
  131. if(isAir(x, y, z + 1)) {
  132. buffer.add({{v001, t4}, {v101, t3}, {v011, t1}});
  133. buffer.add({{v111, t2}, {v011, t1}, {v101, t3}});
  134. }
  135. if(isAir(x, y, z - 1)) {
  136. buffer.add({{v000, t3}, {v010, t2}, {v100, t4}});
  137. buffer.add({{v110, t1}, {v100, t4}, {v010, t2}});
  138. }
  139. }
  140. static void rebuildRenderData() {
  141. TypedBuffer<Mesh::Triangle> buffer(100);
  142. for(int x = 0; x < blocks.getSize(); x++) {
  143. for(int y = 0; y < blocks.getHeight(); y++) {
  144. for(int z = 0; z < blocks.getSize(); z++) {
  145. if(!isAir(x, y, z)) {
  146. addCube(buffer, x, y, z);
  147. }
  148. }
  149. }
  150. }
  151. mesh.build(buffer);
  152. LOG_DEBUG("world render update");
  153. }
  154. void World::render() {
  155. if(dirty) {
  156. rebuildRenderData();
  157. dirty = false;
  158. }
  159. texture.bindTo(0);
  160. for(int x = -1; x <= 1; x++) {
  161. for(int z = -1; z <= 1; z++) {
  162. Engine::matrix
  163. .translateTo(blocks.getSize() * x, 0.0f, blocks.getSize() * z)
  164. .update();
  165. mesh.draw();
  166. }
  167. }
  168. }
  169. int World::getHeight() {
  170. return blocks.getHeight();
  171. }
  172. void World::setBlock(int x, int y, int z, Block::Id block) {
  173. dirty = true;
  174. blocks.set(x, y, z, block);
  175. }