You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

world.cpp 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * =====================================================================================
  3. *
  4. * Filename: world.cpp
  5. *
  6. * Description:
  7. *
  8. * Version: 1.0
  9. * Created: 04/03/2014 09:53:00 PM
  10. * Revision: none
  11. * Compiler: gcc
  12. *
  13. * Author: YOUR NAME (),
  14. * Organization:
  15. *
  16. * =====================================================================================
  17. */
  18. #include "world.h"
  19. #include "chunk.h"
  20. #include <cmath>
  21. #include <iostream>
  22. #include <thread>
  23. #include <GL/glew.h>
  24. #include <GL/gl.h>
  25. #define GLM_FORCE_RADIANS
  26. #include <glm/glm.hpp>
  27. #include <glm/gtc/type_ptr.hpp>
  28. #include <glm/gtc/matrix_transform.hpp>
  29. namespace vtk {
  30. World::World() {
  31. chunkSize = 16;
  32. voxelSize = 1.0f;
  33. voxelInfo.linkedWorld = this;
  34. voxelMath.linkedWorld = this;
  35. rebuildThreadActive = false;
  36. }
  37. bool World::isVoxelSolid(const int& x, const int& y, const int& z) {
  38. auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize),
  39. floor((float)y / (float)chunkSize),
  40. floor((float)z / (float)chunkSize));
  41. if (mChunks.find(chunkPos) == mChunks.end()) { //block is in nonexistant chunk
  42. return true;
  43. }
  44. int relPosX = x - chunkPos.x * chunkSize;
  45. int relPosY = y - chunkPos.y * chunkSize;
  46. int relPosZ = z - chunkPos.z * chunkSize;
  47. return mChunks[chunkPos]->isVoxelSolid(relPosX, relPosY, relPosZ);
  48. }
  49. bool World::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& updateChunk) {
  50. auto chunkPos = glm::ivec3(floor((float)x / (float)chunkSize), floor((float)y / (float)chunkSize), floor((float)z / (float)chunkSize));
  51. if (mChunks.find(chunkPos) == mChunks.end()) { //block is in nonexistant chunk
  52. return false;
  53. }
  54. int relPosX = x - chunkPos.x * chunkSize;
  55. int relPosY = y - chunkPos.y * chunkSize;
  56. int relPosZ = z - chunkPos.z * chunkSize;
  57. mChunks[chunkPos]->setVoxelType(relPosX, relPosY, relPosZ, type);
  58. if (updateChunk) queueChunkUpdate(chunkPos);
  59. return true;
  60. }
  61. unsigned World::getVoxelType(const glm::ivec3& pos) {
  62. auto chunkPos = glm::ivec3(floor((float)pos.x / (float)chunkSize),
  63. floor((float)pos.y / (float)chunkSize),
  64. floor((float)pos.z / (float)chunkSize));
  65. if (mChunks.find(chunkPos) == mChunks.end()) {
  66. return 0;
  67. }
  68. int relPosX = pos.x - chunkPos.x * chunkSize;
  69. int relPosY = pos.y - chunkPos.y * chunkSize;
  70. int relPosZ = pos.z - chunkPos.z * chunkSize;
  71. return mChunks[chunkPos]->getVoxelType((unsigned)relPosX, (unsigned)relPosY, (unsigned)relPosZ);
  72. }
  73. bool World::makeChunk(const int& x, const int& y, const int& z) {
  74. auto pos = glm::ivec3(x, y, z);
  75. if (mChunks.find(pos) != mChunks.end()) { //chunk already exists
  76. return false;
  77. }
  78. auto newChunk = new Chunk(*this);
  79. mChunks[pos] = newChunk;
  80. newChunk->setPos(pos);
  81. mChunkMeshes.emplace(pos, ChunkMesh(*this, pos));
  82. return true;
  83. }
  84. bool World::generateChunk(const int& x, const int& y, const int& z) {
  85. bool chunkMade = makeChunk(x,y,z);
  86. if (chunkMade) {
  87. terrain.generateChunk(getChunk(glm::ivec3(x,y,z)));
  88. //queue this chunk for geometry update
  89. queueChunkUpdate(x,y,z);
  90. //queue the neighboring 6 chunks. the queue functions throws them out
  91. // if they don't exist
  92. queueChunkUpdate(x+1,y,z);
  93. queueChunkUpdate(x-1,y,z);
  94. queueChunkUpdate(x,y+1,z);
  95. queueChunkUpdate(x,y-1,z);
  96. queueChunkUpdate(x,y,z+1);
  97. queueChunkUpdate(x,y,z-1);
  98. }
  99. return chunkMade;
  100. }
  101. Chunk* World::getChunk(const glm::ivec3& pos) {
  102. auto chunk = mChunks.find(pos)->second;
  103. if (chunk) return chunk;
  104. else return nullptr;
  105. }
  106. void World::queueChunkUpdate(const int& x, const int& y, const int& z) {
  107. queueChunkUpdate(glm::ivec3(x,y,z));
  108. }
  109. void World::queueChunkUpdate(const glm::ivec3& pos) {
  110. if (mChunks.find(pos) == mChunks.end()) return; //chunk doesn't exist
  111. for (auto& i : mChunkUpdateQueue) {
  112. if (i == pos) return; //chunk is already in queue, we don't need to update multiple times
  113. }
  114. mChunkUpdateQueue.push_front(pos);
  115. }
  116. void World::draw() {
  117. /*
  118. for (auto& i : chunks) {
  119. glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3(
  120. (float)i.second->getPos().x * 16,
  121. (float)i.second->getPos().y * 16,
  122. (float)i.second->getPos().z * 16
  123. ));
  124. glUniformMatrix4fv(modelMatUni, 1, GL_FALSE, glm::value_ptr(modelMat));
  125. i.second->renderer.drawChunk();
  126. }
  127. */
  128. for (auto& i : mChunkMeshes) {
  129. glm::mat4 modelMat = glm::translate(glm::mat4(), glm::vec3(
  130. (float)i.first.x * 16,
  131. (float)i.first.y * 16,
  132. (float)i.first.z * 16
  133. ));
  134. glUniformMatrix4fv(modelMatUni, 1, GL_FALSE, glm::value_ptr(modelMat));
  135. i.second.draw();
  136. }
  137. }
  138. void World::update() {
  139. if (!rebuildThreadActive && !mChunkUpdateQueue.empty( )) {
  140. auto updatefunc = [&]() {
  141. while (!mChunkUpdateQueue.empty()) {
  142. auto& pos = mChunkUpdateQueue.back();
  143. auto& mesh = mChunkMeshes.find(pos)->second;
  144. mChunkUpdateQueue.pop_back();
  145. mesh.rebuildChunkGeometry();
  146. }
  147. rebuildThreadActive = false;
  148. };
  149. rebuildThreadActive = true;
  150. std::thread(updatefunc).detach();
  151. }
  152. /*
  153. while (!chunkUpdateQueue.empty()) {
  154. auto chunk = chunks[chunkUpdateQueue.back()];
  155. chunkUpdateQueue.pop_back();
  156. std::thread(&ChunkRenderer::updateGeometry, &chunk->renderer).detach();
  157. auto& pos = chunkUpdateQueue.back();
  158. auto posVec = glm::ivec3(std::get<0>(pos), std::get<1>(pos), std::get<2>(pos));
  159. auto& mesh = mChunkMeshes.find(posVec)->second;
  160. chunkUpdateQueue.pop_back();
  161. //mesh.rebuildChunkGeometry();
  162. std::thread(&ChunkMesh::rebuildChunkGeometry, &mesh).detach();
  163. mChunkGeometryUpdateQueue.push_back(posVec);
  164. }
  165. for (auto& i : chunks) {
  166. i.second->renderer.updateVertexData();
  167. }
  168. auto it = mChunkGeometryUpdateQueue.begin();
  169. while (it != mChunkGeometryUpdateQueue.end()) {
  170. if (mChunkMeshes.find(*it)->second.updateGeometry()) {
  171. std::cout << "updated chunk " << it->x << "," << it->y << "," << it->z;
  172. mChunkGeometryUpdateQueue.erase(it);
  173. }
  174. else ++it;
  175. }
  176. */
  177. }
  178. void World::forceGlobalGeometryUpdate() {
  179. int chunkCount = 1;
  180. /*
  181. for (auto& i : chunks) {
  182. std::cout << "\rUpdating chunk geometry (" << chunkCount << "/" << chunks.size() << ")" << std::flush;
  183. i.second->renderer.updateGeometry();
  184. chunkCount++;
  185. //i.second->renderer.updateVertexData();
  186. }
  187. */
  188. chunkCount = 1;
  189. for (auto& i : mChunkMeshes) {
  190. std::cout << "\rUpdating chunk geometry, but better (" << chunkCount << "/" << mChunkMeshes.size() << ")" << std::flush;
  191. i.second.rebuildChunkGeometry();
  192. i.second.updateGeometry();
  193. ++chunkCount;
  194. }
  195. }
  196. }