aboutsummaryrefslogtreecommitdiff
path: root/builtin/common/vector.lua
blob: 0549f9a569c74feb901ffb088093d5185c98b619 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

vector = {}

function vector.new(a, b, c)
	if type(a) == "table" then
		assert(a.x and a.y and a.z, "Invalid vector passed to vector.new()")
		return {x=a.x, y=a.y, z=a.z}
	elseif a then
		assert(b and c, "Invalid arguments for vector.new()")
		return {x=a, y=b, z=c}
	end
	return {x=0, y=0, z=0}
end

function vector.equals(a, b)
	return a.x == b.x and
	       a.y == b.y and
	       a.z == b.z
end

function vector.length(v)
	return math.hypot(v.x, math.hypot(v.y, v.z))
end

function vector.normalize(v)
	local len = vector.length(v)
	if len == 0 then
		return {x=0, y=0, z=0}
	else
		return vector.divide(v, len)
	end
end

function vector.floor(v)
	return {
		x = math.floor(v.x),
		y = math.floor(v.y),
		z = math.floor(v.z)
	}
end

function vector.round(v)
	return {
		x = math.floor(v.x + 0.5),
		y = math.floor(v.y + 0.5),
		z = math.floor(v.z + 0.5)
	}
end

function vector.apply(v, func)
	return {
		x = func(v.x),
		y = func(v.y),
		z = func(v.z)
	}
end

function vector.distance(a, b)
	local x = a.x - b.x
	local y = a.y - b.y
	local z = a.z - b.z
	return math.hypot(x, math.hypot(y, z))
end

function vector.direction(pos1, pos2)
	local x_raw = pos2.x - pos1.x
	local y_raw = pos2.y - pos1.y
	local z_raw = pos2.z - pos1.z
	local x_abs = math.abs(x_raw)
	local y_abs = math.abs(y_raw)
	local z_abs = math.abs(z_raw)
	if x_abs >= y_abs and
	   x_abs >= z_abs then
		y_raw = y_raw * (1 / x_abs)
		z_raw = z_raw * (1 / x_abs)
		x_raw = x_raw / x_abs
	end
	if y_abs >= x_abs and
	   y_abs >= z_abs then
		x_raw = x_raw * (1 / y_abs)
		z_raw = z_raw * (1 / y_abs)
		y_raw = y_raw / y_abs
	end
	if z_abs >= y_abs and
	   z_abs >= x_abs then
		x_raw = x_raw * (1 / z_abs)
		y_raw = y_raw * (1 / z_abs)
		z_raw = z_raw / z_abs
	end
	return {x=x_raw, y=y_raw, z=z_raw}
end


function vector.add(a, b)
	if type(b) == "table" then
		return {x = a.x + b.x,
			y = a.y + b.y,
			z = a.z + b.z}
	else
		return {x = a.x + b,
			y = a.y + b,
			z = a.z + b}
	end
end

function vector.subtract(a, b)
	if type(b) == "table" then
		return {x = a.x - b.x,
			y = a.y - b.y,
			z = a.z - b.z}
	else
		return {x = a.x - b,
			y = a.y - b,
			z = a.z - b}
	end
end

function vector.multiply(a, b)
	if type(b) == "table" then
		return {x = a.x * b.x,
			y = a.y * b.y,
			z = a.z * b.z}
	else
		return {x = a.x * b,
			y = a.y * b,
			z = a.z * b}
	end
end

function vector.divide(a, b)
	if type(b) == "table" then
		return {x = a.x / b.x,
			y = a.y / b.y,
			z = a.z / b.z}
	else
		return {x = a.x / b,
			y = a.y / b,
			z = a.z / b}
	end
end

function vector.sort(a, b)
	return {x = math.min(a.x, b.x), y = math.min(a.y, b.y), z = math.min(a.z, b.z)},
		{x = math.max(a.x, b.x), y = math.max(a.y, b.y), z = math.max(a.z, b.z)}
end
an class="hl num">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++) { m_cache[d].push_back(v3s16(d,y,z)); m_cache[d].push_back(v3s16(-d,y,z)); if(y != 0) { m_cache[d].push_back(v3s16(d,-y,z)); m_cache[d].push_back(v3s16(-d,-y,z)); } } // Back and front side, excluding borders for(s16 x=-d+1; x<=d-1; x++) { m_cache[d].push_back(v3s16(x,y,d)); m_cache[d].push_back(v3s16(x,y,-d)); if(y != 0) { m_cache[d].push_back(v3s16(x,-y,d)); m_cache[d].push_back(v3s16(x,-y,-d)); } } } // 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++) { m_cache[d].push_back(v3s16(x,-d,z)); m_cache[d].push_back(v3s16(x,d,z)); } } /* myrand */ PcgRandom g_pcgrand; u32 myrand() { return g_pcgrand.next(); } void mysrand(unsigned int seed) { g_pcgrand.seed(seed); } void myrand_bytes(void *out, size_t len) { g_pcgrand.bytes(out, len); } int myrand_range(int min, int max) { return g_pcgrand.range(min, max); } /* 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 camera_dir: an unit vector pointing to camera direction range: viewing range */ bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 camera_fov, f32 range, f32 *distance_ptr) { v3s16 blockpos_nodes = blockpos_b * MAP_BLOCKSIZE; // Block center position v3f blockpos( ((float)blockpos_nodes.X + MAP_BLOCKSIZE/2) * BS, ((float)blockpos_nodes.Y + MAP_BLOCKSIZE/2) * BS, ((float)blockpos_nodes.Z + MAP_BLOCKSIZE/2) * BS ); // Block position relative to camera v3f blockpos_relative = blockpos - camera_pos; // Total distance f32 d = blockpos_relative.getLength(); 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) 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 / blockpos_adj.getLength(); // If block is not in the field of view, skip it if(cosangle < cos(camera_fov / 2)) return false; return true; }