From 4a55c6db7b4687ebafbaa38d0b3dfa4884b2fe00 Mon Sep 17 00:00:00 2001 From: sys4-fr Date: Sat, 8 Sep 2018 23:15:32 +0200 Subject: [PATCH] Version MFF. --- .gitignore | 0 LICENSE.txt | 1 + README.txt | 2 +- init.lua | 370 +++++++++++++++++++++++++++++++++++++++++++++--- vector_meta.lua | 6 +- 5 files changed, 352 insertions(+), 27 deletions(-) mode change 100644 => 100755 .gitignore create mode 100644 LICENSE.txt mode change 100644 => 100755 README.txt mode change 100644 => 100755 init.lua mode change 100644 => 100755 vector_meta.lua diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..bc0b1db --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1 @@ +WTFPL diff --git a/README.txt b/README.txt old mode 100644 new mode 100755 index fe5b6b1..fbae6ae --- a/README.txt +++ b/README.txt @@ -1,2 +1,2 @@ TODO: -— add things to this list +— maybe make the explosion table function return a perlin explosion table diff --git a/init.lua b/init.lua old mode 100644 new mode 100755 index 255f84d..aeb2172 --- a/init.lua +++ b/init.lua @@ -1,6 +1,8 @@ local load_time_start = os.clock() -function vector.pos_to_string(pos) +local funcs = {} + +function funcs.pos_to_string(pos) return "("..pos.x.."|"..pos.y.."|"..pos.z..")" end @@ -118,7 +120,7 @@ local function return_fine_line(pos, dir, range, scale) return ps2 end -function vector.fine_line(pos, dir, range, scale) +function funcs.fine_line(pos, dir, range, scale) --assert_vector(pos) if not range then --dir = pos2 dir = vector.direction(pos, dir) @@ -127,7 +129,7 @@ function vector.fine_line(pos, dir, range, scale) return return_fine_line(pos, dir, range, scale) end -function vector.line(pos, dir, range, alt) +function funcs.line(pos, dir, range, alt) --assert_vector(pos) if alt then if not range then --dir = pos2 @@ -149,7 +151,7 @@ function vector.line(pos, dir, range, alt) end local twolines = {} -function vector.twoline(x, y) +function funcs.twoline(x, y) local pstr = x.." "..y local line = twolines[pstr] if line then @@ -183,14 +185,14 @@ function vector.twoline(x, y) end local threelines = {} -function vector.threeline(x, y, z) +function funcs.threeline(x, y, z) local pstr = x.." "..y.." "..z local line = threelines[pstr] if line then return line end if x ~= math.floor(x) then - print("[vector_extras] INFO: The position used for vector.threeline isn't round.") + minetest.log("error", "[vector_extras] INFO: The position used for vector.threeline isn't round.") end local two_line = vector.twoline(x, y) line = {} @@ -218,16 +220,104 @@ function vector.threeline(x, y, z) return line end -function vector.straightdelay(s, v, a) +function funcs.sort(ps, preferred_coords) + preferred_coords = preferred_coords or {"z", "y", "x"} + local a,b,c = unpack(preferred_coords) + local function ps_sorting(p1, p2) + if p1[a] == p2[a] then + if p1[b] == p2[a] then + if p1[c] < p2[c] then + return true + end + elseif p1[b] < p2[b] then + return true + end + elseif p1[a] < p2[a] then + return true + end + end + table.sort(ps, ps_sorting) +end + +function funcs.scalar(v1, v2) + return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z +end + +function funcs.cross(v1, v2) + return { + x = v1.y*v2.z - v1.z*v2.y, + y = v1.z*v2.x - v1.x*v2.z, + z = v1.x*v2.y - v1.y*v2.x + } +end + +--not optimized +--local areas = {} +function funcs.plane(ps) + -- sort positions and imagine the first one (A) as vector.zero + ps = vector.sort(ps) + local pos = ps[1] + local B = vector.subtract(ps[2], pos) + local C = vector.subtract(ps[3], pos) + + -- get the positions for the fors + local cube_p1 = {x=0, y=0, z=0} + local cube_p2 = {x=0, y=0, z=0} + for i in pairs(cube_p1) do + cube_p1[i] = math.min(B[i], C[i], 0) + cube_p2[i] = math.max(B[i], C[i], 0) + end + cube_p1 = vector.apply(cube_p1, math.floor) + cube_p2 = vector.apply(cube_p2, math.ceil) + + local vn = vector.normalize(vector.cross(B, C)) + + local nAB = vector.normalize(B) + local nAC = vector.normalize(C) + local angle_BAC = math.acos(vector.scalar(nAB, nAC)) + + local nBA = vector.multiply(nAB, -1) + local nBC = vector.normalize(vector.subtract(C, B)) + local angle_ABC = math.acos(vector.scalar(nBA, nBC)) + + for z = cube_p1.z, cube_p2.z do + for y = cube_p1.y, cube_p2.y do + for x = cube_p1.x, cube_p2.x do + local p = {x=x, y=y, z=z} + local n = -vector.scalar(p, vn)/vector.scalar(vn, vn) + if math.abs(n) <= 0.5 then + local ep = vector.add(p, vector.multiply(vn, n)) + local nep = vector.normalize(ep) + local angle_BAep = math.acos(vector.scalar(nAB, nep)) + local angle_CAep = math.acos(vector.scalar(nAC, nep)) + local angldif = angle_BAC - (angle_BAep+angle_CAep) + if math.abs(angldif) < 0.001 then + ep = vector.subtract(ep, B) + nep = vector.normalize(ep) + local angle_ABep = math.acos(vector.scalar(nBA, nep)) + local angle_CBep = math.acos(vector.scalar(nBC, nep)) + local angldif = angle_ABC - (angle_ABep+angle_CBep) + if math.abs(angldif) < 0.001 then + table.insert(ps, vector.add(pos, p)) + end + end + end + end + end + end + return ps +end + +function funcs.straightdelay(s, v, a) if not a then return s/v end return (math.sqrt(v*v+2*a*s)-v)/a end -vector.zero = {x=0, y=0, z=0} +vector.zero = vector.new() -function vector.sun_dir(time) +function funcs.sun_dir(time) if not time then time = minetest.get_timeofday() end @@ -240,8 +330,8 @@ function vector.sun_dir(time) return {x=tmp, y=math.sqrt(1-tmp*tmp), z=0} end -function vector.inside(pos, minp, maxp) - for _,i in ipairs({"x", "y", "z"}) do +function funcs.inside(pos, minp, maxp) + for _,i in pairs({"x", "y", "z"}) do if pos[i] < minp[i] or pos[i] > maxp[i] then return false @@ -250,8 +340,8 @@ function vector.inside(pos, minp, maxp) return true end -function vector.minmax(p1, p2) - local p1 = vector.new(p1) --Are these 2 redefinitions necessary? +function funcs.minmax(p1, p2) + local p1 = vector.new(p1) local p2 = vector.new(p2) for _,i in ipairs({"x", "y", "z"}) do if p1[i] > p2[i] then @@ -261,7 +351,7 @@ function vector.minmax(p1, p2) return p1, p2 end -function vector.move(p1, p2, s) +function funcs.move(p1, p2, s) return vector.round( vector.add( vector.multiply( @@ -276,8 +366,12 @@ function vector.move(p1, p2, s) ) end +function funcs.from_number(i) + return {x=i, y=i, z=i} +end + local explosion_tables = {} -function vector.explosion_table(r) +function funcs.explosion_table(r) local table = explosion_tables[r] if table then return table @@ -290,7 +384,7 @@ function vector.explosion_table(r) for x=-r,r do for y=-r,r do for z=-r,r do - local rc = x*x+y*y+z*z + local rc = x*x+y*y+z*z if rc <= tmp then local np={x=x, y=y, z=z} if math.floor(math.sqrt(rc) +0.5) > r-1 then @@ -304,12 +398,96 @@ function vector.explosion_table(r) end end explosion_tables[r] = tab - print(string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) + minetest.log("info", string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) + return tab +end + +local default_nparams = { + offset = 0, + scale = 1, + seed = 1337, + octaves = 6, + persist = 0.6 +} +function funcs.explosion_perlin(rmin, rmax, nparams) + local t1 = os.clock() + + local r = math.ceil(rmax) + nparams = nparams or {} + for i,v in pairs(default_nparams) do + nparams[i] = nparams[i] or v + end + nparams.spread = nparams.spread or vector.from_number(r*5) + + local pos = {x=math.random(-30000, 30000), y=math.random(-30000, 30000), z=math.random(-30000, 30000)} + local map = minetest.get_perlin_map(nparams, vector.from_number(r+r+1)):get3dMap_flat(pos) + + local id = 1 + + local bare_maxdist = rmax*rmax + local bare_mindist = rmin*rmin + + local mindist = math.sqrt(bare_mindist) + local dist_diff = math.sqrt(bare_maxdist)-mindist + mindist = mindist/dist_diff + + local pval_min, pval_max + + local tab, n = {}, 1 + for z=-r,r do + local bare_dist = z*z + for y=-r,r do + local bare_dist = bare_dist+y*y + for x=-r,r do + local bare_dist = bare_dist+x*x + local add = bare_dist < bare_mindist + local pval, distdiv + if not add + and bare_dist <= bare_maxdist then + distdiv = math.sqrt(bare_dist)/dist_diff-mindist + pval = math.abs(map[id]) -- strange perlin values… + if not pval_min then + pval_min = pval + pval_max = pval + else + pval_min = math.min(pval, pval_min) + pval_max = math.max(pval, pval_max) + end + add = true--distdiv < 1-math.abs(map[id]) + end + + if add then + tab[n] = {{x=x, y=y, z=z}, pval, distdiv} + n = n+1 + end + id = id+1 + end + end + end + + -- change strange values + local pval_diff = pval_max - pval_min + pval_min = pval_min/pval_diff + + for n,i in pairs(tab) do + if i[2] then + local new_pval = math.abs(i[2]/pval_diff - pval_min) + if i[3]+0.33 < new_pval then + tab[n] = {i[1]} + elseif i[3] < new_pval then + tab[n] = {i[1], true} + else + tab[n] = nil + end + end + end + + minetest.log("info", string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) return tab end local circle_tables = {} -function vector.circle(r) +function funcs.circle(r) local table = circle_tables[r] if table then return table @@ -327,12 +505,12 @@ function vector.circle(r) end end circle_tables[r] = tab - print(string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) + minetest.log("info", string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) return tab end local ring_tables = {} -function vector.ring(r) +function funcs.ring(r) local table = ring_tables[r] if table then return table @@ -369,14 +547,160 @@ function vector.ring(r) end end ring_tables[r] = tab2 - print(string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) + minetest.log("info", string.format("[vector_extras] table created after ca. %.2fs", os.clock() - t1)) return tab2 end -function vector.chunkcorner(pos) +function funcs.chunkcorner(pos) return {x=pos.x-pos.x%16, y=pos.y-pos.y%16, z=pos.z-pos.z%16} end +function funcs.point_distance_minmax(p1, p2) + local p1 = vector.new(p1) + local p2 = vector.new(p2) + local min, max, vmin, vmax, num + for _,i in ipairs({"x", "y", "z"}) do + num = math.abs(p1[i] - p2[i]) + if not vmin or num < vmin then + vmin = num + min = i + end + if not vmax or num > vmax then + vmax = num + max = i + end + end + return min, max +end + +function funcs.collision(p1, p2) + local clear, node_pos, collision_pos, max, min, dmax, dcmax, pt + clear, node_pos = minetest.line_of_sight(p1, p2) + if clear then + return false + end + collision_pos = {} + min, max = funcs.point_distance_minmax(node_pos, p2) + if node_pos[max] > p2[max] then + collision_pos[max] = node_pos[max] - 0.5 + else + collision_pos[max] = node_pos[max] + 0.5 + end + dmax = p2[max] - node_pos[max] + dcmax = p2[max] - collision_pos[max] + pt = dcmax/dmax + + for _,i in ipairs({"x", "y", "z"}) do + collision_pos[i] = p2[i] - (p2[i] - node_pos[i]) * pt + end + return true, collision_pos, node_pos +end + +function funcs.get_data_from_pos(tab, z,y,x) + local data = tab[z] + if data then + data = data[y] + if data then + return data[x] + end + end +end + +function funcs.set_data_to_pos(tab, z,y,x, data) + if tab[z] then + if tab[z][y] then + tab[z][y][x] = data + return + end + tab[z][y] = {[x] = data} + return + end + tab[z] = {[y] = {[x] = data}} +end + +function funcs.set_data_to_pos_optional(tab, z,y,x, data) + if vector.get_data_from_pos(tab, z,y,x) ~= nil then + return + end + funcs.set_data_to_pos(tab, z,y,x, data) +end + +function funcs.remove_data_from_pos(tab, z,y,x) + if vector.get_data_from_pos(tab, z,y,x) == nil then + return + end + tab[z][y][x] = nil + if not next(tab[z][y]) then + tab[z][y] = nil + end + if not next(tab[z]) then + tab[z] = nil + end +end + +function funcs.get_data_pos_table(tab) + local t,n = {},1 + local minz, miny, minx, maxz, maxy, maxx + for z,yxs in pairs(tab) do + if not minz then + minz = z + maxz = z + else + minz = math.min(minz, z) + maxz = math.max(maxz, z) + end + for y,xs in pairs(yxs) do + if not miny then + miny = y + maxy = y + else + miny = math.min(miny, y) + maxy = math.max(maxy, y) + end + for x,v in pairs(xs) do + if not minx then + minx = x + maxx = x + else + minx = math.min(minx, x) + maxx = math.max(maxx, x) + end + t[n] = {z,y,x, v} + n = n+1 + end + end + end + return t, {x=minx, y=miny, z=minz}, {x=maxx, y=maxy, z=maxz}, n-1 +end + +function funcs.update_minp_maxp(minp, maxp, pos) + for _,i in pairs({"z", "y", "x"}) do + minp[i] = math.min(minp[i], pos[i]) + maxp[i] = math.max(maxp[i], pos[i]) + end +end + +function funcs.quickadd(pos, z,y,x) + if z then + pos.z = pos.z+z + end + if y then + pos.y = pos.y+y + end + if x then + pos.x = pos.x+x + end +end + +function funcs.unpack(pos) + return pos.z, pos.y, pos.x +end + + dofile(minetest.get_modpath("vector_extras").."/vector_meta.lua") -print(string.format("[vector_extras] loaded after ca. %.2fs", os.clock() - load_time_start)) +for name,func in pairs(funcs) do + vector[name] = vector[name] or func +end + +minetest.log("info", string.format("[vector_extras] loaded after ca. %.2fs", os.clock() - load_time_start)) diff --git a/vector_meta.lua b/vector_meta.lua old mode 100644 new mode 100755 index d9606cd..b4ed291 --- a/vector_meta.lua +++ b/vector_meta.lua @@ -3,12 +3,12 @@ vector.meta.nodes = {} vector.meta.nodes_file = { load = function() - local nodesfile = io.open(minetest.get_worldpath()..'/vector_nodes.txt', "r") + local nodesfile = io.open(minetest.get_worldpath()..'/vector_nodes.txt', "r") if nodesfile then local contents = nodesfile:read('*all') io.close(nodesfile) - if contents ~= nil then - local lines = string.split(contents, "\n") + if contents ~= nil then + local lines = string.split(contents, "\n") for _,entry in ipairs(lines) do local name, px, py, pz, meta = unpack(string.split(entry, "°")) vector.meta.set_node({x=px, y=py, z=pz}, name, meta)