]> git.lizzy.rs Git - minetest.git/blobdiff - src/util/numeric.cpp
Fix memory leaks due to messed up memory handling for particles as well as their...
[minetest.git] / src / util / numeric.cpp
index ed83df7d7f768be0f4635820d8d0985cc409f4bd..6173515ee52489d45a7933217176233acb395c14 100644 (file)
@@ -18,9 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "numeric.h"
+#include "mathconstants.h"
 
 #include "../log.h"
 #include "../constants.h" // BS, MAP_BLOCKSIZE
+#include <string.h>
 #include <iostream>
 
 // Calculate the borders of a "d-radius" cube
@@ -138,6 +140,49 @@ int myrand_range(int min, int max)
        return (myrand()%(max-min+1))+min;
 }
 
+// 64-bit unaligned version of MurmurHash
+u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
+{
+       const u64 m = 0xc6a4a7935bd1e995ULL;
+       const int r = 47;
+       u64 h = seed ^ (len * m);
+
+       const u64 *data = (const u64 *)key;
+       const u64 *end = data + (len / 8);
+
+       while (data != end) {
+               u64 k;
+               memcpy(&k, data, sizeof(u64));
+               data++;
+
+               k *= m; 
+               k ^= k >> r; 
+               k *= m; 
+               
+               h ^= k;
+               h *= m; 
+       }
+
+       const unsigned char *data2 = (const unsigned char *)data;
+       switch (len & 7) {
+               case 7: h ^= (u64)data2[6] << 48;
+               case 6: h ^= (u64)data2[5] << 40;
+               case 5: h ^= (u64)data2[4] << 32;
+               case 4: h ^= (u64)data2[3] << 24;
+               case 3: h ^= (u64)data2[2] << 16;
+               case 2: h ^= (u64)data2[1] << 8;
+               case 1: h ^= (u64)data2[0];
+                               h *= m;
+       }
+       h ^= h >> r;
+       h *= m;
+       h ^= h >> r;
+       
+       return h;
+} 
+
+
 /*
        blockpos: position of block in block coordinates
        camera_pos: position of camera in nodes
@@ -159,40 +204,41 @@ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
        // Block position relative to camera
        v3f blockpos_relative = blockpos - camera_pos;
 
-       // Distance in camera direction (+=front, -=back)
-       f32 dforward = blockpos_relative.dotProduct(camera_dir);
-
        // Total distance
        f32 d = blockpos_relative.getLength();
 
        if(distance_ptr)
                *distance_ptr = d;
        
-       // If block is very close, it is always in sight
-       if(d < 1.44*1.44*MAP_BLOCKSIZE*BS/2)
-               return true;
-
        // If block is far away, it's not in sight
        if(d > range)
                return false;
 
-       // Maximum radius of a block
-       f32 block_max_radius = 0.5*1.44*1.44*MAP_BLOCKSIZE*BS;
+       // 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)
                return true;
-       
+
+       // Adjust camera position, for purposes of computing the angle,
+       // such that a block that has any portion visible with the
+       // current camera position will have the center visible at the
+       // adjusted postion
+       f32 adjdist = block_max_radius / cos((M_PI - camera_fov) / 2);
+
+       // Block position relative to adjusted camera
+       v3f blockpos_adj = blockpos - (camera_pos - camera_dir * adjdist);
+
+       // Distance in camera direction (+=front, -=back)
+       f32 dforward = blockpos_adj.dotProduct(camera_dir);
+
        // Cosine of the angle between the camera direction
        // and the block direction (camera_dir is an unit vector)
-       f32 cosangle = dforward / d;
+       f32 cosangle = dforward / blockpos_adj.getLength();
        
-       // Compensate for the size of the block
-       // (as the block has to be shown even if it's a bit off FOV)
-       // This is an estimate, plus an arbitary factor
-       cosangle += block_max_radius / d * 0.5;
-
        // If block is not in the field of view, skip it
        if(cosangle < cos(camera_fov / 2))
                return false;