/*
-Minetest-c55
-Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
*/
#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
-void getFacePositions(core::list<v3s16> &list, u16 d)
+void getFacePositions(std::list<v3s16> &list, u16 d)
{
if(d == 0)
{
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
// 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;