mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
refactor: rivers generation
This commit is contained in:
parent
c1e7d6f54a
commit
3215b6f0d2
18 changed files with 739 additions and 704 deletions
|
|
@ -1,144 +0,0 @@
|
|||
import * as d3 from "d3";
|
||||
|
||||
// @ts-expect-error js module
|
||||
import {drawCoastline} from "layers/renderers/drawCoastline";
|
||||
import {markupPackFeatures} from "modules/markup";
|
||||
// @ts-expect-error js module
|
||||
import {drawScaleBar} from "modules/measurers";
|
||||
// @ts-expect-error js module
|
||||
import {addZones} from "modules/zones";
|
||||
import {DISTANCE_FIELD, MIN_LAND_HEIGHT} from "config/generation";
|
||||
import {TIME} from "config/logging";
|
||||
import {UINT16_MAX} from "constants";
|
||||
import {calculateVoronoi} from "scripts/generation/graph";
|
||||
import {createTypedArray} from "utils/arrayUtils";
|
||||
import {pick} from "utils/functionUtils";
|
||||
import {rn} from "utils/numberUtils";
|
||||
|
||||
const {LAND_COAST, WATER_COAST, DEEPER_WATER} = DISTANCE_FIELD;
|
||||
const {Lakes, OceanLayers, Rivers, Biomes, Cultures, BurgsAndStates, Religions, Military, Markers, Names} = window;
|
||||
|
||||
export function createPack(grid: IGrid): IPack {
|
||||
const {vertices, cells} = repackGrid(grid);
|
||||
|
||||
const markup = markupPackFeatures(grid, vertices, pick(cells, "v", "c", "b", "p", "h"));
|
||||
const {features, featureIds, distanceField, haven, harbor} = markup;
|
||||
|
||||
Rivers.generate(
|
||||
grid.cells.prec,
|
||||
grid.cells.temp,
|
||||
pick({...cells, f: featureIds, t: distanceField, haven}, "i", "c", "b", "g", "t", "h", "f", "haven"),
|
||||
features,
|
||||
true
|
||||
);
|
||||
|
||||
// Lakes.defineGroup(newPack);
|
||||
// Biomes.define(newPack, grid);
|
||||
|
||||
// const rankCellsData = pick(newPack.cells, "i", "f", "fl", "conf", "r", "h", "area", "biome", "haven", "harbor");
|
||||
// rankCells(newPack.features!, rankCellsData);
|
||||
|
||||
// Cultures.generate();
|
||||
// Cultures.expand();
|
||||
// BurgsAndStates.generate();
|
||||
// Religions.generate();
|
||||
// BurgsAndStates.defineStateForms();
|
||||
// BurgsAndStates.generateProvinces();
|
||||
// BurgsAndStates.defineBurgFeatures();
|
||||
|
||||
// renderLayer("states");
|
||||
// renderLayer("borders");
|
||||
// BurgsAndStates.drawStateLabels();
|
||||
|
||||
// Rivers.specify();
|
||||
// Lakes.generateName();
|
||||
|
||||
// Military.generate();
|
||||
// Markers.generate();
|
||||
// addZones();
|
||||
|
||||
// OceanLayers(newGrid);
|
||||
|
||||
// drawScaleBar(window.scale);
|
||||
// Names.getMapName();
|
||||
|
||||
const pack: IPack = {
|
||||
vertices,
|
||||
cells: {
|
||||
...cells,
|
||||
f: featureIds,
|
||||
t: distanceField,
|
||||
haven,
|
||||
harbor
|
||||
},
|
||||
features
|
||||
};
|
||||
|
||||
return pack;
|
||||
}
|
||||
|
||||
// repack grid cells: discart deep water cells, add land cells along the coast
|
||||
function repackGrid(grid: IGrid) {
|
||||
TIME && console.time("repackGrid");
|
||||
const {cells: gridCells, points, features} = grid;
|
||||
const newCells: {p: TPoints; g: number[]; h: number[]} = {p: [], g: [], h: []}; // store new data
|
||||
const spacing2 = grid.spacing ** 2;
|
||||
|
||||
for (const i of gridCells.i) {
|
||||
const height = gridCells.h[i];
|
||||
const type = gridCells.t[i];
|
||||
if (height < MIN_LAND_HEIGHT && type !== WATER_COAST && type !== DEEPER_WATER) continue; // exclude all deep ocean points
|
||||
|
||||
const feature = features[gridCells.f[i]];
|
||||
const isLake = feature && feature.type === "lake";
|
||||
|
||||
if (type === DEEPER_WATER && (i % 4 === 0 || isLake)) continue; // exclude non-coastal lake points
|
||||
const [x, y] = points[i];
|
||||
|
||||
addNewPoint(i, x, y, height);
|
||||
|
||||
// add additional points for cells along coast
|
||||
if (type === LAND_COAST || type === WATER_COAST) {
|
||||
if (gridCells.b[i]) continue; // not for near-border cells
|
||||
gridCells.c[i].forEach(e => {
|
||||
if (i > e) return;
|
||||
if (gridCells.t[e] === type) {
|
||||
const dist2 = (y - points[e][1]) ** 2 + (x - points[e][0]) ** 2;
|
||||
if (dist2 < spacing2) return; // too close to each other
|
||||
const x1 = rn((x + points[e][0]) / 2, 1);
|
||||
const y1 = rn((y + points[e][1]) / 2, 1);
|
||||
addNewPoint(i, x1, y1, height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addNewPoint(i: number, x: number, y: number, height: number) {
|
||||
newCells.p.push([x, y]);
|
||||
newCells.g.push(i);
|
||||
newCells.h.push(height);
|
||||
}
|
||||
|
||||
const {cells, vertices} = calculateVoronoi(newCells.p, grid.boundary);
|
||||
|
||||
function getCellArea(i: number) {
|
||||
const polygon = cells.v[i].map(v => vertices.p[v]);
|
||||
const area = Math.abs(d3.polygonArea(polygon));
|
||||
return Math.min(area, UINT16_MAX);
|
||||
}
|
||||
|
||||
const pack = {
|
||||
vertices,
|
||||
cells: {
|
||||
...cells,
|
||||
p: newCells.p,
|
||||
g: createTypedArray({maxValue: grid.points.length, from: newCells.g}),
|
||||
q: d3.quadtree(newCells.p.map(([x, y], i) => [x, y, i])) as unknown as Quadtree,
|
||||
h: new Uint8Array(newCells.h),
|
||||
area: createTypedArray({maxValue: UINT16_MAX, from: cells.i}).map(getCellArea)
|
||||
}
|
||||
};
|
||||
|
||||
TIME && console.timeEnd("repackGrid");
|
||||
return pack;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue