*/
#include "numeric.h"
-#include "mathconstants.h"
-#include "../log.h"
-#include "../constants.h" // BS, MAP_BLOCKSIZE
-#include <string.h>
-#include <iostream>
+#include "log.h"
+#include "constants.h" // BS, MAP_BLOCKSIZE
+#include "noise.h" // PseudoRandom, PcgRandom
+#include "threading/mutex_auto_lock.h"
+#include <cstring>
+#include <cmath>
-// Calculate the borders of a "d-radius" cube
-void getFacePositions(std::list<v3s16> &list, u16 d)
-{
- if(d == 0)
- {
- list.push_back(v3s16(0,0,0));
- return;
- }
- if(d == 1)
- {
- /*
- This is an optimized sequence of coordinates.
- */
- list.push_back(v3s16( 0, 1, 0)); // top
- list.push_back(v3s16( 0, 0, 1)); // back
- list.push_back(v3s16(-1, 0, 0)); // left
- list.push_back(v3s16( 1, 0, 0)); // right
- list.push_back(v3s16( 0, 0,-1)); // front
- list.push_back(v3s16( 0,-1, 0)); // bottom
- // 6
- list.push_back(v3s16(-1, 0, 1)); // back left
- list.push_back(v3s16( 1, 0, 1)); // back right
- list.push_back(v3s16(-1, 0,-1)); // front left
- list.push_back(v3s16( 1, 0,-1)); // front right
- list.push_back(v3s16(-1,-1, 0)); // bottom left
- list.push_back(v3s16( 1,-1, 0)); // bottom right
- list.push_back(v3s16( 0,-1, 1)); // bottom back
- list.push_back(v3s16( 0,-1,-1)); // bottom front
- list.push_back(v3s16(-1, 1, 0)); // top left
- list.push_back(v3s16( 1, 1, 0)); // top right
- list.push_back(v3s16( 0, 1, 1)); // top back
- list.push_back(v3s16( 0, 1,-1)); // top front
- // 18
- list.push_back(v3s16(-1, 1, 1)); // top back-left
- list.push_back(v3s16( 1, 1, 1)); // top back-right
- list.push_back(v3s16(-1, 1,-1)); // top front-left
- list.push_back(v3s16( 1, 1,-1)); // top front-right
- list.push_back(v3s16(-1,-1, 1)); // bottom back-left
- list.push_back(v3s16( 1,-1, 1)); // bottom back-right
- list.push_back(v3s16(-1,-1,-1)); // bottom front-left
- list.push_back(v3s16( 1,-1,-1)); // bottom front-right
- // 26
- return;
- }
- // Take blocks in all sides, starting from y=0 and going +-y
- for(s16 y=0; y<=d-1; y++)
- {
- // Left and right side, including borders
- for(s16 z=-d; z<=d; z++)
- {
- list.push_back(v3s16(d,y,z));
- list.push_back(v3s16(-d,y,z));
- if(y != 0)
- {
- list.push_back(v3s16(d,-y,z));
- list.push_back(v3s16(-d,-y,z));
- }
- }
- // Back and front side, excluding borders
- for(s16 x=-d+1; x<=d-1; x++)
- {
- list.push_back(v3s16(x,y,d));
- list.push_back(v3s16(x,y,-d));
- if(y != 0)
- {
- list.push_back(v3s16(x,-y,d));
- list.push_back(v3s16(x,-y,-d));
- }
- }
- }
+// myrand
- // Take the bottom and top face with borders
- // -d<x<d, y=+-d, -d<z<d
- for(s16 x=-d; x<=d; x++)
- for(s16 z=-d; z<=d; z++)
- {
- list.push_back(v3s16(x,-d,z));
- list.push_back(v3s16(x,d,z));
- }
-}
+PcgRandom g_pcgrand;
-/*
- myrand
-*/
-
-static unsigned long next = 1;
+u32 myrand()
+{
+ return g_pcgrand.next();
+}
-/* RAND_MAX assumed to be 32767 */
-int myrand(void)
+void mysrand(unsigned int seed)
{
- next = next * 1103515245 + 12345;
- return((unsigned)(next/65536) % 32768);
+ g_pcgrand.seed(seed);
}
-void mysrand(unsigned seed)
+void myrand_bytes(void *out, size_t len)
{
- next = seed;
+ g_pcgrand.bytes(out, len);
}
int myrand_range(int min, int max)
{
- if(max-min > MYRAND_MAX)
- {
- errorstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
- max = min + MYRAND_MAX;
- }
- if(min > max)
- {
- errorstream<<"WARNING: myrand_range: min > max"<<std::endl;
- return max;
- }
- return (myrand()%(max-min+1))+min;
+ return g_pcgrand.range(min, max);
}
-// 64-bit unaligned version of MurmurHash
+
+/*
+ 64-bit unaligned version of MurmurHash
+*/
u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
{
const u64 m = 0xc6a4a7935bd1e995ULL;
memcpy(&k, data, sizeof(u64));
data++;
- k *= m;
- k ^= k >> r;
- k *= m;
-
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
h ^= k;
- h *= m;
+ h *= m;
}
const unsigned char *data2 = (const unsigned char *)data;
case 1: h ^= (u64)data2[0];
h *= m;
}
-
+
h ^= h >> r;
h *= m;
h ^= h >> r;
-
- return h;
-}
+ return h;
+}
/*
- blockpos: position of block in block coordinates
+ blockpos_b: position of block in block coordinates
camera_pos: position of camera in nodes
camera_dir: an unit vector pointing to camera direction
range: viewing range
+ distance_ptr: return location for distance from the camera
*/
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
f32 camera_fov, f32 range, f32 *distance_ptr)
{
+ // Maximum radius of a block. The magic number is
+ // sqrt(3.0) / 2.0 in literal form.
+ const f32 block_max_radius = 0.866025403784 * MAP_BLOCKSIZE * BS;
+
v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE;
-
+
// Block center position
v3f blockpos(
((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS,
v3f blockpos_relative = blockpos - camera_pos;
// Total distance
- f32 d = blockpos_relative.getLength();
+ f32 d = MYMAX(0, blockpos_relative.getLength() - block_max_radius);
if(distance_ptr)
*distance_ptr = d;
-
+
// If block is far away, it's not in sight
if(d > range)
return false;
- // Maximum radius of a block. The magic number is
- // sqrt(3.0) / 2.0 in literal form.
- f32 block_max_radius = 0.866025403784 * MAP_BLOCKSIZE * BS;
-
// If block is (nearly) touching the camera, don't
// bother validating further (that is, render it anyway)
- if(d < block_max_radius)
+ if(d == 0)
return true;
// Adjust camera position, for purposes of computing the angle,
// Cosine of the angle between the camera direction
// and the block direction (camera_dir is an unit vector)
f32 cosangle = dforward / blockpos_adj.getLength();
-
+
// If block is not in the field of view, skip it
- if(cosangle < cos(camera_fov / 2))
+ // HOTFIX: use sligthly increased angle (+10%) to fix too agressive
+ // culling. Somebody have to find out whats wrong with the math here.
+ // Previous value: camera_fov / 2
+ if(cosangle < cos(camera_fov * 0.55))
return false;
return true;
}
+s16 adjustDist(s16 dist, float zoom_fov)
+{
+ // 1.775 ~= 72 * PI / 180 * 1.4, the default on the client
+ const float default_fov = 1.775f;
+ // heuristic cut-off for zooming
+ if (zoom_fov > default_fov / 2.0f)
+ return dist;
+
+ // new_dist = dist * ((1 - cos(FOV / 2)) / (1-cos(zoomFOV /2))) ^ (1/3)
+ return round(dist * cbrt((1.0f - std::cos(default_fov / 2.0f)) /
+ (1.0f - std::cos(zoom_fov / 2.0f))));
+}