not good but not bad
This commit is contained in:
parent
5c82bfcab7
commit
4f0df3f6c5
11 changed files with 1284 additions and 622 deletions
|
|
@ -1,11 +1,10 @@
|
|||
import { INF, MAP_H, MAP_W, SIZE, MinHeap, clamp, createMapFields, fbm, hash2, indexOf, inside, lerp, pickEntities, rand, smoothstep, valueNoise, xyOf } from "./mapUtils.js";
|
||||
import {
|
||||
extractMaskBorder,
|
||||
extractRegionBorderSegments,
|
||||
generateRegionalPrefectures,
|
||||
makePrefectureMask,
|
||||
neighbors8,
|
||||
} from "./mapGeneratorHelpers.js";
|
||||
import { buildNaturalCompartments } from "./adminRegions.js";
|
||||
|
||||
const ASPECT = MAP_W / MAP_H;
|
||||
const SQRT2 = Math.SQRT2;
|
||||
|
|
@ -128,10 +127,10 @@ function ridgeContribution(px, py, ridge, seed) {
|
|||
const along = Math.abs(u / Math.max(0.001, half));
|
||||
if (along >= 1.22) return 0;
|
||||
const taper = smoothstep(1 - clamp((along - 0.68) / 0.54));
|
||||
const wobble = (valueNoise((u + ridge.phase) * 720, (py + ridge.phase) * 720, seed + ridge.seedOffset, 14) - 0.5) * ridge.width * ridge.wobble;
|
||||
const wobble = (valueNoise((u + ridge.phase) * 720, (v + ridge.phase * 0.37) * 980, seed + ridge.seedOffset, 14) - 0.5) * ridge.width * ridge.wobble;
|
||||
const cross = Math.abs(v + wobble);
|
||||
const core = Math.exp(-Math.pow(cross / Math.max(0.0008, ridge.width), 2.0));
|
||||
const serration = 0.82 + 0.36 * valueNoise((px + ridge.phase) * 900, (py - ridge.phase) * 900, seed + ridge.seedOffset + 71, 7.5);
|
||||
const serration = 0.82 + 0.36 * valueNoise((u + ridge.phase) * 900, (v - ridge.phase * 0.41) * 1200, seed + ridge.seedOffset + 71, 7.5);
|
||||
return ridge.height * core * taper * serration;
|
||||
}
|
||||
|
||||
|
|
@ -169,13 +168,13 @@ const TERRAIN_TYPES = [
|
|||
mountainOffsetRange: [0.47, 0.53],
|
||||
baseHeightRange: [0.74, 1.10],
|
||||
primaryLengthRange: [0.76, 0.96],
|
||||
primaryWidthRange: [0.17, 0.30],
|
||||
primaryWidthRange: [0.13, 0.22],
|
||||
systemCountRange: [12, 16],
|
||||
beltCountRange: [3, 4],
|
||||
angleSpread: 0.14,
|
||||
crossSpread: 0.54,
|
||||
crossSpread: 0.38,
|
||||
lengthScale: 1.22,
|
||||
widthScale: 1.16,
|
||||
widthScale: 0.92,
|
||||
heightScale: 1.24,
|
||||
coastStrength: 0.90,
|
||||
plainBiasRange: [0.16, 0.34],
|
||||
|
|
@ -445,7 +444,7 @@ function buildMountainSystems(template, seed) {
|
|||
y: clamp(0.50 + Math.sin(centralAngle) * centralAlong + Math.sin(centralAngle + Math.PI / 2) * centralCross, 0.12, 0.88),
|
||||
angle: centralAngle,
|
||||
length: (0.78 + rand(seed, 3333) * 0.18) * lengthScale,
|
||||
width: (0.17 + rand(seed, 3334) * 0.11) * widthScale,
|
||||
width: (0.12 + rand(seed, 3334) * 0.07) * widthScale,
|
||||
height: template.mountainBaseHeight * heightScale * (0.58 + rand(seed, 3335) * 0.18),
|
||||
scratchCount: Math.round(20 + rand(seed, 3336) * 10),
|
||||
massifness: clamp((template.mountainMassifness ?? 0.16) * 0.55),
|
||||
|
|
@ -462,7 +461,7 @@ function buildMountainSystems(template, seed) {
|
|||
y: clamp(0.50 + Math.sin(centralAngle) * (centralAlong + side * 0.18) + Math.sin(centralAngle + Math.PI / 2) * (centralCross + side * 0.028), 0.10, 0.90),
|
||||
angle: centralAngle + (rand(seed, 3341) - 0.5) * 0.08,
|
||||
length: (0.48 + rand(seed, 3342) * 0.20) * lengthScale,
|
||||
width: (0.11 + rand(seed, 3343) * 0.08) * widthScale,
|
||||
width: (0.075 + rand(seed, 3343) * 0.055) * widthScale,
|
||||
height: template.mountainBaseHeight * heightScale * (0.38 + rand(seed, 3344) * 0.16),
|
||||
scratchCount: Math.round(12 + rand(seed, 3345) * 8),
|
||||
massifness: clamp((template.mountainMassifness ?? 0.16) * 0.65),
|
||||
|
|
@ -970,9 +969,24 @@ export function generateTerrainAndRivers(seed) {
|
|||
branchRidgeField[i] = clamp(branchRidgeField[i] + r * 5.0);
|
||||
arcSpineField[i] = clamp(Math.max(arcSpineField[i], r * 4.6));
|
||||
}
|
||||
const macro = (fbm(x * terrainTemplate.macroNoiseScale * 48, y * terrainTemplate.macroNoiseScale * 48, seed + 500) - 0.5) * 2;
|
||||
let macro;
|
||||
let scratch;
|
||||
if (terrainTemplate.terrainType === "tohoku_spine") {
|
||||
const dx = (px - 0.5) * ASPECT;
|
||||
const dy = py - 0.5;
|
||||
const { u, v } = rotate(dx, dy, terrainTemplate.mountainAngle);
|
||||
const warp = (valueNoise(x * 0.50, y * 0.50, seed + 504, 28) - 0.5) * 18;
|
||||
macro = (fbm(u * 520 + warp, v * 1850 - warp * 0.35, seed + 500) - 0.5) * 2;
|
||||
scratch = (fbm(u * 920 + warp * 0.8, v * 2300 + warp * 0.25, seed + 502) - 0.5) * 2;
|
||||
const passBreak = clamp((valueNoise(u * 760 + 17, v * 1800 - 11, seed + 505, 18) - 0.62) * 2.6);
|
||||
const lateralBranch = clamp((valueNoise(v * 1700 - 3, u * 540 + 5, seed + 506, 16) - 0.54) * 2.1);
|
||||
e += lateralBranch * mountainMaskMax * 0.022;
|
||||
e -= passBreak * mountainMaskMax * 0.052;
|
||||
} else {
|
||||
macro = (fbm(x * terrainTemplate.macroNoiseScale * 48, y * terrainTemplate.macroNoiseScale * 48, seed + 500) - 0.5) * 2;
|
||||
scratch = (fbm(x * 2.2, y * 2.2, seed + 502) - 0.5) * 2;
|
||||
}
|
||||
const global = (valueNoise(x * 0.23, y * 0.23, seed + 501, 38) - 0.5) * 2;
|
||||
const scratch = (fbm(x * 2.2, y * 2.2, seed + 502) - 0.5) * 2;
|
||||
e += macro * terrainTemplate.macroNoiseStrength * (0.38 + mountainMaskMax * 0.80);
|
||||
e += global * 0.020;
|
||||
e += scratch * terrainTemplate.scratchNoiseStrength * mountainMaskMax;
|
||||
|
|
@ -997,11 +1011,16 @@ export function generateTerrainAndRivers(seed) {
|
|||
deriveFields(seed, terrainTemplate, fields, seaLevel);
|
||||
|
||||
const prefectureMask = makePrefectureMask(seed, sea, elevation, slope, river);
|
||||
const regional = generateRegionalPrefectures(seed, sea, elevation, slope, river, ridgeField, flowAccum, prefectureMask);
|
||||
const prefectureRegionId = regional.regionId;
|
||||
const adminPrefectureRegionId = regional.displayRegionId || regional.regionId;
|
||||
const regionalDebug = regional.debug;
|
||||
const regionalPrefectureBorders = extractRegionBorderSegments(adminPrefectureRegionId, sea);
|
||||
const landMask = new Uint8Array(SIZE);
|
||||
for (let i = 0; i < SIZE; i++) landMask[i] = sea[i] ? 0 : 1;
|
||||
const zeroDensity = new Float32Array(SIZE);
|
||||
const zeroLanduse = new Int8Array(SIZE);
|
||||
const natural = buildNaturalCompartments(
|
||||
landMask, sea, elevation, slope, river, ridgeField, valleyField, basinField, coastalLowland, flowAccum,
|
||||
null, plain, agriculture, zeroDensity, zeroLanduse,
|
||||
{ seed: seed + 17003, targetCompartmentCount: clamp(Math.round((SIZE - sea.reduce((sum, value) => sum + value, 0)) / 30), 80, 520) }
|
||||
);
|
||||
const sharedNaturalBarrierScore = natural.naturalBarrierScore || naturalBarrierScore;
|
||||
const prefectureBorder = extractMaskBorder(prefectureMask, sea);
|
||||
|
||||
let landCount = 0;
|
||||
|
|
@ -1065,17 +1084,16 @@ export function generateTerrainAndRivers(seed) {
|
|||
depositionalLowland,
|
||||
alluvialFanField,
|
||||
deltaField,
|
||||
naturalBarrierScore,
|
||||
naturalBarrierScore: sharedNaturalBarrierScore,
|
||||
portSuitability,
|
||||
crossingSuitability,
|
||||
passSuitability,
|
||||
prefectureMask,
|
||||
landMask,
|
||||
prefectureBorder,
|
||||
prefectureRegionId,
|
||||
adminPrefectureRegionId,
|
||||
regionalDebug,
|
||||
naturalCompartmentId: natural.compartmentId,
|
||||
naturalCompartments: natural.compartments,
|
||||
terrainDebug,
|
||||
regionalPrefectureBorders,
|
||||
riverPaths,
|
||||
mainRivers,
|
||||
tributaryRivers,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue