First step for v6 biome rendering mode

This commit is contained in:
Wuzzy 2023-10-27 17:06:27 +02:00
parent ddb8914e5a
commit eec2e94ce1
2 changed files with 195 additions and 30 deletions

View File

@ -19,14 +19,22 @@ ERROR: This tool requires JavaScript to work, but JavaScript is disabled in your
</div>
</noscript>
</div>
<!-- The main content container starts hidden so it doesn't clutter
the page in noscript mode. It will be unhidden once the JavaScript loads -->
<div id="mainContentContainer" class="contentContainer" hidden>
<div id="modeContainer">
<button id="modernModeButton" type="button">Modern biomes</button>
<button id="v6ModeButton" type="button">v6 biomes</button>
</div>
<div id="canvasContainer">
<canvas id="voronoiCanvas" width="500" height="500">
A Voronoi diagram is supposed to be here but for some reason it cannot be displayed. This tool is useless without this functionality.
</canvas>
</div>
<div id="diagramInfoContainer" class="borderedSection">
<span id="errorMessage" hidden></span>
<span id="altitudeDisplay"></span>
@ -36,7 +44,8 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
<span id="coordinateDisplay">&nbsp;</span>
<br>
</div>
<div>
<div id="biomeConfigContainerOuter">
<h2 class="configHeader"><span class="collapser" id="biomeConfigHeaderLink"></span> Biome configuration</h2>
<div id="biomeConfigContainer" class="configFrame">
<form id="biomeForm">
@ -78,7 +87,9 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
</div>
</form>
</div>
<div>
</div>
<div id="viewConfigContainerOuter">
<h2 class="configHeader"><span class="collapser" id="viewConfigHeaderLink"></span> Diagram view settings</h2>
<div id="viewConfigContainer" class="configFrame">
<form id="viewForm">
@ -104,11 +115,12 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
</form>
</div>
</div>
<div>
<div id="noiseConfigContainerOuter">
<h2 class="configHeader"><span class="collapser" id="noiseConfigHeaderLink"></span> Noise parameters</h2>
<div class="configFrame" id="noiseConfigContainer">
<form id="noiseForm">
<h3>Heat (<code>mg_biome_np_heat</code>)</h3>
<h3>Heat (<code id="noiseSettingNameHeat">mg_biome_np_heat</code>)</h3>
<label for="inputNoiseHeatOffset">Offset:&nbsp;</label>
<input id="inputNoiseHeatOffset" type="number" value="50" size="10">
@ -121,7 +133,7 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
<label for="inputNoiseHeatPersistence">Persistence:&nbsp;</label>
<input id="inputNoiseHeatPersistence" type="number" value="0.5" step=0.01 size="10">
<h3>Humidity (<code>mg_biome_np_humidity</code>)</h3>
<h3>Humidity (<code id="noiseSettingNameHumidity">mg_biome_np_humidity</code>)</h3>
<label for="inputNoiseHumidityOffset">Offset:&nbsp;</label>
<input id="inputNoiseHumidityOffset" type="number" value="50" size="10">
@ -139,9 +151,8 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
</form>
</div>
</div>
</div>
<div>
<div id="importContainerOuter">
<h2 class="configHeader"><span class="collapser" id="importHeaderLink"></span> Import</h2>
<div class="configFrame" id="importContainer" style="display:none">
<form id="importForm">
@ -156,7 +167,7 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
</div>
</div>
<div>
<div id="exportContainerOuter">
<h2 class="configHeader"><span class="collapser" id="exportHeaderLink"></span> Export</h2>
<div class="configFrame" id="exportContainer" style="display:none">
<form id="exportForm">
@ -172,6 +183,7 @@ A Voronoi diagram is supposed to be here but for some reason it cannot be displa
</form>
</div>
</div>
</div>
<hr>

197
mibpov.js
View File

