3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "constants.h" // BS, MAP_BLOCKSIZE
24 #include "noise.h" // PseudoRandom, PcgRandom
25 #include "threading/mutex_auto_lock.h"
36 return g_pcgrand
.next();
39 void mysrand(unsigned int seed
)
44 void myrand_bytes(void *out
, size_t len
)
46 g_pcgrand
.bytes(out
, len
);
49 int myrand_range(int min
, int max
)
51 return g_pcgrand
.range(min
, max
);
56 64-bit unaligned version of MurmurHash
58 u64
murmur_hash_64_ua(const void *key
, int len
, unsigned int seed
)
60 const u64 m
= 0xc6a4a7935bd1e995ULL
;
62 u64 h
= seed
^ (len
* m
);
64 const u8
*data
= (const u8
*)key
;
65 const u8
*end
= data
+ (len
/ 8) * 8;
69 memcpy(&k
, data
, sizeof(u64
));
80 const unsigned char *data2
= (const unsigned char *)data
;
82 case 7: h
^= (u64
)data2
[6] << 48;
83 case 6: h
^= (u64
)data2
[5] << 40;
84 case 5: h
^= (u64
)data2
[4] << 32;
85 case 4: h
^= (u64
)data2
[3] << 24;
86 case 3: h
^= (u64
)data2
[2] << 16;
87 case 2: h
^= (u64
)data2
[1] << 8;
88 case 1: h
^= (u64
)data2
[0];
100 blockpos_b: position of block in block coordinates
101 camera_pos: position of camera in nodes
102 camera_dir: an unit vector pointing to camera direction
104 distance_ptr: return location for distance from the camera
106 bool isBlockInSight(v3s16 blockpos_b
, v3f camera_pos
, v3f camera_dir
,
107 f32 camera_fov
, f32 range
, f32
*distance_ptr
)
109 // Maximum radius of a block. The magic number is
110 // sqrt(3.0) / 2.0 in literal form.
111 static constexpr const f32 block_max_radius
= 0.866025403784f
* MAP_BLOCKSIZE
* BS
;
113 v3s16 blockpos_nodes
= blockpos_b
* MAP_BLOCKSIZE
;
115 // Block center position
117 ((float)blockpos_nodes
.X
+ MAP_BLOCKSIZE
/2) * BS
,
118 ((float)blockpos_nodes
.Y
+ MAP_BLOCKSIZE
/2) * BS
,
119 ((float)blockpos_nodes
.Z
+ MAP_BLOCKSIZE
/2) * BS
122 // Block position relative to camera
123 v3f blockpos_relative
= blockpos
- camera_pos
;
126 f32 d
= MYMAX(0, blockpos_relative
.getLength() - block_max_radius
);
131 // If block is far away, it's not in sight
135 // If block is (nearly) touching the camera, don't
136 // bother validating further (that is, render it anyway)
140 // Adjust camera position, for purposes of computing the angle,
141 // such that a block that has any portion visible with the
142 // current camera position will have the center visible at the
144 f32 adjdist
= block_max_radius
/ cos((M_PI
- camera_fov
) / 2);
146 // Block position relative to adjusted camera
147 v3f blockpos_adj
= blockpos
- (camera_pos
- camera_dir
* adjdist
);
149 // Distance in camera direction (+=front, -=back)
150 f32 dforward
= blockpos_adj
.dotProduct(camera_dir
);
152 // Cosine of the angle between the camera direction
153 // and the block direction (camera_dir is an unit vector)
154 f32 cosangle
= dforward
/ blockpos_adj
.getLength();
156 // If block is not in the field of view, skip it
157 // HOTFIX: use sligthly increased angle (+10%) to fix too agressive
158 // culling. Somebody have to find out whats wrong with the math here.
159 // Previous value: camera_fov / 2
160 if (cosangle
< std::cos(camera_fov
* 0.55f
))
166 s16
adjustDist(s16 dist
, float zoom_fov
)
168 // 1.775 ~= 72 * PI / 180 * 1.4, the default FOV on the client.
169 // The heuristic threshold for zooming is half of that.
170 static constexpr const float threshold_fov
= 1.775f
/ 2.0f
;
171 if (zoom_fov
< 0.001f
|| zoom_fov
> threshold_fov
)
174 return std::round(dist
* std::cbrt((1.0f
- std::cos(threshold_fov
)) /
175 (1.0f
- std::cos(zoom_fov
/ 2.0f
))));
178 void setPitchYawRollRad(core::matrix4
&m
, const v3f
&rot
)
180 f64 a1
= rot
.Z
, a2
= rot
.X
, a3
= rot
.Y
;
181 f64 c1
= cos(a1
), s1
= sin(a1
);
182 f64 c2
= cos(a2
), s2
= sin(a2
);
183 f64 c3
= cos(a3
), s3
= sin(a3
);
184 f32
*M
= m
.pointer();
186 M
[0] = s1
* s2
* s3
+ c1
* c3
;
188 M
[2] = s1
* s2
* c3
- c1
* s3
;
190 M
[4] = c1
* s2
* s3
- s1
* c3
;
192 M
[6] = c1
* s2
* c3
+ s1
* s3
;
199 v3f
getPitchYawRollRad(const core::matrix4
&m
)
201 const f32
*M
= m
.pointer();
203 f64 a1
= atan2(M
[1], M
[5]);
204 f32 c2
= std::sqrt((f64
)M
[10]*M
[10] + (f64
)M
[8]*M
[8]);
205 f32 a2
= atan2f(-M
[9], c2
);
208 f32 a3
= atan2f(s1
*M
[6] - c1
*M
[2], c1
*M
[0] - s1
*M
[4]);
210 return v3f(a2
, a3
, a1
);