numeric.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "numeric.h"
  17. #include "log.h"
  18. #include "constants.h" // BS, MAP_BLOCKSIZE
  19. #include "noise.h" // PseudoRandom, PcgRandom
  20. #include "threading/mutex_auto_lock.h"
  21. #include <cstring>
  22. #include <cmath>
  23. // myrand
  24. PcgRandom g_pcgrand;
  25. u32 myrand()
  26. {
  27. return g_pcgrand.next();
  28. }
  29. void mysrand(unsigned int seed)
  30. {
  31. g_pcgrand.seed(seed);
  32. }
  33. void myrand_bytes(void *out, size_t len)
  34. {
  35. g_pcgrand.bytes(out, len);
  36. }
  37. int myrand_range(int min, int max)
  38. {
  39. return g_pcgrand.range(min, max);
  40. }
  41. /*
  42. 64-bit unaligned version of MurmurHash
  43. */
  44. u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
  45. {
  46. const u64 m = 0xc6a4a7935bd1e995ULL;
  47. const int r = 47;
  48. u64 h = seed ^ (len * m);
  49. const u64 *data = (const u64 *)key;
  50. const u64 *end = data + (len / 8);
  51. while (data != end) {
  52. u64 k;
  53. memcpy(&k, data, sizeof(u64));
  54. data++;
  55. k *= m;
  56. k ^= k >> r;
  57. k *= m;
  58. h ^= k;
  59. h *= m;
  60. }
  61. const unsigned char *data2 = (const unsigned char *)data;
  62. switch (len & 7) {
  63. case 7: h ^= (u64)data2[6] << 48;
  64. case 6: h ^= (u64)data2[5] << 40;
  65. case 5: h ^= (u64)data2[4] << 32;
  66. case 4: h ^= (u64)data2[3] << 24;
  67. case 3: h ^= (u64)data2[2] << 16;
  68. case 2: h ^= (u64)data2[1] << 8;
  69. case 1: h ^= (u64)data2[0];
  70. h *= m;
  71. }
  72. h ^= h >> r;
  73. h *= m;
  74. h ^= h >> r;
  75. return h;
  76. }
  77. /*
  78. blockpos_b: position of block in block coordinates
  79. camera_pos: position of camera in nodes
  80. camera_dir: an unit vector pointing to camera direction
  81. range: viewing range
  82. distance_ptr: return location for distance from the camera
  83. */
  84. bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
  85. f32 camera_fov, f32 range, f32 *distance_ptr)
  86. {
  87. // Maximum radius of a block. The magic number is
  88. // sqrt(3.0) / 2.0 in literal form.
  89. static constexpr const f32 block_max_radius = 0.866025403784f * MAP_BLOCKSIZE * BS;
  90. v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
  91. // Block center position
  92. v3f blockpos(
  93. ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
  94. ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS,
  95. ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS
  96. );
  97. // Block position relative to camera
  98. v3f blockpos_relative = blockpos - camera_pos;
  99. // Total distance
  100. f32 d = MYMAX(0, blockpos_relative.getLength() - block_max_radius);
  101. if (distance_ptr)
  102. *distance_ptr = d;
  103. // If block is far away, it's not in sight
  104. if (d > range)
  105. return false;
  106. // If block is (nearly) touching the camera, don't
  107. // bother validating further (that is, render it anyway)
  108. if (d == 0)
  109. return true;
  110. // Adjust camera position, for purposes of computing the angle,
  111. // such that a block that has any portion visible with the
  112. // current camera position will have the center visible at the
  113. // adjusted postion
  114. f32 adjdist = block_max_radius / cos((M_PI - camera_fov) / 2);
  115. // Block position relative to adjusted camera
  116. v3f blockpos_adj = blockpos - (camera_pos - camera_dir * adjdist);
  117. // Distance in camera direction (+=front, -=back)
  118. f32 dforward = blockpos_adj.dotProduct(camera_dir);
  119. // Cosine of the angle between the camera direction
  120. // and the block direction (camera_dir is an unit vector)
  121. f32 cosangle = dforward / blockpos_adj.getLength();
  122. // If block is not in the field of view, skip it
  123. // HOTFIX: use sligthly increased angle (+10%) to fix too agressive
  124. // culling. Somebody have to find out whats wrong with the math here.
  125. // Previous value: camera_fov / 2
  126. if (cosangle < std::cos(camera_fov * 0.55f))
  127. return false;
  128. return true;
  129. }
  130. s16 adjustDist(s16 dist, float zoom_fov)
  131. {
  132. // 1.775 ~= 72 * PI / 180 * 1.4, the default FOV on the client.
  133. // The heuristic threshold for zooming is half of that.
  134. static constexpr const float threshold_fov = 1.775f / 2.0f;
  135. if (zoom_fov < 0.001f || zoom_fov > threshold_fov)
  136. return dist;
  137. return std::round(dist * std::cbrt((1.0f - std::cos(threshold_fov)) /
  138. (1.0f - std::cos(zoom_fov / 2.0f))));
  139. }