HeightMap.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "HeightMap.h"
  2. #include "stb_image.h"
  3. #include "vector.h"
  4. #include <GL/freeglut.h>
  5. #include <iostream>
  6. #include <string>
  7. HeightMap::HeightMap(const std::string &file, float scale)
  8. {
  9. this->scale = scale;
  10. int bpp;
  11. unsigned char* imgData = stbi_load(file.c_str(), &width, &height, &bpp, 4);
  12. auto heightAt = [&](int x, int y)
  13. {
  14. return (imgData[(x + y * width) * 4] / 256.0f) * 100.0f;
  15. };
  16. for (int y = 0; y < height-1; y++)
  17. {
  18. for (int x = 0; x < width-1; x++)
  19. {
  20. int offsets[4][2] = { { 0, 0 },{ 1, 0 },{ 1, 1 },{ 0, 1 } };
  21. Vec3f ca(0, heightAt(x, y + 1) - heightAt(x, y), 1);
  22. Vec3f ba(1, heightAt(x + 1, y) - heightAt(x, y), 0);
  23. Vec3f normal = ca.cross(ba);
  24. normal.Normalize();
  25. for (int i = 0; i < 4; i++)
  26. {
  27. float h = heightAt(x + offsets[i][0], y + offsets[i][1]);
  28. vertices.push_back(Vertex{ (float)(x + offsets[i][0])*scale, h*scale, (float)(y + offsets[i][1])*scale,
  29. normal.x, normal.y, normal.z,
  30. (x + offsets[i][0]) / (float)height, (y + offsets[i][1]) / (float)width } );
  31. }
  32. }
  33. }
  34. glGenTextures(1, &imageIndex);
  35. glBindTexture(GL_TEXTURE_2D, imageIndex);
  36. glTexImage2D(GL_TEXTURE_2D,
  37. 0, //level
  38. GL_RGBA, //internal format
  39. width, //width
  40. height, //height
  41. 0, //border
  42. GL_RGBA, //data format
  43. GL_UNSIGNED_BYTE, //data type
  44. imgData); //data
  45. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  46. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  47. stbi_image_free(imgData);
  48. }
  49. HeightMap::~HeightMap()
  50. {
  51. glDeleteTextures(1, &imageIndex);
  52. }
  53. void HeightMap::Draw()
  54. {
  55. glEnable(GL_LIGHTING);
  56. float color[] = { 0.7f, 0.7f, 0.7f, 1 };
  57. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  58. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
  59. glEnable(GL_TEXTURE_2D);
  60. glBindTexture(GL_TEXTURE_2D, imageIndex);
  61. //glDisable(GL_TEXTURE_2D);
  62. glEnableClientState(GL_VERTEX_ARRAY);
  63. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  64. //glEnableClientState(GL_COLOR_ARRAY);
  65. glEnableClientState(GL_NORMAL_ARRAY);
  66. glVertexPointer(3, GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 0);
  67. glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 6);
  68. glNormalPointer(GL_FLOAT, sizeof(Vertex), ((float*)vertices.data()) + 3);
  69. glDrawArrays(GL_QUADS, 0, vertices.size());
  70. glDisableClientState(GL_VERTEX_ARRAY);
  71. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  72. //glDisableClientState(GL_COLOR_ARRAY);
  73. glDisableClientState(GL_NORMAL_ARRAY);
  74. }
  75. float HeightMap::GetHeight(float x, float y)
  76. {
  77. x /= scale;
  78. y /= scale;
  79. int ix = x;
  80. int iy = y;
  81. int index = (ix + (width - 1) * iy) * 4;
  82. Vertex& a = vertices[index];
  83. Vertex& b = vertices[index+1];
  84. Vertex& c = vertices[index+3];
  85. float lowervalue = ((b.y - c.y)*(a.x - c.x) + (c.x - b.x)*(a.y - c.y));
  86. float labda1 = ((b.y - c.y)*(x - c.x) + (c.x - b.x)*(y - c.y)) / lowervalue;
  87. float labda2 = ((c.y - a.y)*(x - c.x) + (a.x - c.x)*(y - c.y)) / lowervalue;
  88. float labda3 = 1 - labda1 - labda2;
  89. Vec3f z = Vec3f(a.x, a.y, a.z) * labda1 + Vec3f(b.x, b.y, b.z) * labda2 + Vec3f(c.x, c.y, c.z) * labda3;
  90. return z.y;
  91. }
  92. void HeightMap::SetTexture(const std::string &file)
  93. {
  94. int bpp, width2, height2;
  95. unsigned char* imgData = stbi_load(file.c_str(), &width2, &height2, &bpp, 4);
  96. glBindTexture(GL_TEXTURE_2D, imageIndex);
  97. glTexImage2D(GL_TEXTURE_2D,
  98. 0, //level
  99. GL_RGBA, //internal format
  100. width2, //width
  101. height2, //height
  102. 0, //border
  103. GL_RGBA, //data format
  104. GL_UNSIGNED_BYTE, //data type
  105. imgData); //data
  106. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  107. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  108. stbi_image_free(imgData);
  109. }