numeric.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 <string.h>
  22. #include <iostream>
  23. UNORDERED_MAP<u16, std::vector<v3s16> > FacePositionCache::m_cache;
  24. Mutex FacePositionCache::m_cache_mutex;
  25. // Calculate the borders of a "d-radius" cube
  26. // TODO: Make it work without mutex and data races, probably thread-local
  27. std::vector<v3s16> FacePositionCache::getFacePositions(u16 d)
  28. {
  29. MutexAutoLock cachelock(m_cache_mutex);
  30. if (m_cache.find(d) != m_cache.end())
  31. return m_cache[d];
  32. generateFacePosition(d);
  33. return m_cache[d];
  34. }
  35. void FacePositionCache::generateFacePosition(u16 d)
  36. {
  37. m_cache[d] = std::vector<v3s16>();
  38. if(d == 0) {
  39. m_cache[d].push_back(v3s16(0,0,0));
  40. return;
  41. }
  42. if(d == 1) {
  43. /*
  44. This is an optimized sequence of coordinates.
  45. */
  46. m_cache[d].push_back(v3s16( 0, 1, 0)); // top
  47. m_cache[d].push_back(v3s16( 0, 0, 1)); // back
  48. m_cache[d].push_back(v3s16(-1, 0, 0)); // left
  49. m_cache[d].push_back(v3s16( 1, 0, 0)); // right
  50. m_cache[d].push_back(v3s16( 0, 0,-1)); // front
  51. m_cache[d].push_back(v3s16( 0,-1, 0)); // bottom
  52. // 6
  53. m_cache[d].push_back(v3s16(-1, 0, 1)); // back left
  54. m_cache[d].push_back(v3s16( 1, 0, 1)); // back right
  55. m_cache[d].push_back(v3s16(-1, 0,-1)); // front left
  56. m_cache[d].push_back(v3s16( 1, 0,-1)); // front right
  57. m_cache[d].push_back(v3s16(-1,-1, 0)); // bottom left
  58. m_cache[d].push_back(v3s16( 1,-1, 0)); // bottom right
  59. m_cache[d].push_back(v3s16( 0,-1, 1)); // bottom back
  60. m_cache[d].push_back(v3s16( 0,-1,-1)); // bottom front
  61. m_cache[d].push_back(v3s16(-1, 1, 0)); // top left
  62. m_cache[d].push_back(v3s16( 1, 1, 0)); // top right
  63. m_cache[d].push_back(v3s16( 0, 1, 1)); // top back
  64. m_cache[d].push_back(v3s16( 0, 1,-1)); // top front
  65. // 18
  66. m_cache[d].push_back(v3s16(-1, 1, 1)); // top back-left
  67. m_cache[d].push_back(v3s16( 1, 1, 1)); // top back-right
  68. m_cache[d].push_back(v3s16(-1, 1,-1)); // top front-left
  69. m_cache[d].push_back(v3s16( 1, 1,-1)); // top front-right
  70. m_cache[d].push_back(v3s16(-1,-1, 1)); // bottom back-left
  71. m_cache[d].push_back(v3s16( 1,-1, 1)); // bottom back-right
  72. m_cache[d].push_back(v3s16(-1,-1,-1)); // bottom front-left
  73. m_cache[d].push_back(v3s16( 1,-1,-1)); // bottom front-right
  74. // 26
  75. return;
  76. }
  77. // Take blocks in all sides, starting from y=0 and going +-y
  78. for(s16 y=0; y<=d-1; y++) {
  79. // Left and right side, including borders
  80. for(s16 z=-d; z<=d; z++) {
  81. m_cache[d].push_back(v3s16(d,y,z));
  82. m_cache[d].push_back(v3s16(-d,y,z));
  83. if(y != 0) {
  84. m_cache[d].push_back(v3s16(d,-y,z));
  85. m_cache[d].push_back(v3s16(-d,-y,z));
  86. }
  87. }
  88. // Back and front side, excluding borders
  89. for(s16 x=-d+1; x<=d-1; x++) {
  90. m_cache[d].push_back(v3s16(x,y,d));
  91. m_cache[d].push_back(v3s16(x,y,-d));
  92. if(y != 0) {
  93. m_cache[d].push_back(v3s16(x,-y,d));
  94. m_cache[d].push_back(v3s16(x,-y,-d));
  95. }
  96. }
  97. }
  98. // Take the bottom and top face with borders
  99. // -d<x<d, y=+-d, -d<z<d
  100. for(s16 x=-d; x<=d; x++)
  101. for(s16 z=-d; z<=d; z++) {
  102. m_cache[d].push_back(v3s16(x,-d,z));
  103. m_cache[d].push_back(v3s16(x,d,z));
  104. }
  105. }
  106. /*
  107. myrand
  108. */
  109. PcgRandom g_pcgrand;
  110. u32 myrand()
  111. {
  112. return g_pcgrand.next();
  113. }
  114. void mysrand(unsigned int seed)
  115. {
  116. g_pcgrand.seed(seed);
  117. }
  118. void myrand_bytes(void *out, size_t len)
  119. {
  120. g_pcgrand.bytes(out, len);
  121. }
  122. int myrand_range(int min, int max)
  123. {
  124. return g_pcgrand.range(min, max);
  125. }
  126. /*
  127. 64-bit unaligned version of MurmurHash
  128. */
  129. u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
  130. {
  131. const u64 m = 0xc6a4a7935bd1e995ULL;
  132. const int r = 47;
  133. u64 h = seed ^ (len * m);
  134. const u64 *data = (const u64 *)key;
  135. const u64 *end = data + (len / 8);
  136. while (data != end) {
  137. u64 k;
  138. memcpy(&k, data, sizeof(u64));
  139. data++;
  140. k *= m;
  141. k ^= k >> r;
  142. k *= m;
  143. h ^= k;
  144. h *= m;
  145. }
  146. const unsigned char *data2 = (const unsigned char *)data;
  147. switch (len & 7) {
  148. case 7: h ^= (u64)data2[6] << 48;
  149. case 6: h ^= (u64)data2[5] << 40;
  150. case 5: h ^= (u64)data2[4] << 32;
  151. case 4: h ^= (u64)data2[3] << 24;
  152. case 3: h ^= (u64)data2[2] << 16;
  153. case 2: h ^= (u64)data2[1] << 8;
  154. case 1: h ^= (u64)data2[0];
  155. h *= m;
  156. }
  157. h ^= h >> r;
  158. h *= m;
  159. h ^= h >> r;
  160. return h;
  161. }
  162. /*
  163. blockpos_b: position of block in block coordinates
  164. camera_pos: position of camera in nodes
  165. camera_dir: an unit vector pointing to camera direction
  166. range: viewing range
  167. distance_ptr: return location for distance from the camera
  168. */
  169. bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
  170. f32 camera_fov, f32 range, f32 *distance_ptr)
  171. {
  172. // Maximum radius of a block. The magic number is
  173. // sqrt(3.0) / 2.0 in literal form.
  174. const f32 block_max_radius = 0.866025403784 * MAP_BLOCKSIZE * BS;
  175. v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
  176. // Block center position
  177. v3f blockpos(
  178. ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
  179. ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS,
  180. ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS
  181. );
  182. // Block position relative to camera
  183. v3f blockpos_relative = blockpos - camera_pos;
  184. // Total distance
  185. f32 d = MYMAX(0, blockpos_relative.getLength() - block_max_radius);
  186. if(distance_ptr)
  187. *distance_ptr = d;
  188. // If block is far away, it's not in sight
  189. if(d > range)
  190. return false;
  191. // If block is (nearly) touching the camera, don't
  192. // bother validating further (that is, render it anyway)
  193. if(d == 0)
  194. return true;
  195. // Adjust camera position, for purposes of computing the angle,
  196. // such that a block that has any portion visible with the
  197. // current camera position will have the center visible at the
  198. // adjusted postion
  199. f32 adjdist = block_max_radius / cos((M_PI - camera_fov) / 2);
  200. // Block position relative to adjusted camera
  201. v3f blockpos_adj = blockpos - (camera_pos - camera_dir * adjdist);
  202. // Distance in camera direction (+=front, -=back)
  203. f32 dforward = blockpos_adj.dotProduct(camera_dir);
  204. // Cosine of the angle between the camera direction
  205. // and the block direction (camera_dir is an unit vector)
  206. f32 cosangle = dforward / blockpos_adj.getLength();
  207. // If block is not in the field of view, skip it
  208. // HOTFIX: use sligthly increased angle (+10%) to fix too agressive
  209. // culling. Somebody have to find out whats wrong with the math here.
  210. // Previous value: camera_fov / 2
  211. if(cosangle < cos(camera_fov * 0.55))
  212. return false;
  213. return true;
  214. }