@ -6,6 +6,7 @@ const MAX_Y_DEFAULT = 31000
// Draw a grid line every GRID_STEP units
const GRID_STEP = 10
const GRID_STEP_V6 = 0.2
// Size of the resizing corner
const RESIZE_CORNER = 14;
@ -116,25 +117,45 @@ const NOISE_SCALE_DEFAULT = 50;
const NOISE_PERSISTENCE_DEFAULT = 0.5;
const NOISE_OCTAVES_DEFAULT = 3;
const NOISE_ABSVALUE_DEFAULT = false;
const NOISE_V6_OFFSET_DEFAULT = 0;
const NOISE_V6_SCALE_DEFAULT = 1;
const NOISE_V6_PERSISTENCE_DEFAULT = 0.5;
const NOISE_V6_OCTAVES_DEFAULT = 3;
const NOISE_V6_ABSVALUE_DEFAULT = false;
// Current noise values
let noises = {
heat: {
heat_modern: {
offset: NOISE_OFFSET_DEFAULT,
scale: NOISE_SCALE_DEFAULT,
octaves: NOISE_OCTAVES_DEFAULT,
persistence: NOISE_PERSISTENCE_DEFAULT,
absvalue: NOISE_ABSVALUE_DEFAULT,
},
humidity: {
humidity_modern: {
offset: NOISE_OFFSET_DEFAULT,
scale: NOISE_SCALE_DEFAULT,
octaves: NOISE_OCTAVES_DEFAULT,
persistence: NOISE_PERSISTENCE_DEFAULT,
absvalue: NOISE_ABSVALUE_DEFAULT,
},
heat_v6: {
offset: NOISE_V6_OFFSET_DEFAULT,
scale: NOISE_V6_SCALE_DEFAULT,
octaves: NOISE_V6_OCTAVES_DEFAULT,
persistence: NOISE_V6_PERSISTENCE_DEFAULT,
absvalue: NOISE_V6_ABSVALUE_DEFAULT,
},
humidity_v6: {
offset: NOISE_V6_OFFSET_DEFAULT,
scale: NOISE_V6_SCALE_DEFAULT,
octaves: NOISE_V6_OCTAVES_DEFAULT,
persistence: NOISE_V6_PERSISTENCE_DEFAULT,
absvalue: NOISE_V6_ABSVALUE_DEFAULT,
},
};
noises.heat = noises.heat_modern;
noises.humidity = noises.humidity_modern;
function updateAreaVarsFor(noiseType) {
let noise = noises[noiseType];
@ -442,7 +463,7 @@ function putPoint(context, point) {
};
/* Put the grid on the draw context */
function putGrid(context) {
function putGrid(context, gridStep) {
let [limit_x_min, limit_y_min] = biomeCoordsToCanvasPixelCoords(limit_heat_min, limit_humidity_min);
let [limit_x_max, limit_y_max] = biomeCoordsToCanvasPixelCoords(limit_heat_max, limit_humidity_max);
@ -457,8 +478,8 @@ function putGrid(context) {
// on the canvas.
// This code will effectively trigger if the value range
// is very high.
let xGridLinesPerPixel = (limit_heat_max-limit_heat_min) / voronoiCanvas.width / GRID_STEP;
let yGridLinesPerPixel = (limit_humidity_max-limit_humidity_min) / voronoiCanvas.height/ GRID_STEP;
let xGridLinesPerPixel = (limit_heat_max-limit_heat_min) / voronoiCanvas.width / gridStep;
let yGridLinesPerPixel = (limit_humidity_max-limit_humidity_min) / voronoiCanvas.height/ gridStep;
let xWidth = GRID_WIDTH_LEVEL_3;
let yWidth = GRID_WIDTH_LEVEL_3;
if (xGridLinesPerPixel > GRID_THRESHOLD_LEVEL_0) {
@ -484,13 +505,13 @@ function putGrid(context) {
context.beginPath();
let x = -xWidth*2;
let [heat, _] = canvasPixelCoordsToBiomeCoords(x, 0);
heat = heat - (heat % GRID_STEP);
heat = heat - (heat % gridStep);
steps = 0;
while (x < voronoiCanvas.width + xWidth*2) {
[x, _] = biomeCoordsToCanvasPixelCoords(heat, 0);
context.moveTo(x, limit_y_min);
context.lineTo(x, limit_y_max);
heat += GRID_STEP;
heat += gridStep;
steps++;
if (steps > 10000) {
console.error("Over 10000 grid lines on the X axis!");
@ -505,13 +526,13 @@ function putGrid(context) {
context.beginPath();
let y = -yWidth*2;
let [_, humidity] = canvasPixelCoordsToBiomeCoords(0, y);
humidity = humidity - (humidity % GRID_STEP);
humidity = humidity - (humidity % gridStep);
steps = 0;
while (y < voronoiCanvas.height + yWidth*2) {
[_, y] = biomeCoordsToCanvasPixelCoords(0, humidity);
context.moveTo(limit_x_min, y);
context.lineTo(limit_x_max, y);
humidity -= GRID_STEP;
humidity -= gridStep;
steps++;
if (steps > 10000) {
console.error("Over 10000 grid lines on the Y axis!");
@ -802,7 +823,7 @@ function getSelectedBiomeIDAndElement() {
/* Draws the diagram on the voronoiCanvas.
Will (re-)calculate the Voronoi diagram if recalculate is true;
otherwise it may re-use a previous diagram for performance reasons. */
function draw(recalculate) {
function drawModern(recalculate) {
let context = getDrawContext();
let w = voronoiCanvas.width;
let h = voronoiCanvas.height;
@ -996,7 +1017,7 @@ function draw(recalculate) {
if (points.length > 0) {
if (showGrid) {
putGrid(context);
putGrid(context, GRID_STEP);
}
if (showAxes) {
putAxes(context);
@ -1055,6 +1076,90 @@ function draw(recalculate) {
return true;
}
function drawV6() {
let context = getDrawContext();
let w = voronoiCanvas.width;
let h = voronoiCanvas.height;
let y = getViewY();
clear();
if (!context) {
if (!voronoiCanvas.hidden) {
voronoiCanvas.hidden = true;
coordinateDisplay.hidden = true;
altitudeDisplay.hidden = true;
rangeDisplay.hidden = true;
configDiv.hidden = true;
errorMessage.innerText = "ERROR: Could not get the canvas context which means this tool won't work for you. Maybe your browser does not support the HTML canvas element properly.";
console.error("Could not get the canvas context!");
}
return false;
}
clear(context);
let showDiagramMessage = function(context, text) {
context.textAlign = "center";
context.fillStyle = "black";
context.textBaseline = "middle";
if (voronoiCanvas.width < 300) {
context.font = "100% sans-serif";
} else if (voronoiCanvas.width < 450) {
context.font = "150% sans-serif";
} else {
context.font = "200% sans-serif";
}
context.fillText(text, voronoiCanvas.width/2, voronoiCanvas.height/2);
updateAltitudeText();
}
// Fail and render a special message if the value range is tiny
if ((limit_heat_max - limit_heat_min < 0.01) || (limit_humidity_max - limit_humidity_min < 0.01)) {
showDiagramMessage(context, "Value range is too small.");
drawError = true;
putResizeCorner(context);
return true;
}
// Fail and render a special message if the value range is huge
if ((limit_heat_max - limit_heat_min > MAX_HEAT_HUMIDITY_VALUE) || (limit_humidity_max - limit_humidity_min > MAX_HEAT_HUMIDITY_VALUE)) {
showDiagramMessage(context, "Value range is too large.");
drawError = true;
putResizeCorner(context);
return true;
}
// Fail and render a special message if value limit is out of permissible bounds
if ((limit_heat_max > MAX_HEAT_HUMIDITY_VALUE) || (limit_humidity_max > MAX_HEAT_HUMIDITY_VALUE)) {
showDiagramMessage(context, "Maximum value is too large.");
drawError = true;
putResizeCorner(context);
return true;
}
if ((limit_heat_min < MIN_HEAT_HUMIDITY_VALUE) || (limit_humidity_min < MIN_HEAT_HUMIDITY_VALUE)) {
showDiagramMessage(context, "Minimum value is too small.");
drawError = true;
putResizeCorner(context);
return true;
}
if (showGrid) {
putGrid(context, GRID_STEP_V6);
}
if (showAxes) {
putAxes(context);
}
}
function draw(recalculate) {
if (biomeMode === "v6") {
drawV6(recalculate);
} else {
drawModern(recalculate);
}
}
/* Clears the biome list widget and (re-adds) the list elements
for the biomes from scratch. */
function repopulateBiomeSelector() {
@ -1711,22 +1816,39 @@ inputNoiseHumidityPersistence.oninput = function() {
inputNoiseHumidityOctaves.oninput = function() {
updateNoiseParam("humidity", "octaves", this);
}
inputNoiseReset.onclick = function() {
noises.heat.offset = NOISE_OFFSET_DEFAULT;
noises.heat.scale = NOISE_SCALE_DEFAULT;
noises.heat.octaves = NOISE_OCTAVES_DEFAULT;
noises.heat.persistence = NOISE_PERSISTENCE_DEFAULT;
noises.heat.absvalue = NOISE_ABSVALUE_DEFAULT;
if (biomeMode === "v6") {
noises.heat.offset = NOISE_V6_OFFSET_DEFAULT;
noises.heat.scale = NOISE_V6_SCALE_DEFAULT;
noises.heat.octaves = NOISE_V6_OCTAVES_DEFAULT;
noises.heat.persistence = NOISE_V6_PERSISTENCE_DEFAULT;
noises.heat.absvalue = NOISE_V6_ABSVALUE_DEFAULT;
noises.humidity.offset = NOISE_V6_OFFSET_DEFAULT;
noises.humidity.scale = NOISE_V6_SCALE_DEFAULT;
noises.humidity.octaves = NOISE_V6_OCTAVES_DEFAULT;
noises.humidity.persistence = NOISE_V6_PERSISTENCE_DEFAULT;
noises.humidity.absvalue = NOISE_V6_ABSVALUE_DEFAULT;
} else {
noises.heat.offset = NOISE_OFFSET_DEFAULT;
noises.heat.scale = NOISE_SCALE_DEFAULT;
noises.heat.octaves = NOISE_OCTAVES_DEFAULT;
noises.heat.persistence = NOISE_PERSISTENCE_DEFAULT;
noises.heat.absvalue = NOISE_ABSVALUE_DEFAULT;
noises.humidity.offset = NOISE_OFFSET_DEFAULT;
noises.humidity.scale = NOISE_SCALE_DEFAULT;
noises.humidity.octaves = NOISE_OCTAVES_DEFAULT;
noises.humidity.persistence = NOISE_PERSISTENCE_DEFAULT;
noises.humidity.absvalue = NOISE_ABSVALUE_DEFAULT;
}
inputNoiseHeatOffset.value = noises.heat.offset;
inputNoiseHeatScale.value = noises.heat.scale;
inputNoiseHeatOctaves.value = noises.heat.octaves;
inputNoiseHeatPersistence.value = noises.heat.persistence;
noises.humidity.offset = NOISE_OFFSET_DEFAULT;
noises.humidity.scale = NOISE_SCALE_DEFAULT;
noises.humidity.octaves = NOISE_OCTAVES_DEFAULT;
noises.humidity.persistence = NOISE_PERSISTENCE_DEFAULT;
noises.humidity.absvalue = NOISE_ABSVALUE_DEFAULT;
inputNoiseHumidityOffset.value = noises.humidity.offset;
inputNoiseHumidityScale.value = noises.humidity.scale;
inputNoiseHumidityOctaves.value = noises.humidity.octaves;
@ -1956,6 +2078,37 @@ inputImportSubmit.onclick = function() {
}
}
/* Mode events */
let biomeMode = "modern";
modernModeButton.onclick = function() {
biomeMode = "modern";
biomeConfigContainerOuter.hidden = false;
importContainerOuter.hidden = false;
exportContainerOuter.hidden = false;
inputCheckboxPoints.disabled = false;
noises.heat = noises.heat_modern;
noises.humidity = noises.humidity_modern;
noiseSettingNameHeat.innerText = "mg_biome_np_heat";
noiseSettingNameHumidity.innerText = "mg_biome_np_humidity";
updateAreaVars();
updateWidgetStates();
draw(true);
}
v6ModeButton.onclick = function() {
biomeMode = "v6";
biomeConfigContainerOuter.hidden = true;
importContainerOuter.hidden = true;
exportContainerOuter.hidden = true;
inputCheckboxPoints.disabled = true;
noises.heat = noises.heat_v6;
noises.humidity = noises.humidity_v6;
noiseSettingNameHeat.innerText = "mgv6_np_biome";
noiseSettingNameHumidity.innerText = "mgv6_np_humidity";
updateAreaVars();
updateWidgetStates();
draw();
}
/* Events for collapsing/extending config section with the arrow thingie */
biomeConfigHeaderLink.onclick = function() {