mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-18 02:01:22 +01:00
refactor: grid generation
This commit is contained in:
parent
d18636eb8f
commit
e59b536e83
15 changed files with 157 additions and 105 deletions
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,10 +125,8 @@ window.Submap = (function () {
|
|||
OceanLayers(grid);
|
||||
|
||||
calculateMapCoordinates();
|
||||
// calculateTemperatures();
|
||||
// generatePrecipitation();
|
||||
stage("Cell cleanup.");
|
||||
reGraph();
|
||||
reGraph(grid);
|
||||
|
||||
// remove misclassified cells
|
||||
stage("Define coastline.");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
47
src/modules/temperature.ts
Normal file
47
src/modules/temperature.ts
Normal 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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue