fov.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #ifndef __FOV_H
  2. #define __FOV_H
  3. namespace fov {
  4. template <typename T>
  5. void cast_light(unsigned int w, unsigned int h, std::vector<T>& grid,
  6. unsigned int cx, unsigned int cy,
  7. unsigned int cx2, unsigned int cy2,
  8. int row, float start, float end,
  9. unsigned int radius, unsigned int r2,
  10. int xx, int xy, int yx, int yy,
  11. std::set< std::pair<unsigned int, unsigned int> >& ret) {
  12. float new_start = 0.0;
  13. if (start < end)
  14. return;
  15. for (int j = row; j < (int)radius + 1; j++) {
  16. int dx = -j - 1;
  17. int dy = -j;
  18. bool blocked = false;
  19. while (dx <= 0) {
  20. int X;
  21. int Y;
  22. dx++;
  23. X = cx + dx * xx + dy * xy;
  24. Y = cy + dx * yx + dy * yy;
  25. if (X < 0 || (unsigned int)X >= w || Y < 0 || (unsigned int)Y >= h)
  26. continue;
  27. size_t offset = X + Y*w;
  28. float l_slope = (dx-0.5f) / (dy+0.5f);
  29. float r_slope = (dx+0.5f) / (dy-0.5f);
  30. if (start < r_slope) {
  31. continue;
  32. } else if (end > l_slope) {
  33. break;
  34. }
  35. auto& thispoint = grid[offset];
  36. unsigned int dist = dx*dx + dy*dy;
  37. if (cx2 != cx || cy2 != cy) {
  38. unsigned int dx2 = (X - cx2) * (X - cx2);
  39. unsigned int dy2 = (Y - cy2) * (Y - cy2);
  40. unsigned int dist2 = dx2 + dy2;
  41. dist = dist + dist2 + 2.0 * ::sqrt(dist * dist2);
  42. /*
  43. unsigned int dx2 = (X - cx2) * (X - cx2);
  44. unsigned int dy2 = (Y - cy2) * (Y - cy2);
  45. double z = ::sqrt(dx2 + dy2) + ::sqrt(dist);
  46. dist = z * z;
  47. */
  48. }
  49. if (dist <= r2) {
  50. uint8_t newfov = ::sqrt((double)dist / (double)r2) * 100 + 1;
  51. if (thispoint.is_lightsource && thispoint.in_fov == 0) {
  52. ret.insert(std::make_pair(X, Y));
  53. }
  54. if (thispoint.in_fov == 0 || thispoint.in_fov > newfov) {
  55. thispoint.in_fov = newfov;
  56. }
  57. }
  58. if (blocked) {
  59. if (thispoint.is_viewblock) {
  60. new_start = r_slope;
  61. continue;
  62. } else {
  63. blocked = false;
  64. start = new_start;
  65. }
  66. } else {
  67. if (thispoint.is_viewblock && j < (int)radius) {
  68. blocked = true;
  69. cast_light(w, h, grid,
  70. cx, cy,
  71. cx2, cy2,
  72. j+1, start, l_slope, radius, r2,
  73. xx, xy, yx, yy,
  74. ret);
  75. new_start = r_slope;
  76. }
  77. }
  78. }
  79. if (blocked)
  80. break;
  81. }
  82. }
  83. template <typename T>
  84. void fov_shadowcasting(unsigned int w, unsigned int h, std::vector<T>& grid,
  85. unsigned int x, unsigned int y, unsigned int radius) {
  86. for (auto& i : grid) {
  87. i.in_fov = 0;
  88. }
  89. static int mult[4][8] = {
  90. {1, 0, 0, -1, -1, 0, 0, 1},
  91. {0, 1, -1, 0, 0, -1, 1, 0},
  92. {0, 1, 1, 0, 0, -1, -1, 0},
  93. {1, 0, 0, 1, -1, 0, 0, -1},
  94. };
  95. std::set< std::pair<unsigned int, unsigned int> > lights;
  96. for (unsigned int oct = 0; oct < 8; ++oct) {
  97. cast_light(w, h, grid, x, y, x, y,
  98. 1, 1.0, 0.0, radius, radius * radius,
  99. mult[0][oct],
  100. mult[1][oct],
  101. mult[2][oct],
  102. mult[3][oct],
  103. lights);
  104. }
  105. grid[x+w*y].in_fov = 1;
  106. while (lights.size() > 0) {
  107. std::pair<unsigned int, unsigned int> pt = *(lights.begin());
  108. lights.erase(lights.begin());
  109. int _x = (x - pt.first);
  110. int _y = (y - pt.second);
  111. unsigned int rad = ::sqrt(_x*_x + _y*_y) + radius;
  112. unsigned int r2 = ((rad + radius) * (rad + radius));
  113. for (unsigned int oct = 0; oct < 8; ++oct) {
  114. cast_light(w, h, grid, x, y, pt.first, pt.second,
  115. 1, 1.0, 0.0, rad, r2,
  116. mult[0][oct],
  117. mult[1][oct],
  118. mult[2][oct],
  119. mult[3][oct],
  120. lights);
  121. }
  122. }
  123. }
  124. }
  125. #endif