HeightMap.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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, float scale, World* world)
  14. {
  15. this->scale = scale;
  16. int bpp;
  17. unsigned char* imgData = stbi_load(file.c_str(), &width, &height, &bpp, 4);
  18. auto heightAt = [&](int x, int y)
  19. {
  20. return (imgData[(x + y * width) * 4 ] / 256.0f) * 100.0f;
  21. };
  22. auto valueAt = [&](int x, int y, int offset = 0)
  23. {
  24. return imgData[(x + y * width) * 4 + offset];
  25. };
  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. if ((valueAt(x, y, GREEN) >= 10) && (valueAt(x,y,GREEN) <= 100))
  34. {
  35. world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, rand() % 360, 0), 1, true));
  36. }
  37. if (valueAt(x, y, GREEN) == 180 || valueAt(x, y, GREEN) == 190 || valueAt(x, y, GREEN) == 170 || valueAt(x, y, GREEN) == 250)
  38. {
  39. world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, 0, 0), 1, true));
  40. }
  41. if ((valueAt(x, y, GREEN) >= 200) && (valueAt(x, y, GREEN) <= 240))
  42. {
  43. world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, 0, 0), 1, false));
  44. }
  45. if (valueAt(x, y, GREEN) == 160)
  46. {
  47. world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, 0, 0), 1, false));
  48. }
  49. Vec3f normal = ca.cross(ba);
  50. normal.Normalize();
  51. for (int i = 0; i < 4; i++)
  52. {
  53. float h = heightAt(x + offsets[i][0], y + offsets[i][1]);
  54. vertices.push_back(Vertex{ (float)(x + offsets[i][0])*scale, h*scale, (float)(y + offsets[i][1])*scale,
  55. normal.x, normal.y, normal.z,
  56. (x + offsets[i][0]) / (float)height, (y + offsets[i][1]) / (float)width } );
  57. }
  58. }
  59. }
  60. glGenTextures(1, &imageIndex);
  61. glBindTexture(GL_TEXTURE_2D, imageIndex);
  62. glTexImage2D(GL_TEXTURE_2D,
  63. 0, //level
  64. GL_RGBA, //internal format
  65. width, //width
  66. height, //height
  67. 0, //border
  68. GL_RGBA, //data format
  69. GL_UNSIGNED_BYTE, //data type
  70. imgData); //data
  71. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  72. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  73. stbi_image_free(imgData);
  74. }
  75. HeightMap::~HeightMap()
  76. {
  77. glDeleteTextures(1, &imageIndex);
  78. }
  79. void HeightMap::Draw()
  80. {
  81. glEnable(GL_LIGHTING);
  82. float color[] = { 0.7f, 0.7f, 0.7f, 1 };
  83. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  84. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
  85. glEnable(GL_TEXTURE_2D);
  86. glBindTexture(GL_TEXTURE_2D, imageIndex);
  87. glEnableClientState(GL_VERTEX_ARRAY);
  88. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  89. //glEnableClientState(GL_COLOR_ARRAY);
  90. glEnableClientState(GL_NORMAL_ARRAY);
  91. glVertexPointer(3, GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 0);
  92. glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 6);
  93. glNormalPointer(GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 3);
  94. glDrawArrays(GL_QUADS, 0, vertices.size());
  95. glDisableClientState(GL_VERTEX_ARRAY);
  96. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  97. //glDisableClientState(GL_COLOR_ARRAY);
  98. glDisableClientState(GL_NORMAL_ARRAY);
  99. }
  100. float HeightMap::GetHeight(float x, float y)
  101. {
  102. x /= scale;
  103. y /= scale;
  104. int ix = x;
  105. int iy = y;
  106. int index = (ix + (width - 1) * iy) * 4;
  107. Vertex& a = vertices[index];
  108. Vertex& b = vertices[index+1];
  109. Vertex& c = vertices[index+3];
  110. float lowervalue = ((b.z - c.z)*(a.x - c.x) + (c.x - b.x)*(a.z - c.z));
  111. float labda1 = ((b.z - c.z)*(x - c.x) + (c.x - b.x)*(y - c.z)) / lowervalue;
  112. float labda2 = ((c.y - a.y)*(x - c.x) + (a.x - c.x)*(y - c.y)) / lowervalue;
  113. float labda3 = 1 - labda1 - labda2;
  114. Vertex z = a * labda1 + b * labda2 + c * labda3;
  115. return z.y;
  116. }
  117. void HeightMap::SetTexture(const std::string &file)
  118. {
  119. int bpp, width2, height2;
  120. unsigned char* imgData = stbi_load(file.c_str(), &width2, &height2, &bpp, 4);
  121. glBindTexture(GL_TEXTURE_2D, imageIndex);
  122. glTexImage2D(GL_TEXTURE_2D,
  123. 0, //level
  124. GL_RGBA, //internal format
  125. width2, //width
  126. height2, //height
  127. 0, //border
  128. GL_RGBA, //data format
  129. GL_UNSIGNED_BYTE, //data type
  130. imgData); //data
  131. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  132. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  133. stbi_image_free(imgData);
  134. }