refactor: grid generation

This commit is contained in:
Azgaar 2022-07-11 01:38:55 +03:00
parent d18636eb8f
commit e59b536e83
15 changed files with 157 additions and 105 deletions

View file

@ -399,7 +399,7 @@ async function parseLoadedData(data) {
})();
void (function parsePackData() {
reGraph();
reGraph(grid);
reMarkFeatures();
pack.features = JSON.parse(data[12]);
pack.cultures = JSON.parse(data[13]);

View file

@ -7,7 +7,7 @@ import {aleaPRNG} from "scripts/aleaPRNG";
const {UNMARKED, LAND_COAST, WATER_COAST} = DISTANCE_FIELD;
// define features (grid.features: ocean, lakes, islands) and calculate distance field (cells.t)
export function markupGridFeatures(grid: IGraph & {cells: {h: UintArray}}) {
export function markupGridFeatures(grid: IGridWithHeights) {
TIME && console.time("markupGridFeatures");
Math.random = aleaPRNG(seed); // get the same result on heightmap edit in Erase mode
@ -173,8 +173,10 @@ export function reMarkFeatures() {
return "gulf";
}
function defineIslandGroup(cell, number) {
if (cell && features[cells.f[cell - 1]].type === "lake") return "lake_island";
function defineIslandGroup(cellId: number, number: number) {
const prevCellFeature = features[cells.f[cellId - 1]];
if (cellId && prevCellFeature && prevCellFeature.type === "lake") return "lake_island";
if (number > grid.cells.i.length / 10) return "continent";
if (number > grid.cells.i.length / 1000) return "island";
return "isle";

View file

@ -5,11 +5,12 @@ import {minmax} from "utils/numberUtils";
import {rand} from "utils/probabilityUtils";
// simplest precipitation model
export function generatePrecipitation() {
export function generatePrecipitation(grid) {
TIME && console.time("generatePrecipitation");
prec.selectAll("*").remove();
const {cells, cellsX, cellsY} = grid;
cells.prec = new Uint8Array(cells.i.length); // precipitation array
const precipitation = new Uint8Array(cells.i.length); // precipitation array
const cellsNumberModifier = (pointsInput.dataset.cells / 10000) ** 0.25;
const precInputModifier = precInput.value / 100;
@ -94,20 +95,20 @@ export function generatePrecipitation() {
if (cells.h[current] < 20) {
// water cell
if (cells.h[current + next] >= 20) {
cells.prec[current + next] += Math.max(humidity / rand(10, 20), 1); // coastal precipitation
precipitation[current + next] += Math.max(humidity / rand(10, 20), 1); // coastal precipitation
} else {
humidity = Math.min(humidity + 5 * modifier, maxPrec); // wind gets more humidity passing water cell
cells.prec[current] += 5 * modifier; // water cells precipitation (need to correctly pour water through lakes)
precipitation[current] += 5 * modifier; // water cells precipitation (need to correctly pour water through lakes)
}
continue;
}
// land cell
const isPassable = cells.h[current + next] <= MAX_PASSABLE_ELEVATION;
const precipitation = isPassable ? getPrecipitation(humidity, current, next) : humidity;
cells.prec[current] += precipitation;
const evaporation = precipitation > 1.5 ? 1 : 0; // some humidity evaporates back to the atmosphere
humidity = isPassable ? minmax(humidity - precipitation + evaporation, 0, maxPrec) : 0;
const cellPrec = isPassable ? getPrecipitation(humidity, current, next) : humidity;
precipitation[current] += cellPrec;
const evaporation = cellPrec > 1.5 ? 1 : 0; // some humidity evaporates back to the atmosphere
humidity = isPassable ? minmax(humidity - cellPrec + evaporation, 0, maxPrec) : 0;
}
}
}
@ -162,4 +163,5 @@ export function generatePrecipitation() {
})();
TIME && console.timeEnd("generatePrecipitation");
return precipitation;
}

View file

@ -125,10 +125,8 @@ window.Submap = (function () {
OceanLayers(grid);
calculateMapCoordinates();
// calculateTemperatures();
// generatePrecipitation();
stage("Cell cleanup.");
reGraph();
reGraph(grid);
// remove misclassified cells
stage("Define coastline.");

View file

@ -1,35 +0,0 @@
import * as d3 from "d3";
import {TIME} from "config/logging";
import {minmax, rn} from "utils/numberUtils";
// temperature model
export function calculateTemperatures() {
TIME && console.time("calculateTemperatures");
const cells = grid.cells;
cells.temp = new Int8Array(cells.i.length); // temperature array
const tEq = +temperatureEquatorInput.value;
const tPole = +temperaturePoleInput.value;
const tDelta = tEq - tPole;
const int = d3.easePolyInOut.exponent(0.5); // interpolation function
d3.range(0, cells.i.length, grid.cellsX).forEach(function (r) {
const y = grid.points[r][1];
const lat = Math.abs(mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT); // [0; 90]
const initTemp = tEq - int(lat / 90) * tDelta;
for (let i = r; i < r + grid.cellsX; i++) {
cells.temp[i] = minmax(initTemp - convertToFriendly(cells.h[i]), -128, 127);
}
});
// temperature decreases by 6.5 degree C per 1km
function convertToFriendly(h) {
if (h < 20) return 0;
const exponent = +heightExponentInput.value;
const height = Math.pow(h - 18, exponent);
return rn((height / 1000) * 6.5);
}
TIME && console.timeEnd("calculateTemperatures");
}

View file

@ -0,0 +1,47 @@
import * as d3 from "d3";
import {TIME} from "config/logging";
import {minmax} from "utils/numberUtils";
import {getInputNumber} from "utils/nodeUtils";
import {MIN_LAND_HEIGHT} from "config/generation";
const interpolate = d3.easePolyInOut.exponent(0.5); // interpolation function
export function calculateTemperatures(grid: IGridWithHeights) {
TIME && console.time("calculateTemperatures");
const {cells, cellsX, points} = grid;
const heights = cells.h;
const temperatures = new Int8Array(heights.length); // temperature array
// temperature decreases by 6.5 Celsius per kilometer
const heightExponent = getInputNumber("heightExponentInput");
function decreaseTempFromElevation(height: number) {
if (height < MIN_LAND_HEIGHT) return 0;
const realHeight = Math.pow(height - 18, heightExponent);
return (realHeight / 1000) * 6.5;
}
const tEq = getInputNumber("temperatureEquatorInput");
const tPole = getInputNumber("temperaturePoleInput");
const tDelta = tEq - tPole;
const {latN, latT} = window.mapCoordinates;
d3.range(0, heights.length, cellsX).forEach(rowStart => {
const y = points[rowStart][1];
const lat = Math.abs(latN - (y / graphHeight) * latT); // [0; 90]
const initTemp = tEq - interpolate(lat / 90) * tDelta;
for (let i = rowStart; i < rowStart + cellsX; i++) {
const elevationDecrease = decreaseTempFromElevation(heights[i]);
temperatures[i] = minmax(initTemp - elevationDecrease, -128, 127);
}
});
TIME && console.timeEnd("calculateTemperatures");
return temperatures;
}

View file

@ -60,8 +60,8 @@ export function editWorld() {
updateGlobeTemperature();
updateGlobePosition();
calculateTemperatures();
generatePrecipitation();
calculateTemperatures(grid);
generatePrecipitation(grid);
const heights = new Uint8Array(pack.cells.h);
Rivers.generate();
Lakes.defineGroup();