mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
added topography
This commit is contained in:
parent
21df872ca2
commit
2c3692f000
5 changed files with 151 additions and 1 deletions
|
|
@ -494,6 +494,14 @@
|
|||
>
|
||||
<u>H</u>eightmap
|
||||
</li>
|
||||
<li
|
||||
id="toggleTopography"
|
||||
data-tip="Topographic contours: click to toggle, drag to raise or lower the layer"
|
||||
data-shortcut="Q"
|
||||
onclick="toggleTopography(event)"
|
||||
>
|
||||
Topo<u>g</u>raphy
|
||||
</li>
|
||||
<li
|
||||
id="toggleBiomes"
|
||||
data-tip="Biomes: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style"
|
||||
|
|
@ -8205,5 +8213,6 @@
|
|||
<script defer src="modules/renderers/draw-burg-labels.js?v=1.108.1"></script>
|
||||
<script defer src="modules/renderers/draw-burg-icons.js?v=1.104.0"></script>
|
||||
<script defer src="modules/renderers/draw-relief-icons.js?v=1.108.4"></script>
|
||||
<script defer src="modules/renderers/draw-topography.js?v=1.108.4"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
3
main.js
3
main.js
|
|
@ -50,6 +50,7 @@ let lakes = viewbox.append("g").attr("id", "lakes");
|
|||
let landmass = viewbox.append("g").attr("id", "landmass");
|
||||
let texture = viewbox.append("g").attr("id", "texture");
|
||||
let terrs = viewbox.append("g").attr("id", "terrs");
|
||||
let topography = viewbox.append("g").attr("id", "topography");
|
||||
let biomes = viewbox.append("g").attr("id", "biomes");
|
||||
let cells = viewbox.append("g").attr("id", "cells");
|
||||
let gridOverlay = viewbox.append("g").attr("id", "gridOverlay");
|
||||
|
|
@ -249,7 +250,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||
hideLoading();
|
||||
await checkLoadParameters();
|
||||
}
|
||||
restoreDefaultEvents; // apply default viewbox events
|
||||
restoreDefaultEvents(); // apply default viewbox events
|
||||
initiateAutosave();
|
||||
});
|
||||
|
||||
|
|
|
|||
125
modules/renderers/draw-topography.js
Normal file
125
modules/renderers/draw-topography.js
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
"use strict";
|
||||
|
||||
// Draw topographic hillshade-style fill per grid cell
|
||||
function drawTopography() {
|
||||
TIME && console.time("drawTopography");
|
||||
|
||||
const group = d3.select("#topography");
|
||||
group.selectAll("*").remove();
|
||||
|
||||
const {cells, points, features: gridFeatures} = grid;
|
||||
|
||||
// Colorimetry from user (positive altitudes, depressions, negative altitudes)
|
||||
// Start positive ramp at #BAAE9A as requested
|
||||
const POSITIVE_COLORS = [
|
||||
"#BAAE9A",
|
||||
"#AC9A7C",
|
||||
"#AA8753",
|
||||
"#B9985A",
|
||||
"#C3A76B",
|
||||
"#CAB982",
|
||||
"#D3CA9D",
|
||||
"#DED6A3",
|
||||
"#E8E1B6",
|
||||
"#EFEBC0",
|
||||
"#E1E4B5",
|
||||
"#D1D7AB",
|
||||
"#BDCC96",
|
||||
"#A8C68F",
|
||||
"#94BF8B",
|
||||
"#ACD0A5"
|
||||
];
|
||||
const NEGATIVE_COLORS = [
|
||||
"#D8F2FE",
|
||||
"#C6ECFF",
|
||||
"#B9E3FF",
|
||||
"#ACDBFB",
|
||||
"#A1D2F7",
|
||||
"#96C9F0",
|
||||
"#8DC1EA",
|
||||
"#84B9E3",
|
||||
"#79B2DE",
|
||||
"#71ABD8"
|
||||
];
|
||||
const DEPRESSIONS_COLOR = "#0978AB"; // lakes / inland depressions: Rivers, coasts, hydronyms color
|
||||
|
||||
const posInterp = d3.interpolateRgbBasis(POSITIVE_COLORS);
|
||||
const negInterp = d3.interpolateRgbBasis(NEGATIVE_COLORS);
|
||||
|
||||
// Base color scheme mirrors heightmap scheme
|
||||
// not used now; we fully replace with provided palette
|
||||
|
||||
// Lighting settings (can be overridden by attributes)
|
||||
const azimuth = (+group.attr("azimuth") || 315) * (Math.PI / 180); // degrees → radians
|
||||
const altitude = (+group.attr("altitude") || 45) * (Math.PI / 180);
|
||||
const light = [Math.cos(azimuth) * Math.cos(altitude), Math.sin(azimuth) * Math.cos(altitude), Math.sin(altitude)];
|
||||
const zScale = +group.attr("zscale") || 0.8; // vertical exaggeration for normals
|
||||
|
||||
let html = "";
|
||||
|
||||
for (const i of cells.i) {
|
||||
const h = cells.h[i];
|
||||
const isWater = h < 20;
|
||||
const featureType = isWater && gridFeatures ? gridFeatures[cells.f[i]]?.type : null;
|
||||
const isLake = isWater && featureType === "lake";
|
||||
|
||||
// Estimate gradient from neighbors
|
||||
const [cx, cy] = points[i];
|
||||
let gx = 0,
|
||||
gy = 0,
|
||||
wsum = 0;
|
||||
for (const n of cells.c[i]) {
|
||||
if (n < 0) continue;
|
||||
const [nx, ny] = points[n];
|
||||
const dx = nx - cx;
|
||||
const dy = ny - cy;
|
||||
const dist = Math.hypot(dx, dy) || 1;
|
||||
const dh = (cells.h[n] - h) / 100; // normalize height difference
|
||||
const w = 1 / dist; // weight close neighbors higher
|
||||
gx += w * dh * (dx / dist);
|
||||
gy += w * dh * (dy / dist);
|
||||
wsum += w;
|
||||
}
|
||||
if (wsum) {
|
||||
gx /= wsum;
|
||||
gy /= wsum;
|
||||
}
|
||||
|
||||
// Build surface normal and compute light intensity
|
||||
const nx = -gx * zScale;
|
||||
const ny = -gy * zScale;
|
||||
const nz = 1;
|
||||
const invLen = 1 / Math.hypot(nx, ny, nz);
|
||||
const n0 = [nx * invLen, ny * invLen, nz * invLen];
|
||||
const intensity = minmax(n0[0] * light[0] + n0[1] * light[1] + n0[2] * light[2], 0, 1);
|
||||
|
||||
// Base color from provided palettes
|
||||
let baseColor;
|
||||
if (isWater) {
|
||||
if (isLake) baseColor = d3.color(DEPRESSIONS_COLOR);
|
||||
else {
|
||||
const t = minmax((20 - h) / 20, 0, 1); // shallow 0 → deep 1
|
||||
baseColor = d3.color(negInterp(t));
|
||||
}
|
||||
} else {
|
||||
const t = minmax((h - 20) / 80, 0, 1); // lowland 0 → highland 1
|
||||
baseColor = d3.color(posInterp(t));
|
||||
}
|
||||
|
||||
// Modulate lightness by intensity (weaker effect on water)
|
||||
const hsl = d3.hsl(baseColor);
|
||||
const k = isWater ? 0.4 : 0.8;
|
||||
hsl.l = minmax(hsl.l * (0.6 + k * intensity), 0, 1);
|
||||
const color = hsl.toString();
|
||||
|
||||
// Cell polygon
|
||||
const poly = getGridPolygon(i)
|
||||
.map(p => `${rn(p[0], 2)},${rn(p[1], 2)}`)
|
||||
.join(" ");
|
||||
html += `<polygon points="${poly}" fill="${color}" opacity="${(terrs.attr("opacity") || 1) * 1}" />`;
|
||||
}
|
||||
|
||||
group.html(html);
|
||||
|
||||
TIME && console.timeEnd("drawTopography");
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ function handleKeyup(event) {
|
|||
else if (key === "%") toggleAddMarker();
|
||||
else if (code === "KeyX") toggleTexture();
|
||||
else if (code === "KeyH") toggleHeight();
|
||||
else if (code === "KeyQ") toggleTopography();
|
||||
else if (code === "KeyB") toggleBiomes();
|
||||
else if (code === "KeyE") toggleCells();
|
||||
else if (code === "KeyG") toggleGrid();
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ function drawLayers() {
|
|||
drawFeatures();
|
||||
if (layerIsOn("toggleTexture")) drawTexture();
|
||||
if (layerIsOn("toggleHeight")) drawHeightmap();
|
||||
if (layerIsOn("toggleTopography")) drawTopography();
|
||||
if (layerIsOn("toggleBiomes")) drawBiomes();
|
||||
if (layerIsOn("toggleCells")) drawCells();
|
||||
if (layerIsOn("toggleGrid")) drawGrid();
|
||||
|
|
@ -229,6 +230,18 @@ function toggleHeight(event) {
|
|||
}
|
||||
}
|
||||
|
||||
function toggleTopography(event) {
|
||||
const group = d3.select('#topography');
|
||||
const hasContent = group.selectAll('*').size() > 0;
|
||||
if (!hasContent) {
|
||||
turnButtonOn('toggleTopography');
|
||||
drawTopography();
|
||||
} else {
|
||||
turnButtonOff('toggleTopography');
|
||||
group.selectAll('*').remove();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTemperature(event) {
|
||||
if (!temperature.selectAll("*").size()) {
|
||||
turnButtonOn("toggleTemperature");
|
||||
|
|
@ -1015,6 +1028,7 @@ function moveLayer(event, ui) {
|
|||
// define connection between option layer buttons and actual svg groups to move the element
|
||||
function getLayer(id) {
|
||||
if (id === "toggleHeight") return $("#terrs");
|
||||
if (id === "toggleTopography") return $("#topography");
|
||||
if (id === "toggleBiomes") return $("#biomes");
|
||||
if (id === "toggleCells") return $("#cells");
|
||||
if (id === "toggleGrid") return $("#gridOverlay");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue