Fractious template

This commit is contained in:
Azgaar 2022-05-21 19:46:42 +03:00
parent cf92a65ea1
commit a16e609696
5 changed files with 124 additions and 129 deletions

View file

@ -922,7 +922,7 @@ fieldset {
display: inline-block;
}
body button.noicon {
#templateTools > button {
width: 1.8em;
height: 1.6em;
margin: 1px;

View file

@ -1292,7 +1292,7 @@
<option value="volcano">Volcano</option>
<option value="highIsland">High Island</option>
<option value="lowIsland">Low Island</option>
<option value="continents">Two Continents</option>
<option value="continents">Continents</option>
<option value="archipelago">Archipelago</option>
<option value="atoll">Atoll</option>
<option value="mediterranean">Mediterranean</option>
@ -1302,6 +1302,7 @@
<option value="shattered">Shattered</option>
<option value="taklamakan">Taklamakan</option>
<option value="oldWorld">Old World</option>
<option value="fractious">Fractious</option>
</optgroup>
<optgroup label="Specific">
<option value="africa-centric">Africa Centric</option>
@ -2932,13 +2933,13 @@
<div id="templateEditor" class="dialog stable" style="display: none">
<div id="templateTop">
<i>Select template: </i
><select id="templateSelect" style="width: 16em" data-prev="templateCustom" data-tip="Select base template">
<i>Select template: </i>
<select id="templateSelect" style="width: 16em" data-prev="templateCustom" data-tip="Select base template">
<option value="custom" selected>Custom</option>
<option value="volcano">Volcano</option>
<option value="highIsland">High Island</option>
<option value="lowIsland">Low Island</option>
<option value="continents">Two Continents</option>
<option value="continents">Continents</option>
<option value="archipelago">Archipelago</option>
<option value="atoll">Atoll</option>
<option value="mediterranean">Mediterranean</option>
@ -2948,18 +2949,19 @@
<option value="shattered">Shattered</option>
<option value="taklamakan">Taklamakan</option>
<option value="oldWorld">Old World</option>
<option value="fractious">Fractious</option>
</select>
</div>
<div id="templateTools">
<button data-type="Hill" data-tip="Hill: small blob" class="noicon">H</button>
<button data-type="Pit" data-tip="Pit: round depression" class="noicon">P</button>
<button data-type="Range" data-tip="Range: elongated elevation" class="noicon">R</button>
<button data-type="Trough" data-tip="Trough: elongated depression" class="noicon">T</button>
<button data-type="Strait" data-tip="Strait: centered vertical or horizontal depression" class="noicon">S</button>
<button data-type="Insulate" data-tip="Insulate: lower cells near edges" class="noicon">I</button>
<button data-type="Add" data-tip="Add or subtract value from all heights in range" class="noicon">+</button>
<button data-type="Multiply" data-tip="Multiply all heights in range by factor" class="noicon">*</button>
<button data-type="Smooth" data-tip="Smooth the map replacing cell heights by an average values of its neighbors" class="noicon">~</button>
<button data-type="Hill" data-tip="Hill: small blob">H</button>
<button data-type="Pit" data-tip="Pit: round depression">P</button>
<button data-type="Range" data-tip="Range: elongated elevation">R</button>
<button data-type="Trough" data-tip="Trough: elongated depression">T</button>
<button data-type="Strait" data-tip="Strait: centered vertical or horizontal depression">S</button>
<button data-type="Mask" data-tip="Mask: lower cells near edges or in map center">M</button>
<button data-type="Add" data-tip="Add or subtract value from all heights in range">+</button>
<button data-type="Multiply" data-tip="Multiply all heights in range by factor">*</button>
<button data-type="Smooth" data-tip="Smooth the map replacing cell heights by an average values of its neighbors">~</button>
</div>
<div id="templateBody" data-changed="0" class="table" style="padding: 2px 0">
<div data-type="Hill">
@ -2986,6 +2988,9 @@
onclick="openURL('https://cartographyassets.com/asset-category/specific-assets/azgaars-generator/templates')"
></button>
<button id="templateTutorial" data-tip="Open Template Editor Tutorial" class="icon-info" onclick="wiki('Heightmap-template-editor')"></button>
<label data-tip="Set seed if you want template to generate the same heightmap each time. Leave blank to use random seed">
Seed: <input id="templateSeed" value="" type="number" min="1" max="999999999" step="1" />
</label>
</div>
</div>
@ -6110,7 +6115,7 @@
<script src="utils/unitUtils.js"></script>
<script src="modules/voronoi.js"></script>
<script src="modules/heightmap-templates.js"></script>
<script src="modules/heightmap-templates.js?v=21052020"></script>
<script src="modules/heightmap-generator.js?v=21052020"></script>
<script src="modules/ocean-layers.js"></script>
<script src="modules/river-generator.js"></script>

View file

@ -61,7 +61,7 @@ window.HeightmapGenerator = (function () {
if (a1 === "Range") return addRange(a2, a3, a4, a5);
if (a1 === "Trough") return addTrough(a2, a3, a4, a5);
if (a1 === "Strait") return addStrait(a2, a3);
if (a1 === "Insulate") return insulate(a2);
if (a1 === "Mask") return mask(a2);
if (a1 === "Add") return modify(a3, +a2, 1);
if (a1 === "Multiply") return modify(a3, 0, +a2);
if (a1 === "Smooth") return smooth(a2);
@ -432,14 +432,17 @@ window.HeightmapGenerator = (function () {
});
};
const insulate = (fr = 2) => {
const power = fr * 2;
const mask = (power = 1) => {
const fr = power ? Math.abs(power) : 1;
cells.h = cells.h.map((h, i) => {
const [x, y] = p[i];
const nx = (2 * x) / graphWidth - 1;
const ny = (2 * y) / graphHeight - 1;
const distance = (1 - nx ** power) * (1 - ny ** power); // 1 is center, 0 is edge
return h * distance;
const nx = (2 * x) / graphWidth - 1; // [-1, 1], 0 is center
const ny = (2 * y) / graphHeight - 1; // [-1, 1], 0 is center
let distance = (1 - nx ** 2) * (1 - ny ** 2); // 1 is center, 0 is edge
if (power < 0) distance = 1 - distance; // inverted, 0 is center, 1 is edge
const masked = h * distance;
return lim((h * (fr - 1) + masked) / fr);
});
};
@ -462,5 +465,5 @@ window.HeightmapGenerator = (function () {
}
}
return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify, insulate};
return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify, mask};
})();

