diff --git a/geometry.lua b/geometry.lua deleted file mode 100644 index 26b2214..0000000 --- a/geometry.lua +++ /dev/null @@ -1,40 +0,0 @@ -local sqrt, abs = math.sqrt, math.abs -local unpk = unpack - -local function distance_to_segment(x1, y1, x2, y2, x, y) - -- get the distance between point (x,y) and segment (x1,y1)-(x2,y2) - local a = (x1-x2)^2 + (y1-y2)^2 -- square of distance - local b = (x1-x)^2 + (y1-y)^2 - local c = (x2-x)^2 + (y2-y)^2 - if a + b < c then - -- The closest point of the segment is the extremity 1 - return sqrt(b) - elseif a + c < b then - -- The closest point of the segment is the extremity 2 - return sqrt(c) - else - -- The closest point is on the segment - return abs(x1 * (y2-y) + x2 * (y-y1) + x * (y1-y2)) / sqrt(a) - end -end - -local function transform_quadri(X, Y, x, y) - -- To index points in an irregular quadrilateral, giving x and y between 0 (one edge) and 1 (opposite edge) - -- X, Y 4-vectors giving the coordinates of the 4 vertices - -- x, y position to index. - local x1, x2, x3, x4 = unpk(X) - local y1, y2, y3, y4 = unpk(Y) - - -- Compare distance to 2 opposite edges, they give the X coordinate - local d23 = distance_to_segment(x2,y2,x3,y3,x,y) - local d41 = distance_to_segment(x4,y4,x1,y1,x,y) - local xc = d41 / (d23+d41) - - -- Same for the 2 other edges, they give the Y coordinate - local d12 = distance_to_segment(x1,y1,x2,y2,x,y) - local d34 = distance_to_segment(x3,y3,x4,y4,x,y) - local yc = d12 / (d12+d34) - return xc, yc -end - -return transform_quadri diff --git a/heightmap.lua b/heightmap.lua index 3532818..97fbd0b 100644 --- a/heightmap.lua +++ b/heightmap.lua @@ -1,16 +1,51 @@ local modpath = mapgen_rivers.modpath -local transform_quadri = dofile(modpath .. 'geometry.lua') - local sea_level = mapgen_rivers.settings.sea_level local riverbed_slope = mapgen_rivers.settings.riverbed_slope * mapgen_rivers.settings.blocksize local out_elev = mapgen_rivers.settings.margin_elev -- Localize for performance -local floor, min, max = math.floor, math.min, math.max +local floor, min, max, sqrt, abs = math.floor, math.min, math.max, math.sqrt, math.abs local unpk = unpack +-- Geometrical helpers +local function distance_to_segment(x1, y1, x2, y2, x, y) + -- get the distance between point (x,y) and segment (x1,y1)-(x2,y2) + local a = (x1-x2)^2 + (y1-y2)^2 -- square of distance + local b = (x1-x)^2 + (y1-y)^2 + local c = (x2-x)^2 + (y2-y)^2 + if a + b < c then + -- The closest point of the segment is the extremity 1 + return sqrt(b) + elseif a + c < b then + -- The closest point of the segment is the extremity 2 + return sqrt(c) + else + -- The closest point is on the segment + return abs(x1 * (y2-y) + x2 * (y-y1) + x * (y1-y2)) / sqrt(a) + end +end + +local function transform_quadri(X, Y, x, y) + -- To index points in an irregular quadrilateral, giving x and y between 0 (one edge) and 1 (opposite edge) + -- X, Y 4-vectors giving the coordinates of the 4 vertices + -- x, y position to index. + local x1, x2, x3, x4 = unpk(X) + local y1, y2, y3, y4 = unpk(Y) + + -- Compare distance to 2 opposite edges, they give the X coordinate + local d23 = distance_to_segment(x2,y2,x3,y3,x,y) + local d41 = distance_to_segment(x4,y4,x1,y1,x,y) + local xc = d41 / (d23+d41) + + -- Same for the 2 other edges, they give the Y coordinate + local d12 = distance_to_segment(x1,y1,x2,y2,x,y) + local d34 = distance_to_segment(x3,y3,x4,y4,x,y) + local yc = d12 / (d12+d34) + return xc, yc +end + -- Linear interpolation local function interp(v00, v01, v11, v10, xf, zf) local v0 = v01*xf + v00*(1-xf)