WorldTerrain.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. #include "WorldTerrain.h"
  2. #include <time.h>
  3. #include <cstdlib>
  4. #include "Crown.h"
  5. #include "perlin.h"
  6. #include <iostream>
  7. using namespace Crown;
  8. int perlinSeed;
  9. extern MovableCamera* cam;
  10. void DrawWiredCube(float x, float y, float z, float size);
  11. WorldTerrain::WorldTerrain()
  12. {
  13. Clear();
  14. mChunkX = 0;
  15. mChunkZ = 0;
  16. mChunkH = 0;
  17. mDrawGrid = true;
  18. mPlayerChunkX = (CHUNKS_COUNT+1)/2.0f;
  19. mPlayerChunkZ = (CHUNKS_COUNT+1)/2.0f;
  20. mPlayerChunkH = CHUNKS_COUNT_H;
  21. mPlayerPosition = Vec3((mPlayerChunkX + 0.5) * CHUNK_SIZE, mPlayerChunkH * CHUNK_SIZE, (mPlayerChunkZ + 0.5) * CHUNK_SIZE);
  22. for(int x = 0; x < CHUNKS_COUNT; x++)
  23. {
  24. for(int z = 0; z < CHUNKS_COUNT; z++)
  25. {
  26. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  27. {
  28. mChunks[x][z][h] = new Chunk(this);
  29. }
  30. }
  31. }
  32. BMPImageLoader bmp;
  33. Image* image = bmp.LoadFile("res/terrain.bmp");
  34. mTerrainTexture = new GLTexture();
  35. //mTerrainTexture->SetWrap(TW_CLAMP_TO_EDGE);
  36. mTerrainTexture->SetGenerateMipMaps(true);
  37. mTerrainTexture->SetFilter(TF_ANISOTROPIC);
  38. mTerrainTexture->CreateFromImage(image);
  39. delete image;
  40. GLfloat fogColor[4] = {0.457f, 0.754f, 1.0f, 1.0f};//{0.5, 0.5, 0.5, 1.0};
  41. glEnable (GL_FOG);
  42. glFogi (GL_FOG_MODE, GL_LINEAR);
  43. glFogf(GL_FOG_START, 0.0f);
  44. glFogf(GL_FOG_END, 10.0f);
  45. glFogfv (GL_FOG_COLOR, fogColor);
  46. glHint (GL_FOG_HINT, GL_NICEST);
  47. glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
  48. mViewDistance = 128;
  49. CycleViewDistance();
  50. }
  51. WorldTerrain::~WorldTerrain()
  52. {
  53. for(int x = 0; x < CHUNKS_COUNT; x++)
  54. {
  55. for(int z = 0; z < CHUNKS_COUNT; z++)
  56. {
  57. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  58. {
  59. delete mChunks[x][z][h];
  60. }
  61. }
  62. }
  63. delete mTerrainTexture;
  64. }
  65. void WorldTerrain::Clear()
  66. {
  67. for(int x = 0; x < WORLD_SIZE; x++)
  68. {
  69. for(int z = 0; z < WORLD_SIZE; z++)
  70. {
  71. for(int h = 0; h < WORLD_SIZE_H; h++)
  72. {
  73. mBlocks[x][z][h].opaque = false;
  74. mBlocks[x][z][h].faceVisibility = FV_NONE;
  75. mBlocks[x][z][h].light = 4;
  76. }
  77. }
  78. }
  79. }
  80. void WorldTerrain::RandomMap(int groundLevel, int seed, int octaves, int freq)
  81. {
  82. Clear();
  83. Perlin per(octaves, freq, WORLD_SIZE_H/2, seed);
  84. for(int x = 0; x < WORLD_SIZE; x++)
  85. {
  86. for(int z = 0; z < WORLD_SIZE; z++)
  87. {
  88. int height = per.Get(x * 1.0f / WORLD_SIZE, z * 1.0f / WORLD_SIZE) - groundLevel;
  89. if (height < 0)
  90. height /= 6;
  91. height = (WORLD_SIZE_H / 2) + height;
  92. for(int h = 0; h < height; h++)
  93. mBlocks[x][z][h].opaque = true;
  94. }
  95. }
  96. int px = (int) (cam->GetPosition().x / CubeSize);
  97. int pz = (int) (cam->GetPosition().z / CubeSize);
  98. int ph = WORLD_SIZE_H-1;
  99. while(ph > 1 && !mBlocks[px][pz][ph-1].opaque)
  100. ph--;
  101. ph++;
  102. mPlayerChunkX = px / CHUNK_SIZE;
  103. mPlayerChunkZ = pz / CHUNK_SIZE;
  104. mPlayerChunkH = ph / CHUNK_SIZE;
  105. cam->SetPosition(Vec3(px*CubeSize, ph*CubeSize, pz*CubeSize));
  106. RecalculateVisibleBlocksSides();
  107. RecalculateSunlight();
  108. RegenerateTerrain();
  109. }
  110. void WorldTerrain::UpdateVisibleNeighbourBlocks(Crown::uint xC, Crown::uint zC, Crown::uint hC)
  111. {
  112. for(int x = xC-1; x < (int)xC+2; x++)
  113. {
  114. if (x < 0 || x >= WORLD_SIZE)
  115. continue;
  116. for(int z = zC-1; z < (int)zC+2; z++)
  117. {
  118. if (z < 0 || z >= WORLD_SIZE)
  119. continue;
  120. for(int h = hC-1; h < (int)hC+2; h++)
  121. {
  122. if (h<0 || h>=WORLD_SIZE_H)
  123. continue;
  124. Block& b = mBlocks[x][z][h];
  125. b.faceVisibility = FV_NONE;
  126. if (b.opaque)
  127. {
  128. if (x == 0 || !mBlocks[x-1][z][h].opaque)
  129. b.faceVisibility |= FV_LEFT;
  130. if (z == 0 || !mBlocks[x][z-1][h].opaque)
  131. b.faceVisibility |= FV_BACK;
  132. if (h == 0 || !mBlocks[x][z][h-1].opaque)
  133. b.faceVisibility |= FV_BOTTOM;
  134. if (x == WORLD_SIZE-1 || !mBlocks[x+1][z][h].opaque)
  135. b.faceVisibility |= FV_RIGHT;
  136. if (z == WORLD_SIZE-1 || !mBlocks[x][z+1][h].opaque)
  137. b.faceVisibility |= FV_FRONT;
  138. if (h == WORLD_SIZE_H-1 || !mBlocks[x][z][h+1].opaque)
  139. b.faceVisibility |= FV_TOP;
  140. }
  141. Crown::uint cx = x / CHUNK_SIZE;
  142. Crown::uint cz = z / CHUNK_SIZE;
  143. Crown::uint ch = h / CHUNK_SIZE;
  144. if (cx < 0 || cz < 0 || ch < 0 || cx >= CHUNKS_COUNT || cz >= CHUNKS_COUNT || ch >= CHUNKS_COUNT_H)
  145. continue;
  146. if (b.faceVisibility == FV_NONE)
  147. mChunks[cx][cz][ch]->BlockRemoved(x, z, h);
  148. else
  149. mChunks[cx][cz][ch]->BlockRevealed(x, z, h);
  150. }
  151. }
  152. }
  153. }
  154. void WorldTerrain::RecalculateVisibleBlocksSides()
  155. {
  156. for(int x = 0; x < WORLD_SIZE; x++)
  157. {
  158. for(int z = 0; z < WORLD_SIZE; z++)
  159. {
  160. for(int h = 0; h < WORLD_SIZE_H; h++)
  161. {
  162. Block& b = mBlocks[x][z][h];
  163. Crown::uint fv = FV_NONE;
  164. if (b.opaque)
  165. {
  166. if (x == 0 || !mBlocks[x-1][z][h].opaque)
  167. fv |= FV_LEFT;
  168. if (x == WORLD_SIZE-1 || !mBlocks[x+1][z][h].opaque)
  169. fv |= FV_RIGHT;
  170. if (z == 0 || !mBlocks[x][z-1][h].opaque)
  171. fv |= FV_BACK;
  172. if (z == WORLD_SIZE-1 || !mBlocks[x][z+1][h].opaque)
  173. fv |= FV_FRONT;
  174. if (h == 0 || !mBlocks[x][z][h-1].opaque)
  175. fv |= FV_BOTTOM;
  176. if (h == WORLD_SIZE_H-1 || !mBlocks[x][z][h+1].opaque)
  177. fv |= FV_TOP;
  178. }
  179. b.faceVisibility = fv;
  180. }
  181. }
  182. }
  183. }
  184. void WorldTerrain::RecalculateSunlight()
  185. {
  186. for(int x = 0; x < WORLD_SIZE; x++)
  187. {
  188. for(int z = 0; z < WORLD_SIZE; z++)
  189. {
  190. mBlocks[x][z][WORLD_SIZE_H-1].light = 15;
  191. }
  192. }
  193. for(int x = 0; x < WORLD_SIZE; x++)
  194. {
  195. for(int z = 0; z < WORLD_SIZE; z++)
  196. {
  197. for(int h = WORLD_SIZE_H-2; h > 0 && !mBlocks[x][z][h].opaque; h--)
  198. {
  199. mBlocks[x][z][h].light = 15;
  200. }
  201. }
  202. }
  203. }
  204. void WorldTerrain::RegenerateTerrain()
  205. {
  206. for(int x = 0; x < CHUNKS_COUNT; x++)
  207. {
  208. for(int z = 0; z < CHUNKS_COUNT; z++)
  209. {
  210. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  211. {
  212. mChunks[x][z][h]->AssignLocation(x*CHUNK_SIZE , z*CHUNK_SIZE, h*CHUNK_SIZE);
  213. }
  214. }
  215. }
  216. }
  217. void WorldTerrain::Render()
  218. {
  219. glEnable(GL_TEXTURE_2D);
  220. Renderer* r = GetDevice()->GetRenderer();
  221. r->SetTexture(1, mTerrainTexture);
  222. //mTerrainTexture->MakeCurrent();
  223. glEnableClientState(GL_VERTEX_ARRAY);
  224. glEnableClientState(GL_NORMAL_ARRAY);
  225. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  226. glEnableClientState(GL_COLOR_ARRAY);
  227. mChunkRegenerationSlots = 30;
  228. for(int x = 0; x < CHUNKS_COUNT; x++)
  229. {
  230. for(int z = 0; z < CHUNKS_COUNT; z++)
  231. {
  232. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  233. {
  234. mChunks[x][z][h]->Render();
  235. }
  236. }
  237. }
  238. glDisableClientState(GL_VERTEX_ARRAY);
  239. glDisableClientState(GL_NORMAL_ARRAY);
  240. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  241. glDisableClientState(GL_COLOR_ARRAY);
  242. glDisable(GL_TEXTURE_2D);
  243. }
  244. void WorldTerrain::SetPlayerPosition(Vec3 newPosition)
  245. {
  246. newPosition /= CubeSize;
  247. Crown::uint chunkX = (Crown::uint) (newPosition.x / (CHUNK_SIZE)) - mChunkX;
  248. Crown::uint chunkZ = (Crown::uint) (newPosition.z / (CHUNK_SIZE)) - mChunkZ;
  249. Crown::uint chunkH = (Crown::uint) (newPosition.y / (CHUNK_SIZE)) - mChunkH;
  250. mPlayerPosition = newPosition;
  251. if (chunkX > (CHUNKS_COUNT+1)/2 && (mChunkX + CHUNKS_COUNT) * CHUNK_SIZE < WORLD_SIZE)
  252. {
  253. //Fai uno spostamento verso x+
  254. Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
  255. mChunkX += 1;
  256. ExtractChunksFromX(tempChunks, 0);
  257. //Slide all chunks behind in the -x direction
  258. for(int x = 0; x < CHUNKS_COUNT-1; x++)
  259. {
  260. for(int z = 0; z < CHUNKS_COUNT; z++)
  261. {
  262. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  263. {
  264. Chunk* c = mChunks[x+1][z][h];
  265. mChunks[x][z][h] = c;
  266. c->mRelX--;
  267. c->UpdateShouldRender();
  268. }
  269. }
  270. }
  271. ReplaceChunksInX(tempChunks, CHUNKS_COUNT-1);
  272. }
  273. else if (chunkX < (CHUNKS_COUNT+1)/2 && mChunkX > 0)
  274. {
  275. //Fai uno spostamento verso x-
  276. Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
  277. mChunkX -= 1;
  278. ExtractChunksFromX(tempChunks, CHUNKS_COUNT-1);
  279. for(int x = CHUNKS_COUNT-1; x > 0; x--)
  280. {
  281. for(int z = 0; z < CHUNKS_COUNT; z++)
  282. {
  283. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  284. {
  285. Chunk* c = mChunks[x-1][z][h];
  286. mChunks[x][z][h] = c;
  287. c->mRelX++;
  288. c->UpdateShouldRender();
  289. }
  290. }
  291. }
  292. ReplaceChunksInX(tempChunks, 0);
  293. }
  294. else if (chunkZ > (CHUNKS_COUNT+1)/2 && (mChunkZ + CHUNKS_COUNT) * CHUNK_SIZE < WORLD_SIZE)
  295. {
  296. //Fai uno spostamento verso z+
  297. Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
  298. mChunkZ += 1;
  299. ExtractChunksFromZ(tempChunks, 0);
  300. for(int z = 0; z < CHUNKS_COUNT-1; z++)
  301. {
  302. for(int x = 0; x < CHUNKS_COUNT; x++)
  303. {
  304. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  305. {
  306. Chunk* c = mChunks[x][z+1][h];
  307. mChunks[x][z][h] = c;
  308. c->mRelZ--;
  309. c->UpdateShouldRender();
  310. }
  311. }
  312. }
  313. ReplaceChunksInZ(tempChunks, CHUNKS_COUNT-1);
  314. }
  315. else if (chunkZ < (CHUNKS_COUNT+1)/2 && mChunkZ > 0)
  316. {
  317. //Fai uno spostamento verso z-
  318. Chunk* tempChunks[CHUNKS_COUNT][CHUNKS_COUNT_H];
  319. mChunkZ -= 1;
  320. ExtractChunksFromZ(tempChunks, CHUNKS_COUNT-1);
  321. for(int z = CHUNKS_COUNT-1; z > 0; z--)
  322. {
  323. for(int x = 0; x < CHUNKS_COUNT; x++)
  324. {
  325. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  326. {
  327. Chunk* c = mChunks[x][z-1][h];
  328. mChunks[x][z][h] = c;
  329. c->mRelZ++;
  330. c->UpdateShouldRender();
  331. }
  332. }
  333. }
  334. ReplaceChunksInZ(tempChunks, 0);
  335. }
  336. else if (chunkX != mPlayerChunkX || chunkZ != mPlayerChunkZ || chunkH != mPlayerChunkH)
  337. {
  338. if (chunkX >= CHUNKS_COUNT || chunkZ >= CHUNKS_COUNT || chunkH >= CHUNKS_COUNT_H)
  339. return;
  340. Crown::uint xOff = chunkX - mPlayerChunkX;
  341. Crown::uint zOff = chunkZ - mPlayerChunkZ;
  342. Crown::uint hOff = chunkH - mPlayerChunkH;
  343. mPlayerChunkX = chunkX;
  344. mPlayerChunkZ = chunkZ;
  345. mPlayerChunkH = chunkH;
  346. //Just update the ShouldDraw of chunks
  347. for(int x = 0; x < CHUNKS_COUNT; x++)
  348. {
  349. for(int z = 0; z < CHUNKS_COUNT; z++)
  350. {
  351. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  352. {
  353. mChunks[x][z][h]->UpdateShouldRender();
  354. mChunks[x][z][h]->mRelX -= xOff;
  355. mChunks[x][z][h]->mRelZ -= zOff;
  356. mChunks[x][z][h]->mRelH -= hOff;
  357. }
  358. }
  359. }
  360. }
  361. }
  362. void WorldTerrain::LOL()
  363. {
  364. Crown::uint x = rand() % CHUNK_SIZE;
  365. Crown::uint z = rand() % CHUNK_SIZE;
  366. Crown::uint h = 0;
  367. while (h < WORLD_SIZE_H-1 && mBlocks[x][z][h+1].opaque)
  368. h++;
  369. mBlocks[x][z][h].opaque = false;
  370. UpdateVisibleNeighbourBlocks(x, z, h);
  371. }
  372. void WorldTerrain::CycleViewDistance()
  373. {
  374. if (mViewDistance == 256)
  375. mViewDistance = 32;
  376. else
  377. mViewDistance <<= 1;
  378. std::cout << "View distance changed: " << mViewDistance << std::endl;
  379. cam->SetFarClipDistance(mViewDistance);
  380. glFogf(GL_FOG_START, mViewDistance*CubeSize*0.35);
  381. glFogf(GL_FOG_END, mViewDistance*CubeSize);
  382. }
  383. void WorldTerrain::ExtractChunksFromX(Chunk* destChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint x)
  384. {
  385. for(int z = 0; z < CHUNKS_COUNT; z++)
  386. {
  387. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  388. {
  389. destChunks[z][h] = mChunks[x][z][h];
  390. }
  391. }
  392. }
  393. void WorldTerrain::ReplaceChunksInX(Chunk* srcChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint x)
  394. {
  395. for(int z = 0; z < CHUNKS_COUNT; z++)
  396. {
  397. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  398. {
  399. Chunk* c;
  400. c = srcChunks[z][h];
  401. mChunks[x][z][h] = c;
  402. c->AssignLocation((mChunkX + x) * CHUNK_SIZE, c->mZ, c->mH);
  403. }
  404. }
  405. }
  406. void WorldTerrain::ExtractChunksFromZ(Chunk* destChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint z)
  407. {
  408. for(int x = 0; x < CHUNKS_COUNT; x++)
  409. {
  410. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  411. {
  412. destChunks[x][h] = mChunks[x][z][h];
  413. }
  414. }
  415. }
  416. void WorldTerrain::ReplaceChunksInZ(Chunk* srcChunks[CHUNKS_COUNT][CHUNKS_COUNT_H], Crown::uint z)
  417. {
  418. for(int x = 0; x < CHUNKS_COUNT; x++)
  419. {
  420. for(int h = 0; h < CHUNKS_COUNT_H; h++)
  421. {
  422. Chunk* c;
  423. c = srcChunks[x][h];
  424. mChunks[x][z][h] = c;
  425. c->AssignLocation(c->mX, (mChunkZ + z) * CHUNK_SIZE, c->mH);
  426. }
  427. }
  428. }
  429. //------------CHUNK-------------
  430. Chunk::Chunk(WorldTerrain* terrain):
  431. mWorldTerrain(terrain), mX(0), mZ(0), mH(0), mRelX(0), mRelZ(0), mRelH(0), mIsDirty(false), mShouldRender(false),
  432. mCandidateBlocks(0),
  433. mVertexBuffer(NULL), mIndexBuffer(NULL),
  434. mVertex(NULL), mVertexCount(0)
  435. {
  436. for(int i = 0; i < 6; i++)
  437. {
  438. mIndices[i] = NULL;
  439. mIndicesCount[i] = 0;
  440. }
  441. mVertexBuffer = GetDevice()->GetRenderer()->CreateVertexBuffer();
  442. mIndexBuffer = GetDevice()->GetRenderer()->CreateIndexBuffer();
  443. }
  444. Chunk::~Chunk()
  445. {
  446. delete[] mVertex;
  447. for(int i = 0; i < 6; i++)
  448. if (mIndices[i] != NULL)
  449. {
  450. delete[] mIndices[i];
  451. mIndices[i] = NULL;
  452. }
  453. }
  454. void Chunk::Render()
  455. {
  456. Box box;
  457. box.min = Vec3(mX*CubeSize, mH*CubeSize, mZ*CubeSize);
  458. box.max = Vec3((mX+CHUNK_SIZE)*CubeSize, (mH+CHUNK_SIZE)*CubeSize, (mZ+CHUNK_SIZE)*CubeSize);
  459. //Vec3 minToMax = box.max - box.min;
  460. //Compensate imprecise frustum culling
  461. //box.min -= minToMax/(18*1.6);
  462. //box.max += minToMax/(18*1.6);
  463. if (mShouldRender)// && cam->GetFrustum().IntersectsBox(box))
  464. {
  465. if (mWorldTerrain->mDrawGrid)
  466. {
  467. glColor3f(0.6f, 0.6f, 1.0f);
  468. DrawWiredCube(mX*CubeSize, mH*CubeSize, mZ*CubeSize, 16*CubeSize);
  469. glColor3f(1.0f, 1.0f, 1.0f);
  470. }
  471. if (mCandidateBlocks > 0)
  472. {
  473. if (mIsDirty && mWorldTerrain->mChunkRegenerationSlots > 0)
  474. {
  475. mWorldTerrain->mChunkRegenerationSlots--;
  476. mIsDirty = false;
  477. mWorldTerrain->RegeneratedChunks++;
  478. RegenerateChunk();
  479. }
  480. if (mVertexBuffer == NULL || mIndexBuffer == NULL)
  481. return;
  482. mVertexBuffer->MakeCurrent();
  483. mIndexBuffer->MakeCurrent();
  484. if (mRelX >= 0)
  485. glDrawElements(GL_TRIANGLES, mIndicesCount[FB_LEFT], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_LEFT]*sizeof(Crown::uint)));
  486. if (mRelX <= 0)
  487. glDrawElements(GL_TRIANGLES, mIndicesCount[FB_RIGHT], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_RIGHT]*sizeof(Crown::uint)));
  488. if (mRelZ >= 0)
  489. glDrawElements(GL_TRIANGLES, mIndicesCount[FB_BACK], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_BACK]*sizeof(Crown::uint)));
  490. if (mRelZ <= 0)
  491. glDrawElements(GL_TRIANGLES, mIndicesCount[FB_FRONT], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_FRONT]*sizeof(Crown::uint)));
  492. if (mRelH >= 0)
  493. glDrawElements(GL_TRIANGLES, mIndicesCount[FB_BOTTOM], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_BOTTOM]*sizeof(Crown::uint)));
  494. if (mRelH <= 0)
  495. glDrawElements(GL_TRIANGLES, mIndicesCount[FB_TOP], GL_UNSIGNED_INT, (void*) (mIndicesOffsets[FB_TOP]*sizeof(Crown::uint)));
  496. }
  497. }
  498. if (mVertex)
  499. {
  500. delete[] mVertex;
  501. mVertex = NULL;
  502. for(int i = 0; i < 6; i++)
  503. {
  504. if (mIndices[i] != NULL)
  505. {
  506. delete[] mIndices[i];
  507. mIndices[i] = NULL;
  508. }
  509. }
  510. }
  511. }
  512. void Chunk::UpdateShouldRender()
  513. {
  514. float d = (float) (pow(mRelX*CHUNK_SIZE + CHUNK_SIZE / (mRelX < 0 ? -2.0 : 2.0), 2) +
  515. pow(mRelZ*CHUNK_SIZE + CHUNK_SIZE / (mRelZ < 0 ? -2.0 : 2.0), 2));
  516. if (d > pow((float)mWorldTerrain->mViewDistance + 2*CHUNK_SIZE, 2))
  517. mShouldRender = false;
  518. else
  519. mShouldRender = true;
  520. }
  521. void Chunk::Dirty()
  522. {
  523. mIsDirty = true;
  524. }
  525. void Chunk::AssignLocation(Crown::uint x, Crown::uint z, Crown::uint h)
  526. {
  527. mX = x;
  528. mZ = z;
  529. mH = h;
  530. int xTo = mX + CHUNK_SIZE;
  531. int zTo = mZ + CHUNK_SIZE;
  532. int hTo = mH + CHUNK_SIZE;
  533. mCandidateBlocks = 0;
  534. mBlocksToRender.Clear();
  535. for(int x = mX; x < xTo; x++)
  536. {
  537. for(int z = mZ; z < zTo; z++)
  538. {
  539. for(int h = mH; h < hTo; h++)
  540. {
  541. Block& b = mWorldTerrain->mBlocks[x][z][h];
  542. if (!b.opaque || b.faceVisibility == 0)
  543. continue;
  544. BlockToRender bt = {&b, x, z, h};
  545. mBlocksToRender.Append(bt);
  546. mCandidateBlocks++;
  547. }
  548. }
  549. }
  550. mRelX = mX / CHUNK_SIZE - (mWorldTerrain->mChunkX + mWorldTerrain->mPlayerChunkX);
  551. mRelZ = mZ / CHUNK_SIZE - (mWorldTerrain->mChunkZ + mWorldTerrain->mPlayerChunkZ);
  552. mRelH = mH / CHUNK_SIZE - (mWorldTerrain->mChunkH + mWorldTerrain->mPlayerChunkH);
  553. mIsDirty = true;
  554. UpdateShouldRender();
  555. }
  556. void Chunk::BlockRemoved(Crown::uint x, Crown::uint z, Crown::uint h)
  557. {
  558. Block* block = &mWorldTerrain->mBlocks[x][z][h];
  559. for(int i = 0; i<mBlocksToRender.GetSize(); i++)
  560. {
  561. if (mBlocksToRender[i].block == block)
  562. {
  563. mBlocksToRender[i] = mBlocksToRender[mBlocksToRender.GetSize()-1];
  564. mBlocksToRender.Remove(mBlocksToRender.GetSize()-1);
  565. mCandidateBlocks--;
  566. mIsDirty = true;
  567. return;
  568. }
  569. }
  570. }
  571. void Chunk::BlockRevealed(Crown::uint x, Crown::uint z, Crown::uint h)
  572. {
  573. mIsDirty = true;
  574. Block* block = &mWorldTerrain->mBlocks[x][z][h];
  575. for(int i = 0; i<mBlocksToRender.GetSize(); i++)
  576. {
  577. if (mBlocksToRender[i].block == block)
  578. {
  579. return;
  580. }
  581. }
  582. BlockToRender bt = {block, x, z, h};
  583. mBlocksToRender.Append(bt);
  584. mCandidateBlocks++;
  585. }
  586. void Chunk::RegenerateChunk()
  587. {
  588. mVertexCount = 0;
  589. for(int i = 0; i < 6; i++)
  590. mIndicesCount[i] = 0;
  591. if (mCandidateBlocks == 0)
  592. {
  593. mCandidateBlocks = 0;
  594. mVertexBuffer->SetVertexData((VertexBufferMode) (VBM_NORMAL_COORDS | VBM_TEXTURE_COORDS | VBM_COLOR_COORDS), NULL, 0);
  595. mIndexBuffer->SetIndexData(NULL, 0);
  596. return;
  597. }
  598. if (mVertex != NULL)
  599. delete[] mVertex;
  600. for(int i = 0; i < 6; i++)
  601. if (mIndices[i] != NULL)
  602. delete[] mIndices[i];
  603. mVertex = new VertexData[mCandidateBlocks * 24];
  604. for(int i = 0; i < 6; i++)
  605. mIndices[i] = new Crown::uint[mCandidateBlocks * 36];
  606. for(int i = 0; i<mBlocksToRender.GetSize(); i++)
  607. {
  608. BlockToRender& bt = mBlocksToRender[i];
  609. Block* b = bt.block;
  610. uchar light;
  611. if (b->faceVisibility & FV_TOP)
  612. {
  613. if (bt.h < WORLD_SIZE_H-1)
  614. light = mWorldTerrain->mBlocks[bt.x][bt.z][bt.h+1].light;
  615. AddFace(bt.x, bt.z, bt.h, FB_TOP, light);
  616. }
  617. if (b->faceVisibility & FV_BOTTOM)
  618. {
  619. if (bt.h > 0)
  620. light = mWorldTerrain->mBlocks[bt.x][bt.z][bt.h-1].light;
  621. AddFace(bt.x, bt.z, bt.h, FB_BOTTOM, light);
  622. }
  623. if (b->faceVisibility & FV_LEFT)
  624. {
  625. if (bt.x > 0)
  626. light = mWorldTerrain->mBlocks[bt.x-1][bt.z][bt.h].light;
  627. AddFace(bt.x, bt.z, bt.h, FB_LEFT, light);
  628. }
  629. if (b->faceVisibility & FV_RIGHT)
  630. {
  631. if (bt.x < WORLD_SIZE_H-1)
  632. light = mWorldTerrain->mBlocks[bt.x+1][bt.z][bt.h].light;
  633. AddFace(bt.x, bt.z, bt.h, FB_RIGHT, light);
  634. }
  635. if (b->faceVisibility & FV_FRONT)
  636. {
  637. if (bt.z < WORLD_SIZE_H-1)
  638. light = mWorldTerrain->mBlocks[bt.x][bt.z+1][bt.h].light;
  639. AddFace(bt.x, bt.z, bt.h, FB_FRONT, light);
  640. }
  641. if (b->faceVisibility & FV_BACK)
  642. {
  643. if (bt.z > 0)
  644. light = mWorldTerrain->mBlocks[bt.x][bt.z-1][bt.h].light;
  645. AddFace(bt.x, bt.z, bt.h, FB_BACK, light);
  646. }
  647. }
  648. mVertexBuffer->SetVertexData((VertexBufferMode) (VBM_NORMAL_COORDS | VBM_TEXTURE_COORDS | VBM_COLOR_COORDS), (float*)mVertex, mVertexCount);
  649. int totIndicesCount = 0;
  650. for(int i = 0; i < 6; i++)
  651. totIndicesCount += mIndicesCount[i];
  652. mIndexBuffer->SetIndexData(NULL, totIndicesCount);
  653. totIndicesCount = 0;
  654. for(int i = 0; i < 6; i++)
  655. {
  656. mIndicesOffsets[i] = totIndicesCount;
  657. if (mIndicesCount[i] > 0)
  658. {
  659. mIndexBuffer->SetIndexSubData(mIndices[i], totIndicesCount, mIndicesCount[i]);
  660. totIndicesCount += mIndicesCount[i];
  661. }
  662. }
  663. }
  664. void Chunk::AddFace(int x, int z, int h, FaceBuffer face, uchar light)
  665. {
  666. float xx = x * CubeSize;
  667. float zz = z * CubeSize;
  668. float hh = h * CubeSize;
  669. FaceMaterial faceMaterial = GetMaterial(0, face);
  670. float lightFactor = light / 15.0f;
  671. AddFace(faceMaterial, Vec3(xx, hh, zz), lightFactor, mIndices[face], mIndicesCount[face]);
  672. }
  673. void Chunk::AddFace(const FaceMaterial& faceMaterial, Vec3 traslation, float lightFactor, Crown::uint* index, Crown::uint& indicesCount)
  674. {
  675. Crown::uint firstIdx = mVertexCount;
  676. VertexData vd;
  677. vd = faceMaterial.vd0;
  678. vd.position += traslation;
  679. //vd.color *= lightFactor;
  680. memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
  681. mVertexCount++;
  682. vd = faceMaterial.vd1;
  683. vd.position += traslation;
  684. //vd.color *= lightFactor;
  685. memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
  686. mVertexCount++;
  687. vd = faceMaterial.vd2;
  688. vd.position += traslation;
  689. //vd.color *= lightFactor;
  690. memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
  691. mVertexCount++;
  692. vd = faceMaterial.vd3;
  693. vd.position += traslation;
  694. //vd.color *= lightFactor;
  695. memcpy(&mVertex[mVertexCount], &vd, sizeof(VertexData));
  696. mVertexCount++;
  697. index[indicesCount++] = firstIdx;
  698. index[indicesCount++] = firstIdx+1;
  699. index[indicesCount++] = firstIdx+2;
  700. index[indicesCount++] = firstIdx;
  701. index[indicesCount++] = firstIdx+2;
  702. index[indicesCount++] = firstIdx+3;
  703. }
  704. void DrawWiredCube(float x, float y, float z, float size)
  705. {
  706. glBegin(GL_LINES);
  707. glVertex3f(x, y, z);
  708. glVertex3f(x, y, z + size);
  709. glVertex3f(x + size, y, z);
  710. glVertex3f(x + size, y, z + size);
  711. glVertex3f(x, y + size, z);
  712. glVertex3f(x, y + size, z + size);
  713. glVertex3f(x + size, y + size, z);
  714. glVertex3f(x + size, y + size, z + size);
  715. glVertex3f(x , y, z);
  716. glVertex3f(x + size, y, z);
  717. glVertex3f(x , y, z + size);
  718. glVertex3f(x + size, y, z + size);
  719. glVertex3f(x , y + size , z);
  720. glVertex3f(x + size, y + size , z);
  721. glVertex3f(x , y + size , z + size);
  722. glVertex3f(x + size, y + size , z + size);
  723. glVertex3f(x, y , z);
  724. glVertex3f(x, y + size, z);
  725. glVertex3f(x + size, y , z);
  726. glVertex3f(x + size, y + size, z);
  727. glVertex3f(x, y , z + size);
  728. glVertex3f(x, y + size, z + size);
  729. glVertex3f(x + size, y , z + size);
  730. glVertex3f(x + size, y + size, z + size);
  731. glEnd();
  732. }