mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-23 12:31:24 +01:00
better cell sampler
This commit is contained in:
parent
ecb367616d
commit
d2bd611412
1 changed files with 79 additions and 20 deletions
|
|
@ -40,19 +40,32 @@ window.Submap = (function () {
|
||||||
grid.cells.h = new Uint8Array(n); // heightmap
|
grid.cells.h = new Uint8Array(n); // heightmap
|
||||||
grid.cells.temp = new Int8Array(n); // temperature
|
grid.cells.temp = new Int8Array(n); // temperature
|
||||||
grid.cells.prec = new Int8Array(n); // precipitation
|
grid.cells.prec = new Int8Array(n); // precipitation
|
||||||
|
const reverseGridMap = new Uint32Array(n); // cellmap from new -> oldcell
|
||||||
|
|
||||||
const gridCells = parentMap.grid.cells;
|
const oldGrid = parentMap.grid;
|
||||||
// build cache old -> [newcelllist]
|
// build cache old -> [newcelllist]
|
||||||
const forwardGridMap = parentMap.grid.points.map(_=>[]);
|
const forwardGridMap = parentMap.grid.points.map(_=>[]);
|
||||||
resampler(grid.points, parentMap.pack.cells.q, (id, oldid) => {
|
resampler(grid.points, parentMap.pack.cells.q, (id, oldid) => {
|
||||||
const cid = parentMap.pack.cells.g[oldid];
|
const cid = parentMap.pack.cells.g[oldid];
|
||||||
grid.cells.h[id] = gridCells.h[cid];
|
grid.cells.h[id] = oldGrid.cells.h[cid];
|
||||||
grid.cells.temp[id] = gridCells.temp[cid];
|
grid.cells.temp[id] = oldGrid.cells.temp[cid];
|
||||||
grid.cells.prec[id] = gridCells.prec[cid];
|
grid.cells.prec[id] = oldGrid.cells.prec[cid];
|
||||||
if (options.depressRivers) forwardGridMap[cid].push(id);
|
if (options.depressRivers) forwardGridMap[cid].push(id);
|
||||||
|
reverseGridMap[id] = cid;
|
||||||
})
|
})
|
||||||
// TODO: add smooth/noise function for h, temp, prec n times
|
// TODO: add smooth/noise function for h, temp, prec n times
|
||||||
|
|
||||||
|
// smooth heightmap
|
||||||
|
// smoothing never should change cell type (land->water or water->land)
|
||||||
|
const gcells = grid.cells;
|
||||||
|
gcells.h.forEach((h,i) => {
|
||||||
|
const hs = gcells.c[i].map(c=>gcells.h[c])
|
||||||
|
hs.push(h)
|
||||||
|
gcells.h[i] = h>=20
|
||||||
|
? Math.max(d3.mean(hs),20)
|
||||||
|
: Math.min(d3.mean(hs),19);
|
||||||
|
});
|
||||||
|
|
||||||
if (options.depressRivers) {
|
if (options.depressRivers) {
|
||||||
stage("Generating riverbeds.")
|
stage("Generating riverbeds.")
|
||||||
const rbeds = new Uint16Array(grid.cells.i.length);
|
const rbeds = new Uint16Array(grid.cells.i.length);
|
||||||
|
|
@ -60,7 +73,7 @@ window.Submap = (function () {
|
||||||
// and erode riverbeds
|
// and erode riverbeds
|
||||||
parentMap.pack.rivers.forEach(r =>
|
parentMap.pack.rivers.forEach(r =>
|
||||||
r.cells.forEach(oldpc => {
|
r.cells.forEach(oldpc => {
|
||||||
if (oldpc < 0) return; // ignore out of map marker (-1)
|
if (oldpc < 0) return; // ignore out-of-map marker (-1)
|
||||||
const oldc = parentMap.pack.cells.g[oldpc];
|
const oldc = parentMap.pack.cells.g[oldpc];
|
||||||
const targetCells = forwardGridMap[oldc];
|
const targetCells = forwardGridMap[oldc];
|
||||||
if (!targetCells)
|
if (!targetCells)
|
||||||
|
|
@ -102,10 +115,12 @@ window.Submap = (function () {
|
||||||
stage("Define coastline.")
|
stage("Define coastline.")
|
||||||
drawCoastline();
|
drawCoastline();
|
||||||
|
|
||||||
// resample packed graph
|
/****************************************************/
|
||||||
|
/* Packed Graph */
|
||||||
|
/****************************************************/
|
||||||
const oldCells = parentMap.pack.cells;
|
const oldCells = parentMap.pack.cells;
|
||||||
const reverseMap = new Map(); // cellmap from new -> oldcell
|
// const reverseMap = new Map(); // cellmap from new -> oldcell
|
||||||
const forwardMap = parentMap.pack.cells.p.map(_=>[]); // old -> [newcelllist]
|
// const forwardMap = parentMap.pack.cells.p.map(_=>[]); // old -> [newcelllist]
|
||||||
|
|
||||||
const pn = pack.cells.i.length;
|
const pn = pack.cells.i.length;
|
||||||
const cells = pack.cells;
|
const cells = pack.cells;
|
||||||
|
|
@ -115,28 +130,72 @@ window.Submap = (function () {
|
||||||
cells.religion = new Uint16Array(pn);
|
cells.religion = new Uint16Array(pn);
|
||||||
cells.road = new Uint16Array(pn);
|
cells.road = new Uint16Array(pn);
|
||||||
cells.crossroad = new Uint16Array(pn);
|
cells.crossroad = new Uint16Array(pn);
|
||||||
|
cells.province = new Uint16Array(pn);
|
||||||
|
|
||||||
stage("Resampling culture, state and religion map.")
|
stage("Resampling culture, state and religion map.")
|
||||||
|
|
||||||
resampler(cells.p, oldCells.q, (id, oldid) => {
|
|
||||||
if (cells.t[id] * oldCells.t[oldid] < 0) {
|
for(const [id, gridCellId] of cells.g.entries()) {
|
||||||
// fix missmaped cell: water instead of land or vice versa
|
const oldGridId = reverseGridMap[gridCellId];
|
||||||
WARN && console.warn('Type discrepancy detected:', id, oldid, `${pack.cells.t[id]} != ${oldCells.t[oldid]}`);
|
if (!oldGridId) {
|
||||||
const aid = cells.t[id]<0
|
console.error("oldgridid must be defined for", gridCellId, reverseGridMap);
|
||||||
? cells.c[id].find(c=>cells.t[c]<0)
|
throw(new Error("oldgridid"))
|
||||||
: cells.c[id].find(c=>cells.t[c]>0);
|
}
|
||||||
const [x, y] = cells.p[aid];
|
// find old parent's children
|
||||||
|
const oldChildren = oldCells.i.filter(oid=>oldCells.g[oid]==oldGridId);
|
||||||
|
const isWater = x => x < 1? true: false;
|
||||||
|
let oldid; // matching cell on the original map
|
||||||
|
|
||||||
|
if (!oldChildren.length) {
|
||||||
|
// it *must* be a (deleted) deep ocean cell
|
||||||
|
if (!oldGrid.cells.h[oldGridId] < 20) {
|
||||||
|
console.error(`Warning, ${gridCellId} should be water cell, not ${oldGrid.cells.h[oldGridId]}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// find replacement: closest water cell
|
||||||
|
const [ox, oy] = cells.p[id]
|
||||||
const [tx, ty] = projection(x, y, true);
|
const [tx, ty] = projection(x, y, true);
|
||||||
oldid = oldCells.q.find(tx,ty,Infinity)[2];
|
oldid = oldCells.q.find(tx,ty,Infinity)[2];
|
||||||
WARN && console.warn(`using cell ${aid}->${oldid} instead`);
|
if (!oldid) {
|
||||||
|
console.warn("Warning, no id found in quad", id, "parent", gridCellId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// find closest children (packcell) on the parent map
|
||||||
|
const distance = x => (x[0]-cells.p[id][0])**2 + (x[1]-cells.p[id][1])**2;
|
||||||
|
let d = Infinity;
|
||||||
|
oldChildren.forEach(oid => {
|
||||||
|
// must be the same type (it should be always true!)
|
||||||
|
if (isWater(oldCells.t[oid]) !== isWater(cells.t[id])) {
|
||||||
|
console.error(
|
||||||
|
"should be the same", oid, id, oldCells.t[oid], cells.t[id],
|
||||||
|
"oldparent", oldCells.g[oid], "newparent", cells.g[id],
|
||||||
|
"oldheight:", oldGrid.cells.h[oldCells.g[oid]],
|
||||||
|
"newheight", grid.cells.h[cells.g[id]])
|
||||||
|
throw new Error("should be the same type")
|
||||||
|
}
|
||||||
|
|
||||||
|
const nd = distance(oldCells.p[oid]);
|
||||||
|
if (nd < d) [d, oldid] = [nd, oid];
|
||||||
|
})
|
||||||
|
if (!oldid) {
|
||||||
|
console.warn("Warning, no match for", id, "parent", gridCellId, "in");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWater(cells.t[id]) !== isWater(oldCells.t[oldid])) {
|
||||||
|
// fix missmaped cell: water instead of land or vice versa
|
||||||
|
WARN && console.warn('Type discrepancy detected:', id, oldid, `${pack.cells.t[id]} != ${oldCells.t[oldid]}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
cells.culture[id] = oldCells.culture[oldid];
|
cells.culture[id] = oldCells.culture[oldid];
|
||||||
cells.state[id] = oldCells.state[oldid];
|
cells.state[id] = oldCells.state[oldid];
|
||||||
cells.religion[id] = oldCells.religion[oldid];
|
cells.religion[id] = oldCells.religion[oldid];
|
||||||
reverseMap.set(id, oldid)
|
cells.province[id] = oldCells.province[oldid];
|
||||||
forwardMap[oldid].push(id)
|
// reverseMap.set(id, oldid)
|
||||||
})
|
// forwardMap[oldid].push(id)
|
||||||
|
}
|
||||||
|
|
||||||
stage("Regenerating river network.")
|
stage("Regenerating river network.")
|
||||||
Rivers.generate();
|
Rivers.generate();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue