HeightMap.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include "HeightMap.h"
  2. #include "stb_image.h"
  3. #include "Vector.h"
  4. #include "LevelObject.h"
  5. #include <GL/freeglut.h>
  6. #include <iostream>
  7. #include <string>
  8. #include "World.h"
  9. #define RED 0
  10. #define GREEN 1
  11. #define BLUE 2
  12. #define ALPHA 3
  13. HeightMap::HeightMap(const std::string &file, World* world)
  14. {
  15. int bpp;
  16. unsigned char* imgData = stbi_load(file.c_str(), &width, &height, &bpp, 4);
  17. auto heightAt = [&](int x, int y)
  18. {
  19. return (imgData[(x + y * width) * 4 ] / 256.0f) * 50.0f;
  20. };
  21. auto valueAt = [&](int x, int y, int offset = 0)
  22. {
  23. return imgData[(x + y * width) * 4 + offset];
  24. };
  25. std::vector<std::vector<Vec3f>> faceNormals(width-1, std::vector<Vec3f>(height-1, Vec3f(0,1,0)));
  26. for (int y = 0; y < height - 1; y++)
  27. {
  28. for (int x = 0; x < width - 1; x++)
  29. {
  30. int offsets[4][2] = { { 0, 0 },{ 1, 0 },{ 1, 1 },{ 0, 1 } };
  31. Vec3f ca(0, heightAt(x, y + 1) - heightAt(x, y), 1);
  32. Vec3f ba(1, heightAt(x + 1, y) - heightAt(x, y), 0);
  33. Vec3f normal = ca.cross(ba);
  34. normal.Normalize();
  35. faceNormals[x][y] = normal;
  36. }
  37. }
  38. for (int y = 0; y < height-1; y++)
  39. {
  40. for (int x = 0; x < width-1; x++)
  41. {
  42. int offsets[4][2] = { { 0, 0 },{ 1, 0 },{ 1, 1 },{ 0, 1 } };
  43. if (valueAt(x, y, GREEN) > 5)
  44. {
  45. world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)).first, Vec3f(x, heightAt(x, y), y), Vec3f(0, 0, 0), 1, world->getObjectFromValue(valueAt(x, y, GREEN)).second));
  46. }
  47. for (int i = 0; i < 4; i++)
  48. {
  49. int xx = x + offsets[i][0];
  50. int yy = y + offsets[i][1];
  51. Vec3f normal(0, 0, 0);
  52. if(xx < width-1 && yy < height-1)
  53. normal = normal + faceNormals[xx][yy];
  54. if(xx > 0 && yy < height-1)
  55. normal = normal + faceNormals[xx-1][yy];
  56. if (xx > 0 && yy > 0)
  57. normal = normal + faceNormals[xx-1][yy-1];
  58. if (yy > 0 && xx < width-1)
  59. normal = normal + faceNormals[xx][yy-1];
  60. normal.Normalize();
  61. float h = heightAt(xx, yy);
  62. vertices.push_back(Vertex{ (float)(xx), h, (float)(yy),
  63. normal.x, normal.y, normal.z,
  64. (xx) / (float)height, (yy) / (float)width } );
  65. }
  66. }
  67. }
  68. glGenTextures(1, &imageIndex);
  69. glBindTexture(GL_TEXTURE_2D, imageIndex);
  70. glTexImage2D(GL_TEXTURE_2D,
  71. 0, //level
  72. GL_RGBA, //internal format
  73. width, //width
  74. height, //height
  75. 0, //border
  76. GL_RGBA, //data format
  77. GL_UNSIGNED_BYTE, //data type
  78. imgData); //data
  79. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  80. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  81. stbi_image_free(imgData);
  82. }
  83. HeightMap::~HeightMap()
  84. {
  85. glDeleteTextures(1, &imageIndex);
  86. }
  87. void HeightMap::Draw()
  88. {
  89. glEnable(GL_LIGHTING);
  90. float color[] = { 0.7f, 0.7f, 0.7f, 1 };
  91. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  92. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
  93. glEnable(GL_TEXTURE_2D);
  94. glBindTexture(GL_TEXTURE_2D, imageIndex);
  95. glEnableClientState(GL_VERTEX_ARRAY);
  96. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  97. //glEnableClientState(GL_COLOR_ARRAY);
  98. glEnableClientState(GL_NORMAL_ARRAY);
  99. glVertexPointer(3, GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 0);
  100. glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 6);
  101. glNormalPointer(GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 3);
  102. glDrawArrays(GL_QUADS, 0, vertices.size());
  103. glDisableClientState(GL_VERTEX_ARRAY);
  104. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  105. //glDisableClientState(GL_COLOR_ARRAY);
  106. glDisableClientState(GL_NORMAL_ARRAY);
  107. }
  108. float HeightMap::GetHeight(float x, float y)
  109. {
  110. int ix = x;
  111. int iy = y;
  112. int index = (ix + (width - 1) * iy) * 4;
  113. if (index + 3 >= vertices.size())
  114. index = vertices.size() - 4;
  115. if (index < 0)
  116. index = 0;
  117. Vertex& a = vertices[index];
  118. Vertex& b = vertices[index+1];
  119. Vertex& c = vertices[index+3];
  120. float lowervalue = ((b.z - c.z)*(a.x - c.x) + (c.x - b.x)*(a.z - c.z));
  121. float labda1 = ((b.z - c.z)*(x - c.x) + (c.x - b.x)*(y - c.z)) / lowervalue;
  122. float labda2 = ((c.y - a.y)*(x - c.x) + (a.x - c.x)*(y - c.y)) / lowervalue;
  123. float labda3 = 1 - labda1 - labda2;
  124. Vertex z = a * labda1 + b * labda2 + c * labda3;
  125. // Vertex z = (a * labda1) + (b * labda2) ;
  126. return z.y;
  127. }
  128. int HeightMap::GetSize()
  129. {
  130. return height >= width ? height : width;
  131. }
  132. void HeightMap::SetTexture(const std::string &file)
  133. {
  134. int bpp, width2, height2;
  135. unsigned char* imgData = stbi_load(file.c_str(), &width2, &height2, &bpp, 4);
  136. glBindTexture(GL_TEXTURE_2D, imageIndex);
  137. glTexImage2D(GL_TEXTURE_2D,
  138. 0, //level
  139. GL_RGBA, //internal format
  140. width2, //width
  141. height2, //height
  142. 0, //border
  143. GL_RGBA, //data format
  144. GL_UNSIGNED_BYTE, //data type
  145. imgData); //data
  146. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  147. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  148. stbi_image_free(imgData);
  149. }