Index: binaries/data/mods/public/maps/random/rmgen/painter/DunePainter.js =================================================================== --- /dev/null +++ binaries/data/mods/public/maps/random/rmgen/painter/DunePainter.js @@ -0,0 +1,64 @@ +/** + * @param {Boolean} type - ELEVATION_MODIFY or ELEVATION_SET. + * @param {Number} scale - Global scale of dune size. + * @param {Number} scaleVertical - Vertical scale of dune size. + * @param {Number} baseHeight - Dunes base altitude if type=ELEVATION_SET. + */ +class DunePainter +{ + constructor(type = ELEVATION_MODIFY, scale = 1, scaleVertical = 1, baseHeight = 0) + { + this.type = type; + this.scale = scale; + this.scaleVertical = scaleVertical; + this.baseHeight = baseHeight; + } + + /** + * Dune shape function. + * @param {Number} x - [0,1] value. + * @param {Number} xCrest - (0,1) position of the dune crest. + * @param {Boolean} dune - True is dune, false is dome. + * @returns {Number} Height of dune at point x + */ + dune(x, xCrest = 0.75, dune = true) + { + return x < xCrest ? (1 - Math.cos(Math.PI * x / xCrest)) * 0.5 : + dune ? (1 - Math.cos(Math.PI * (x - 1) / (xCrest - 1))) * 0.5 : + 1 - Math.cos(Math.PI * (x - 1) / (xCrest - 1) * 0.5); + } + + paint(area) + { + let points = area.getPoints(); + + // 1st dune layer. + let height1_1 = PerlinNoise(points, 6, 2, 1, 1.1, true); + let height1_2 = PerlinNoise(points, 3, 2, 1, 1, true); + // Make big dunes 17 times wider than taller. + let width1 = 17.0 * this.scale; + + // 2nd dune layer. + let height2_1 = PerlinNoise(points, 8, 1, 2, 2, true); + let height2_2 = PerlinNoise(points, 4, 2, 2, 2, true); + // Make smaller dunes 14 times wider than taller. + let width2 = 14.0 * this.scale; + + for (let i = 0; i < points.length; ++i) + { + let x1 = ((points[i].x + height1_1[i] * 13 + points[i].y * 0.1) % width1) / width1; + // Main dunes creation height. + let height1 = this.dune(x1, 0.60, false) * 9 * 0.9 + height1_1[i] * height1_2[i] * 150 * 0.1; + + let x2 = ((points[i].x + height2_1[i] * 13 + points[i].y * 0.1) % width2) / width2; + // Secondary dunes height. + let height2 = this.dune(x2, 0.60, false) * 9 * 0.9 + height2_2[i] * 50 * 0.1; + + let height = (height1 * 0.8 + height2 * 0.2) * this.scaleVertical * this.scale; + + // Add or set height. + let base = this.type ? g_Map.getHeight(points[i]) : baseHeight; + g_Map.setHeight(points[i], base + height); + } + } +}