ChunkFluidModel.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "ChunkFluidModel.h"
  2. #include <Trie.h>
  3. #include "Area.h"
  4. #include "Block.h"
  5. #include "Constants.h"
  6. #include "FactoryCraftModel.h"
  7. #include "Globals.h"
  8. ChunkFluidModel::ChunkFluidModel(FactoryCraftModel* target, Chunk* zChunk)
  9. : ChunkModelBuilder(target, zChunk, Chunk::CombinedModels::FLUID)
  10. {}
  11. __int64 ChunkFluidModel::calculateLight(Framework::Vec3<float> vertexPos,
  12. Framework::Vec3<int> blockPos,
  13. Direction direction)
  14. {
  15. __int64 result = 0;
  16. int sumCount = 1;
  17. short lightSum[6];
  18. Block* current = blocks()[Chunk::index(blockPos)];
  19. const unsigned char* light = current->getLightData(direction);
  20. for (int i = 0; i < 6; i++)
  21. {
  22. lightSum[i] = (short)light[i];
  23. }
  24. Vec3<int> vertexDirs(vertexPos.x < 0 ? -1 : 1,
  25. vertexPos.y < 0 ? -1 : 1,
  26. vertexPos.z < 0 ? -1 : 1);
  27. Directions dirs = getDirectionsFromVector(vertexDirs) & ~direction;
  28. Vec3<int> neighborDirs[3];
  29. int neighborIndex = 0;
  30. for (int i = 0; i < 6; i++)
  31. {
  32. Direction dir = getDirectionFromIndex(i);
  33. if ((dirs | dir) == dirs)
  34. {
  35. neighborDirs[neighborIndex++] = getDirection(dir);
  36. if (neighborIndex == 2) break;
  37. }
  38. }
  39. neighborDirs[2] = neighborDirs[0] + neighborDirs[1];
  40. for (int i = 0; i < 3; i++)
  41. {
  42. neighborDirs[i] += blockPos;
  43. if (neighborDirs[i].x >= 0 && neighborDirs[i].y >= 0
  44. && neighborDirs[i].z >= 0 && neighborDirs[i].x < CHUNK_SIZE
  45. && neighborDirs[i].y < CHUNK_SIZE
  46. && neighborDirs[i].z < WORLD_HEIGHT)
  47. {
  48. int neighborIndex = Chunk::index(neighborDirs[i]);
  49. Block* neighbor = blocks()[neighborIndex];
  50. if (neighbor)
  51. {
  52. const unsigned char* neighborLight
  53. = neighbor->getLightData(direction);
  54. if ((neighborLight[0] | neighborLight[1] | neighborLight[2]
  55. | neighborLight[3] | neighborLight[4]
  56. | neighborLight[5])
  57. != 0)
  58. {
  59. sumCount++;
  60. for (int j = 0; j < 6; j++)
  61. {
  62. lightSum[j] += (short)neighborLight[j];
  63. }
  64. }
  65. }
  66. }
  67. else
  68. { // TODO: get light from neighbor chunk
  69. }
  70. }
  71. for (int i = 0; i < 6; i++)
  72. {
  73. lightSum[i] = (lightSum[i] / sumCount) & 0xFF;
  74. }
  75. result = ((__int64)lightSum[0] << 24) | ((__int64)lightSum[1] << 16)
  76. | ((__int64)lightSum[2] << 8) | ((__int64)lightSum[3] << 56)
  77. | ((__int64)lightSum[4] << 48) | ((__int64)lightSum[5] << 40);
  78. return result;
  79. }
  80. bool ChunkFluidModel::isPartOfGroundModel(
  81. Framework::Vec3<int> location, int directionIndex)
  82. {
  83. Framework::Vec3<int> neighborLocation
  84. = location + getDirection(getDirectionFromIndex(directionIndex));
  85. bool needed = 0;
  86. if (neighborLocation.x < 0 || neighborLocation.y < 0
  87. || neighborLocation.z < 0 || neighborLocation.x >= CHUNK_SIZE
  88. || neighborLocation.y >= CHUNK_SIZE
  89. || neighborLocation.z >= WORLD_HEIGHT)
  90. {
  91. needed = 1;
  92. }
  93. else
  94. {
  95. int naighborIndex = Chunk::index(neighborLocation);
  96. int currIndex = Chunk::index(location);
  97. if (!blocks()[naighborIndex] || !isPartOfModel(blocks()[naighborIndex])
  98. || blocks()[currIndex]->zBlockType()
  99. != blocks()[naighborIndex]->zBlockType()
  100. || blocks()[naighborIndex]->getDistanceToSource()
  101. > blocks()[currIndex]->getDistanceToSource())
  102. {
  103. needed = 1;
  104. }
  105. }
  106. return needed;
  107. }
  108. void ChunkFluidModel::buildModel()
  109. {
  110. Model3DData* chunkModel = target->zModelData();
  111. // remove old model
  112. while (chunkModel->getPolygonAnzahl() > 0)
  113. {
  114. chunkModel->removePolygon(0);
  115. }
  116. // calculate verticies
  117. Trie<GroundModelPart*> groundModelBuidler;
  118. Array<GroundModelPart*> groundPartArray;
  119. Vertex3D* groundVerticies = new Vertex3D[10000];
  120. __int64* lightBuffer = new __int64[10000];
  121. int groundVertexCount = 0;
  122. int groundVertexArraySize = 10000;
  123. for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
  124. {
  125. if (blocks()[i])
  126. {
  127. if (isPartOfModel(blocks()[i]))
  128. {
  129. setBlockPartOfModel(blocks()[i], 1);
  130. int index = 0;
  131. for (Text* textureName :
  132. *blocks()[i]->zBlockType()->getModelInfo().getTexturNames())
  133. {
  134. Framework::Vec3<int> location(
  135. (i / WORLD_HEIGHT) / CHUNK_SIZE,
  136. (i / WORLD_HEIGHT) % CHUNK_SIZE,
  137. i % WORLD_HEIGHT);
  138. Framework::Vec3<int> aboveLocation
  139. = location
  140. + getDirection(Direction::TOP);
  141. int aboveIndex = Chunk::index(aboveLocation);
  142. bool sameAbove = aboveLocation.z < WORLD_HEIGHT
  143. && blocks()[aboveIndex]
  144. && blocks()[aboveIndex]->zBlockType()
  145. == blocks()[i]->zBlockType();
  146. if (isPartOfGroundModel(location, index))
  147. {
  148. if (!groundModelBuidler.get(
  149. *textureName, textureName->getLength()))
  150. {
  151. GroundModelPart* part = new GroundModelPart();
  152. part->indexList = new int[10000];
  153. part->indexCount = 0;
  154. part->indexArraySize = 10000;
  155. part->name = *textureName;
  156. groundModelBuidler.set(
  157. *textureName, textureName->getLength(), part);
  158. groundPartArray.add(part);
  159. }
  160. GroundModelPart* part = groundModelBuidler.get(
  161. *textureName, textureName->getLength());
  162. const Vertex3D* vBuffer
  163. = blocks()[i]->zModelData()->zVertexBuffer();
  164. Polygon3D* polygon
  165. = blocks()[i]->zModelData()->getPolygon(index);
  166. if (part->indexCount + polygon->indexAnz
  167. > part->indexArraySize)
  168. {
  169. int* tmp = new int[part->indexArraySize + 10000];
  170. memcpy(tmp, part->indexList, part->indexCount * 4);
  171. delete[] part->indexList;
  172. part->indexList = tmp;
  173. part->indexArraySize += 10000;
  174. }
  175. if (groundVertexCount + polygon->indexAnz
  176. > groundVertexArraySize)
  177. {
  178. Vertex3D* tmp
  179. = new Vertex3D[groundVertexArraySize + 10000];
  180. memcpy(tmp,
  181. groundVerticies,
  182. groundVertexCount * sizeof(Vertex3D));
  183. delete[] groundVerticies;
  184. groundVerticies = tmp;
  185. groundVertexArraySize += 10000;
  186. __int64* lTmp = new __int64[groundVertexArraySize];
  187. memcpy(lTmp,
  188. lightBuffer,
  189. groundVertexCount * sizeof(__int64));
  190. delete[] lightBuffer;
  191. lightBuffer = lTmp;
  192. }
  193. for (int vi = 0; vi < polygon->indexAnz; vi++)
  194. {
  195. lightBuffer[groundVertexCount] = calculateLight(
  196. vBuffer[polygon->indexList[vi]].pos,
  197. location,
  198. getDirectionFromIndex(index));
  199. part->indexList[part->indexCount++]
  200. = groundVertexCount;
  201. groundVerticies[groundVertexCount++]
  202. = vBuffer[polygon->indexList[vi]];
  203. if (groundVerticies[groundVertexCount - 1].pos.z > 0
  204. && !sameAbove)
  205. {
  206. char maxFlowDist = blocks()[i]
  207. ->zBlockType()
  208. ->getMaxFlowDistance();
  209. float dist = (float)(maxFlowDist + 1 - blocks()[i]
  210. ->getDistanceToSource()) / (float)(maxFlowDist + 1);
  211. groundVerticies[groundVertexCount - 1].pos.z
  212. -= (1 - dist);
  213. }
  214. groundVerticies[groundVertexCount - 1].pos
  215. += blocks()[i]->getPos()
  216. - Vec3<float>((float)chunkCenter().x,
  217. (float)chunkCenter().y,
  218. (float)WORLD_HEIGHT / 2.f);
  219. groundVerticies[groundVertexCount - 1].id
  220. = groundVertexCount - 1;
  221. }
  222. }
  223. index++;
  224. }
  225. }
  226. else
  227. {
  228. setBlockPartOfModel(blocks()[i], 0);
  229. }
  230. }
  231. }
  232. Model3DTextur* textur = new Model3DTextur();
  233. int pi = 0;
  234. for (GroundModelPart* part : groundPartArray)
  235. {
  236. Polygon3D* polygon = new Polygon3D();
  237. polygon->indexAnz = part->indexCount;
  238. polygon->indexList = part->indexList;
  239. target->zModelData()->addPolygon(polygon);
  240. textur->setPolygonTextur(pi,
  241. uiFactory.initParam.bildschirm->zGraphicsApi()->createOrGetTextur(
  242. part->name));
  243. pi++;
  244. delete part;
  245. }
  246. target->zModelData()->setVertecies(groundVerticies, groundVertexCount);
  247. target->setModelTextur(textur);
  248. target->setVertexLightBuffer(lightBuffer, groundVertexCount);
  249. }
  250. bool ChunkFluidModel::updateLightning()
  251. {
  252. __int64* lightBuffer = target->zLightBuffer();
  253. int oldVertexCount = target->getVertexAnzahl();
  254. int groundVertexCount = 0;
  255. for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
  256. {
  257. if (blocks()[i]
  258. && isPartOfModel(blocks()[i]))
  259. {
  260. int index = 0;
  261. for (Text* textureName :
  262. *blocks()[i]->zBlockType()->getModelInfo().getTexturNames())
  263. {
  264. Framework::Vec3<int> location(
  265. (i / WORLD_HEIGHT) / CHUNK_SIZE,
  266. (i / WORLD_HEIGHT) % CHUNK_SIZE,
  267. i % WORLD_HEIGHT);
  268. if (isPartOfGroundModel(location, index))
  269. {
  270. const Vertex3D* vBuffer
  271. = blocks()[i]->zModelData()->zVertexBuffer();
  272. Polygon3D* polygon
  273. = blocks()[i]->zModelData()->getPolygon(index);
  274. for (int vi = 0; vi < polygon->indexAnz; vi++)
  275. {
  276. if (oldVertexCount <= groundVertexCount)
  277. {
  278. std::cout << "ERROR: to many vertecies in chunk fluid model" << std::endl;
  279. return 0;
  280. }
  281. lightBuffer[groundVertexCount++] = calculateLight(
  282. vBuffer[polygon->indexList[vi]].pos,
  283. location,
  284. getDirectionFromIndex(index));
  285. }
  286. }
  287. index++;
  288. }
  289. }
  290. }
  291. target->copyLightToGPU();
  292. return 1;
  293. }
  294. bool ChunkFluidModel::isTransparent() const
  295. {
  296. return true;
  297. }
  298. bool ChunkFluidModel::isPartOfModel(Block* zBlock) const
  299. {
  300. return zBlock->zBlockType()->isFluid();
  301. }