View file

@ -4,49 +4,55 @@ window.HeightmapTemplates = (function () {
const volcano = `Hill 1 90-100 44-56 40-60
Multiply 0.8 50-100 0 0
Range 1.5 30-55 45-55 40-60
Smooth 2 0 0 0
Hill 1.5 25-35 25-30 20-75
Hill 1 25-35 75-80 25-75
Hill 0.5 20-25 10-15 20-25`;
Smooth 3 0 0 0
Hill 1.5 35-45 25-30 20-75
Hill 1 35-55 75-80 25-75
Hill 0.5 20-25 10-15 20-25
Mask 3 0 0 0`;
const highIsland = `Hill 1 90-100 65-75 47-53
Add 5 all 0 0
Hill 6 20-23 25-55 45-55
Add 7 all 0 0
Hill 5-6 20-30 25-55 45-55
Range 1 40-50 45-55 45-55
Multiply 0.8 land 0 0
Mask 3 0 0 0
Smooth 2 0 0 0
Trough 2-3 20-30 20-30 20-30
Trough 2-3 20-30 60-80 70-80
Hill 1 10-15 60-60 50-50
Hill 1.5 13-16 15-20 20-75
Multiply 0.8 20-100 0 0
Range 1.5 30-40 15-85 30-40
Range 1.5 30-40 15-85 60-70
Pit 2-3 10-15 15-85 20-80`;
Pit 3-5 10-30 15-85 20-80`;
const lowIsland = `Hill 1 90-99 60-80 45-55
Hill 4-5 25-35 20-65 40-60
Hill 1-2 20-30 10-30 10-90
Smooth 2 0 0 0
Hill 6-7 25-35 20-70 30-70
Range 1 40-50 45-55 45-55
Smooth 3 0 0 0
Trough 1.5 20-30 15-85 20-30
Trough 1.5 20-30 15-85 70-80
Trough 2-3 20-30 15-85 20-30
Trough 2-3 20-30 15-85 70-80
Hill 1.5 10-15 5-15 20-80
Hill 1 10-15 85-95 70-80
Pit 3-5 10-15 15-85 20-80
Multiply 0.4 20-100 0 0`;
Pit 5-7 15-25 15-85 20-80
Multiply 0.4 20-100 0 0
Mask 4 0 0 0`;
const continents = `Hill 1 80-85 75-80 40-60
Hill 1 80-85 20-25 40-60
Multiply 0.22 20-100 0 0
Hill 5-6 15-20 25-75 20-82
Range .8 30-60 5-15 20-45
Range .8 30-60 5-15 55-80
const continents = `Hill 1 80-85 60-80 40-60
Hill 1 80-85 20-30 40-60
Hill 6-7 15-30 25-75 15-85
Multiply 0.6 land 0 0
Hill 8-10 5-10 15-85 20-80
Range 1-2 30-60 5-15 25-75
Range 1-2 30-60 80-95 25-75
Range 0-3 30-60 80-90 20-80
Trough 3-4 15-20 15-85 20-80
Strait 2 vertical 0 0
Smooth 2 0 0 0
Trough 1-2 5-10 45-55 45-55
Pit 3-4 10-15 15-85 20-80
Hill 1 5-10 40-60 40-60`;
Strait 1 vertical 0 0
Smooth 3 0 0 0
Trough 3-4 15-20 15-85 20-80
Trough 3-4 5-10 45-55 45-55
Pit 3-4 10-20 15-85 20-80
Mask 4 0 0 0`;
const archipelago = `Add 11 all 0 0
Range 2-3 40-60 20-80 20-80
@ -65,16 +71,17 @@ window.HeightmapTemplates = (function () {
Multiply 0.2 25-100 0 0
Hill .5 10-20 50-55 48-52`;
const mediterranean = `Range 3-4 30-50 0-100 0-10
Range 3-4 30-50 0-100 90-100
Hill 5-6 30-70 0-100 0-5
Hill 5-6 30-70 0-100 95-100
const mediterranean = `Range 4-6 30-80 0-100 0-10
Range 4-6 30-80 0-100 90-100
Hill 6-8 30-50 10-90 0-5
Hill 6-8 30-50 10-90 95-100
Multiply 0.9 land 0 0
Mask -2 0 0 0
Smooth 1 0 0 0
Hill 2-3 30-70 0-5 20-80
Hill 2-3 30-70 95-100 20-80
Multiply 0.8 land 0 0
Trough 3-5 40-50 0-100 0-10
Trough 3-5 40-50 0-100 90-100`;
Trough 3-6 40-50 0-100 0-10
Trough 3-6 40-50 0-100 90-100`;
const peninsula = `Range 2-3 20-35 40-50 0-15
Add 5 all 0 0
@ -117,57 +124,26 @@ window.HeightmapTemplates = (function () {
Hill 2-4 60-85 0-5 0-100
Hill 2-4 60-85 95-100 0-100
Hill 3-4 60-85 20-80 0-5
Hill 3-4 60-85 20-80 95-100`;
Hill 3-4 60-85 20-80 95-100
Smooth 3 0 0 0`;
const oldWorld = `Hill 4-6 20-40 15-85 30-45
Hill 3-7 20-40 15-85 55-70
Strait 2-7 vertical 0 0
Pit 1-2 40-50 35-55 20-80
Strait 2-7 vertical 0 0
Range 2-3 20-25 15-35 20-30
Range 2-3 20-25 15-35 65-80
Range 2-3 20-25 45-85 20-45
Range 2-3 20-25 45-85 65-80
Multiply .9 80-100 0 0
Strait 2-7 vertical 0 0
Pit 2-3 40-50 45-65 20-80
Trough 1-2 40-50 15-45 20-45
Trough 1-3 40-50 15-45 45-80
Trough 1-2 40-50 45-85 20-45
Trough 1-2 40-50 45-85 45-80
Multiply 1.2 17-20 0 0
Strait 2-7 horizontal 0 0
Multiply 1.2 17-50 0 0
Range 1-2 20-25 15-45 45-65
Range 1-2 20-25 65-85 45-80
Multiply 1.1 50-80 0 0
Hill 1-2 20 15-45 20-80
Hill 1-2 20 65-85 20-80
Multiply 1.2 15-30 0 0
Strait 2-7 vertical 0 0
Trough 1-2 40-50 35-65 65-80
Range 1-2 20-25 15-35 20-45
Strait 2-7 vertical 0 0
Range 1-2 20-25 65-85 45-80
Multiply .9 70-100 0 0
Hill 1-2 20-25 15-45 65-80
Hill 1-2 20-25 65-85 20-45
Hill 1 20-25 15-45 45-65
Hill 1 20-25 65-85 45-65
Strait 2-7 vertical 0 0
Trough 1-2 20-50 15-45 45-65
Trough 1-2 20-50 65-85 45-65
Strait 2-7 horizontal 0 0
Multiply 0.8 70-100 0 0
Hill 1-2 20-25 35-45 45-65
Hill 1-2 20-25 65-70 45-65
Pit 2-3 40-50 45-65 30-70
Trough 1-2 40-50 15-85 65-80
Trough 1-2 40-50 15-85 10-35
Strait 2-5 vertical 0 0
Multiply 1.1 45-90 0 0
const oldWorld = `Range 3 70 15-85 20-80
Hill 2-3 50-70 15-45 20-80
Hill 2-3 50-70 65-85 20-80
Hill 4-6 20-25 15-85 20-80
Multiply 0.5 land 0 0
Smooth 2 0 0 0
Range 3-4 20-50 15-35 20-45
Range 2-4 20-50 65-85 45-80
Strait 3-7 vertical 0 0
Trough 1-2 40-50 45-65 45-65`;
Trough 6-8 20-50 15-85 45-65
Pit 5-6 20-30 10-90 10-90`;
const fractious = `Hill 12-15 50-80 5-95 5-95
Mask -1.5 0 0 0
Mask 3 0 0 0
Add -20 30-100 0 0
Range 6-8 40-50 5-95 10-90`;
return {
volcano,
@ -183,6 +159,7 @@ window.HeightmapTemplates = (function () {
isthmus,
shattered,
taklamakan,
oldWorld
oldWorld,
fractious
};
})();

View file

@ -487,8 +487,8 @@ function editHeightmap() {
function updateStatistics() {
const landCells = grid.cells.h.reduce((s, h) => (h >= 20 ? s + 1 : s));
landmassCounter.innerHTML = /* html */ `${landCells} (${rn((landCells / grid.cells.i.length) * 100)}%)`;
landmassAverage.innerHTML = rn(d3.mean(grid.cells.h));
byId("landmassCounter").innerText = `${landCells} (${rn((landCells / grid.cells.i.length) * 100)}%)`;
byId("landmassAverage").innerText = rn(d3.mean(grid.cells.h));
}
function updateHistory(noStat) {
@ -691,7 +691,7 @@ function editHeightmap() {
function openTemplateEditor() {
if ($("#templateEditor").is(":visible")) return;
const body = byId("templateBody");
const $body = byId("templateBody");
$("#templateEditor").dialog({
title: "Template Editor",
@ -707,13 +707,13 @@ function editHeightmap() {
$("#templateBody").sortable({items: "> div", handle: ".icon-resize-vertical", containment: "#templateBody", axis: "y"});
// add listeners
body.on("click", function (ev) {
$body.on("click", function (ev) {
const el = ev.target;
if (el.classList.contains("icon-check")) {
el.classList.remove("icon-check");
el.classList.add("icon-check-empty");
el.parentElement.style.opacity = 0.5;
body.dataset.changed = 1;
$body.dataset.changed = 1;
return;
}
if (el.classList.contains("icon-check-empty")) {
@ -728,6 +728,13 @@ function editHeightmap() {
}
});
byId("templateEditor").on("keypress", event => {
if (event.key === "Enter") {
event.preventDefault();
executeTemplate();
}
});
byId("templateTools").on("click", addStepOnClick);
byId("templateSelect").on("change", selectTemplate);
byId("templateRun").on("click", executeTemplate);
@ -789,9 +796,10 @@ function editHeightmap() {
</select></span>
<span>w:<input class="templateCount" data-tip="Strait width, use hyphen to get a random number in range" value=${count || "2-7"}></span></div>`;
if (type === "Insulate")
return /* html */ `${common}<span>f:<input class="templateCount" data-tip="Set insulation power. 1 - full insulation, 2 - half-insulation, etc." type="number" min=1 max=10
value=${count || 2}></span></div>`;
if (type === "Mask")
return /* html */ `${common}<span>f:<input class="templateCount"
data-tip="Set masking fraction. 1 - full insulation (prevent land on map edges), 2 - half-insulation, etc. Negative number to inverse the effect"
type="number" min=-10 max=10 value=${count || 1}></span></div>`;
if (type === "Add")
return /* html */ `${common}<span>to:<select class="templateDist" data-tip="Change only land or all cells">
@ -811,8 +819,8 @@ function editHeightmap() {
value=${count || 1.1} min=0 max=10 step=.1></span></div>`;
if (type === "Smooth")
return /* html */ `${common}<span>f:<input class="templateCount" data-tip="Set smooth fraction. 1 - full smooth, 2 - half-smooth, etc." type="number" min=1 max=10
value=${count || 2}></span></div>`;
return /* html */ `${common}<span>f:<input class="templateCount" data-tip="Set smooth fraction. 1 - full smooth, 2 - half-smooth, etc."
type="number" min=1 max=10 step=1 value=${count || 2}></span></div>`;
}
function setRange(event) {
@ -870,34 +878,36 @@ function editHeightmap() {
}
function executeTemplate() {
const body = byId("templateBody");
const steps = body.querySelectorAll("#templateBody > div");
const steps = byId("templateBody").querySelectorAll("#templateBody > div");
if (!steps.length) return;
const {addHill, addPit, addRange, addTrough, addStrait, modify, smooth, insulate} = HeightmapGenerator;
grid.cells.h = new Uint8Array(grid.cells.i.length); // clean all heights
const seed = byId("templateSeed").value;
if (seed) Math.random = aleaPRNG(seed);
restartHistory();
for (const step of steps) {
if (step.style.opacity === "0.5") continue;
const type = step.dataset.type;
const count = step.querySelector(".templateCount")?.value || "";
const height = step.querySelector(".templateHeight")?.value || "";
const dist = step.querySelector(".templateDist")?.value || null;
const x = step.querySelector(".templateX")?.value || null;
const y = step.querySelector(".templateY")?.value || null;
const type = step.dataset.type;
if (type === "Hill") addHill(count, height, x, y);
else if (type === "Pit") addPit(count, height, x, y);
else if (type === "Range") addRange(count, height, x, y);
else if (type === "Trough") addTrough(count, height, x, y);
else if (type === "Strait") addStrait(count, dist);
else if (type === "Insulate") insulate(+count);
else if (type === "Add") modify(dist, +count, 1);
else if (type === "Multiply") modify(dist, 0, +count);
else if (type === "Smooth") smooth(+count);
if (type === "Hill") HeightmapGenerator.addHill(count, height, x, y);
else if (type === "Pit") HeightmapGenerator.addPit(count, height, x, y);
else if (type === "Range") HeightmapGenerator.addRange(count, height, x, y);
else if (type === "Trough") HeightmapGenerator.addTrough(count, height, x, y);
else if (type === "Strait") HeightmapGenerator.addStrait(count, dist);
else if (type === "Mask") HeightmapGenerator.mask(+count);
else if (type === "Add") HeightmapGenerator.modify(dist, +count, 1);
else if (type === "Multiply") HeightmapGenerator.modify(dist, 0, +count);
else if (type === "Smooth") HeightmapGenerator.smooth(+count);
updateHistory("noStat"); // update history every step
updateHistory("noStat"); // update history on every step
}
updateStatistics();