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.

chunk.cpp 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #include "chunk.h"
  2. #include "world.h"
  3. #include <iostream>
  4. namespace vtk {
  5. Chunk::Chunk(World& world) :
  6. mLinkedWorld(world),
  7. mLoaded(false),
  8. mQueuedForMeshRebuild(false)
  9. {
  10. mPos = glm::ivec3(0,0,0);
  11. //fill voxels with 0
  12. for (unsigned i = 0; i < mData.size(); ++i) {
  13. mData[i].store(0);
  14. }
  15. for (unsigned i = 0; i < mLighting.size(); ++i) {
  16. mLighting[i].store(0);
  17. }
  18. mLoaded.store(true);
  19. }
  20. bool Chunk::isLoaded() {
  21. return mLoaded.load();
  22. }
  23. unsigned Chunk::breakVoxel(const glm::ivec3& pos) {
  24. unsigned voxelType = getVoxelType(pos);
  25. if (voxelType == 0) return voxelType; //return early if nothing broken
  26. setVoxelType(pos, 0);
  27. //update heightmap
  28. mLinkedWorld.getHeightMap(glm::ivec2(mPos.x, mPos.z))
  29. ->unblockHeight(glm::ivec3(pos.x, pos.y + mPos.y * 16, pos.z));
  30. mLinkedWorld.queueChunkUpdate(mPos);
  31. //update the neightboring chunks if voxel lies along border
  32. glm::ivec3 neighborPos(0,0,0);
  33. if (pos.x == 0) neighborPos.x--;
  34. else if (pos.x == 15) neighborPos.x++;
  35. if (pos.y == 0) neighborPos.y--;
  36. else if (pos.y == 15) neighborPos.y++;
  37. if (pos.z == 0) neighborPos.z--;
  38. else if (pos.z == 15) neighborPos.z++;
  39. if (neighborPos.x != 0)
  40. mLinkedWorld.queueChunkUpdate(glm::ivec3(mPos.x + neighborPos.x,
  41. mPos.y,
  42. mPos.z));
  43. if (neighborPos.y != 0)
  44. mLinkedWorld.queueChunkUpdate(glm::ivec3(mPos.x,
  45. mPos.y + neighborPos.y,
  46. mPos.z));
  47. if (neighborPos.z != 0)
  48. mLinkedWorld.queueChunkUpdate(glm::ivec3(mPos.x,
  49. mPos.y,
  50. mPos.z + neighborPos.z));
  51. return voxelType;
  52. }
  53. bool Chunk::placeVoxel(const glm::ivec3& pos, const unsigned& type) {
  54. unsigned curType = getVoxelType(pos);
  55. if (curType != 0) // return false if the voxel is NOT air
  56. return false;
  57. setVoxelType(pos, type);
  58. //update heightmap
  59. mLinkedWorld.getHeightMap(glm::ivec2(mPos.x, mPos.z))
  60. ->blockHeight(glm::ivec3(pos.x, pos.y + mPos.y * 16, pos.z));
  61. mLinkedWorld.queueChunkUpdate(mPos);
  62. //update the neightboring chunks if voxel lies along border
  63. glm::ivec3 neighborPos(0,0,0);
  64. if (pos.x == 0) neighborPos.x--;
  65. else if (pos.x == 15) neighborPos.x++;
  66. if (pos.y == 0) neighborPos.y--;
  67. else if (pos.y == 15) neighborPos.y++;
  68. if (pos.z == 0) neighborPos.z--;
  69. else if (pos.z == 15) neighborPos.z++;
  70. if (neighborPos.x != 0)
  71. mLinkedWorld.queueChunkUpdate(glm::ivec3(mPos.x + neighborPos.x,
  72. mPos.y,
  73. mPos.z));
  74. if (neighborPos.y != 0)
  75. mLinkedWorld.queueChunkUpdate(glm::ivec3(mPos.x,
  76. mPos.y + neighborPos.y,
  77. mPos.z));
  78. if (neighborPos.z != 0)
  79. mLinkedWorld.queueChunkUpdate(glm::ivec3(mPos.x,
  80. mPos.y,
  81. mPos.z + neighborPos.z));
  82. return true;
  83. }
  84. bool Chunk::isVoxelSolid(const int& x, const int& y, const int& z) {
  85. if (x < 0 || x > 15 ||
  86. y < 0 || y > 15 ||
  87. z < 0 || z > 15 )
  88. { //position is outside of the chunk
  89. return mLinkedWorld.isVoxelSolid(mPos.x * 16 + x,
  90. mPos.y * 16 + y,
  91. mPos.z * 16 + z);
  92. }
  93. return !mLinkedWorld.voxelInfo.isTransparent(getVoxelType((unsigned)x, (unsigned)y, (unsigned)z));
  94. }
  95. void Chunk::setVoxelType(const glm::ivec3 &pos, const unsigned& type) {
  96. setVoxelType(pos.x, pos.y, pos.z, type);
  97. }
  98. void Chunk::setVoxelType(const int& x, const int& y, const int& z, const unsigned& type, const bool& update) {
  99. auto index = x + 16 * (y + 16 * z);
  100. if (index > 4095) {
  101. std::cout << "CHUNK ACCESS ERROR (set voxel): Out of range, doing nothing\n";
  102. return;
  103. }
  104. mData[index].store(type, std::memory_order_release);
  105. if (!update) return;
  106. mLinkedWorld.queueChunkUpdate(mPos);
  107. }
  108. unsigned Chunk::getVoxelType(const glm::ivec3& pos) {
  109. auto index = pos.x + 16 * (pos.y + 16 * pos.z);
  110. if (index > 4095) {
  111. std::cout << "CHUNK ACCESS ERROR (get voxel): Out of range, returning type 0\n";
  112. return 0;
  113. }
  114. return mData[index].load(std::memory_order_consume);
  115. }
  116. unsigned Chunk::getVoxelType(const unsigned& x, const unsigned& y, const unsigned& z) {
  117. return getVoxelType(glm::ivec3(x,y,z));
  118. }
  119. glm::ivec3 Chunk::getWorldCoords(const int& x, const int& y, const int& z) {
  120. return glm::ivec3(mPos.x * 16 + x,
  121. mPos.y * 16 + y,
  122. mPos.z * 16 + z);
  123. }
  124. unsigned Chunk::getLightLevel(const glm::ivec3 &pos) {
  125. if (isVoxelSolid(pos.x, pos.y, pos.z)) {
  126. return 0;
  127. }
  128. return 15;
  129. }
  130. unsigned short Chunk::getLightPacked(const glm::ivec3 &pos) {
  131. if (isVoxelSolid(pos.x, pos.y, pos.z)) {
  132. return 0x0000;
  133. }
  134. auto wPos = chunkPosToWorldPos(mPos, pos);
  135. if (mLinkedWorld.getHeight(glm::ivec2(wPos.x, wPos.z)) > wPos.y) { //voxel is below ground
  136. //std::cout << mLinkedWorld.getHeight(glm::ivec2(pos.x, pos.z)) << ", ";
  137. return 0x000A;
  138. }
  139. return 0x000F;
  140. }
  141. HeightMap* Chunk::getHeightMap() {
  142. return mLinkedWorld.getHeightMap(glm::ivec2(mPos.x,mPos.z));
  143. }
  144. void Chunk::setPos(const glm::ivec3& pos) {
  145. mPos = pos;
  146. }
  147. glm::ivec3 Chunk::getPos() {
  148. return mPos;
  149. }
  150. World& Chunk::getWorld() {
  151. return mLinkedWorld;
  152. }
  153. void Chunk::setQueuedForMeshRebuild(const bool& rebuild) {
  154. mQueuedForMeshRebuild = rebuild;
  155. }
  156. bool Chunk::isQueuedForMeshRebuild() {
  157. return mQueuedForMeshRebuild.load();
  158. }
  159. }