feat: allow to render ocean heightmap - fix issue

This commit is contained in:
Azgaar 2024-02-11 22:35:53 +01:00
parent 94280e0acf
commit 2d0cd90f6e
9 changed files with 37 additions and 42 deletions

View file

@ -1 +1 @@
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).polylabel=t()}}(function(){return function t(n,e,r){function o(a,u){if(!e[a]){if(!n[a]){var f="function"==typeof require&&require;if(!u&&f)return f(a,!0);if(i)return i(a,!0);var h=new Error("Cannot find module '"+a+"'");throw h.code="MODULE_NOT_FOUND",h}var s=e[a]={exports:{}};n[a][0].call(s.exports,function(t){var e=n[a][1][t];return o(e||t)},s,s.exports,t,n,e,r)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,n,e){"use strict";var r=t("tinyqueue");function o(t,n){return n.max-t.max}function i(t,n,e,r){this.x=t,this.y=n,this.h=e,this.d=function(t,n,e){for(var r=!1,o=1/0,i=0;i<e.length;i++)for(var u=e[i],f=0,h=u.length,s=h-1;f<h;s=f++){var d=u[f],l=u[s];d[1]>n!=l[1]>n&&t<(l[0]-d[0])*(n-d[1])/(l[1]-d[1])+d[0]&&(r=!r),o=Math.min(o,a(t,n,d,l))}return(r?1:-1)*Math.sqrt(o)}(t,n,r),this.max=this.d+this.h*Math.SQRT2}function a(t,n,e,r){var o=e[0],i=e[1],a=r[0]-o,u=r[1]-i;if(0!==a||0!==u){var f=((t-o)*a+(n-i)*u)/(a*a+u*u);f>1?(o=r[0],i=r[1]):f>0&&(o+=a*f,i+=u*f)}return(a=t-o)*a+(u=n-i)*u}n.exports=function(t,n,e){var a,u,f,h;n=n||1;for(var s=0;s<t[0].length;s++){var d=t[0][s];(!s||d[0]<a)&&(a=d[0]),(!s||d[1]<u)&&(u=d[1]),(!s||d[0]>f)&&(f=d[0]),(!s||d[1]>h)&&(h=d[1])}for(var l=f-a,p=h-u,c=Math.min(l,p),v=c/2,g=new r(null,o),x=a;x<f;x+=c)for(var y=u;y<h;y+=c)g.push(new i(x+v,y+v,v,t));var w=function(t){for(var n=0,e=0,r=0,o=t[0],a=0,u=o.length,f=u-1;a<u;f=a++){var h=o[a],s=o[f],d=h[0]*s[1]-s[0]*h[1];e+=(h[0]+s[0])*d,r+=(h[1]+s[1])*d,n+=3*d}return new i(e/n,r/n,0,t)}(t),m=g.length;for(;g.length;){var b=g.pop();b.d>w.d&&(w=b,e&&console.log("found best %d after %d probes",Math.round(1e4*b.d)/1e4,m)),b.max-w.d<=n||(v=b.h/2,g.push(new i(b.x-v,b.y-v,v,t)),g.push(new i(b.x+v,b.y-v,v,t)),g.push(new i(b.x-v,b.y+v,v,t)),g.push(new i(b.x+v,b.y+v,v,t)),m+=4)}e&&(console.log("num probes: "+m),console.log("best distance: "+w.d));return[w.x,w.y]}},{tinyqueue:2}],2:[function(t,n,e){"use strict";function r(t,n){if(!(this instanceof r))return new r(t,n);if(this.data=t||[],this.length=this.data.length,this.compare=n||o,t)for(var e=Math.floor(this.length/2);e>=0;e--)this._down(e)}function o(t,n){return t<n?-1:t>n?1:0}function i(t,n,e){var r=t[n];t[n]=t[e],t[e]=r}n.exports=r,r.prototype={push:function(t){this.data.push(t),this.length++,this._up(this.length-1)},pop:function(){var t=this.data[0];return this.data[0]=this.data[this.length-1],this.length--,this.data.pop(),this._down(0),t},peek:function(){return this.data[0]},_up:function(t){for(var n=this.data,e=this.compare;t>0;){var r=Math.floor((t-1)/2);if(!(e(n[t],n[r])<0))break;i(n,r,t),t=r}},_down:function(t){for(var n=this.data,e=this.compare,r=this.length;;){var o=2*t+1,a=o+1,u=t;if(o<r&&e(n[o],n[u])<0&&(u=o),a<r&&e(n[a],n[u])<0&&(u=a),u===t)return;i(n,u,t),t=u}}}},{}]},{},[1])(1)}); !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).polylabel=t()}}(function(){return function t(n,e,r){function o(a,u){if(!e[a]){if(!n[a]){var f="function"==typeof require&&require;if(!u&&f)return f(a,!0);if(i)return i(a,!0);var h=new Error("Cannot find module '"+a+"'");throw h.code="MODULE_NOT_FOUND",h}var s=e[a]={exports:{}};n[a][0].call(s.exports,function(t){var e=n[a][1][t];return o(e||t)},s,s.exports,t,n,e,r)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,n,e){"use strict";var r=t("tinyqueue");function o(t,n){return n.max-t.max}function i(t,n,e,r){this.x=t,this.y=n,this.h=e,this.d=function(t,n,e){for(var r=!1,o=1/0,i=0;i<e.length;i++)for(var u=e[i],f=0,h=u.length,s=h-1;f<h;s=f++){var d=u[f],l=u[s];d[1]>n!=l[1]>n&&t<(l[0]-d[0])*(n-d[1])/(l[1]-d[1])+d[0]&&(r=!r),o=Math.min(o,a(t,n,d,l))}return(r?1:-1)*Math.sqrt(o)}(t,n,r),this.max=this.d+this.h*Math.SQRT2}function a(t,n,e,r){var o=e[0],i=e[1],a=r[0]-o,u=r[1]-i;if(0!==a||0!==u){var f=((t-o)*a+(n-i)*u)/(a*a+u*u);f>1?(o=r[0],i=r[1]):f>0&&(o+=a*f,i+=u*f)}return(a=t-o)*a+(u=n-i)*u}n.exports=function(t,n,e){var a,u,f,h;n=n||1;for(var s=0;s<t[0].length;s++){var d=t[0][s];(!s||d[0]<a)&&(a=d[0]),(!s||d[1]<u)&&(u=d[1]),(!s||d[0]>f)&&(f=d[0]),(!s||d[1]>h)&&(h=d[1])}for(var l=f-a,p=h-u,c=Math.min(l,p),v=c/2,g=new r(null,o),x=a;x<f;x+=c)for(var y=u;y<h;y+=c)g.push(new i(x+v,y+v,v,t));var w=function(t){for(var n=0,e=0,r=0,o=t[0],a=0,u=o.length,f=u-1;a<u;f=a++){var h=o[a],s=o[f],d=h[0]*s[1]-s[0]*h[1];e+=(h[0]+s[0])*d,r+=(h[1]+s[1])*d,n+=3*d}return new i(e/n,r/n,0,t)}(t),m=g.length;for(;g.length;){var b=g.pop();b.d>w.d&&(w=b,e&&console.info("found best %d after %d probes",Math.round(1e4*b.d)/1e4,m)),b.max-w.d<=n||(v=b.h/2,g.push(new i(b.x-v,b.y-v,v,t)),g.push(new i(b.x+v,b.y-v,v,t)),g.push(new i(b.x-v,b.y+v,v,t)),g.push(new i(b.x+v,b.y+v,v,t)),m+=4)}e&&(console.info("num probes: "+m),console.info("best distance: "+w.d));return[w.x,w.y]}},{tinyqueue:2}],2:[function(t,n,e){"use strict";function r(t,n){if(!(this instanceof r))return new r(t,n);if(this.data=t||[],this.length=this.data.length,this.compare=n||o,t)for(var e=Math.floor(this.length/2);e>=0;e--)this._down(e)}function o(t,n){return t<n?-1:t>n?1:0}function i(t,n,e){var r=t[n];t[n]=t[e],t[e]=r}n.exports=r,r.prototype={push:function(t){this.data.push(t),this.length++,this._up(this.length-1)},pop:function(){var t=this.data[0];return this.data[0]=this.data[this.length-1],this.length--,this.data.pop(),this._down(0),t},peek:function(){return this.data[0]},_up:function(t){for(var n=this.data,e=this.compare;t>0;){var r=Math.floor((t-1)/2);if(!(e(n[t],n[r])<0))break;i(n,r,t),t=r}},_down:function(t){for(var n=this.data,e=this.compare,r=this.length;;){var o=2*t+1,a=o+1,u=t;if(o<r&&e(n[o],n[u])<0&&(u=o),a<r&&e(n[a],n[u])<0&&(u=a),u===t)return;i(n,u,t),t=u}}}},{}]},{},[1])(1)});

2
libs/three.min.js vendored

File diff suppressed because one or more lines are too long

37
main.js
View file

@ -604,7 +604,6 @@ void (function addDragToUpload() {
async function generate(options) { async function generate(options) {
try { try {
console.log("--- 1 ---", Math.random());
const timeStart = performance.now(); const timeStart = performance.now();
const {seed: precreatedSeed, graph: precreatedGraph} = options || {}; const {seed: precreatedSeed, graph: precreatedGraph} = options || {};
@ -640,9 +639,7 @@ async function generate(options) {
Biomes.define(); Biomes.define();
rankCells(); rankCells();
console.log("--- 6 ---", Math.random());
Cultures.generate(); Cultures.generate();
console.log("--- 7 ---", Math.random());
Cultures.expand(); Cultures.expand();
BurgsAndStates.generate(); BurgsAndStates.generate();
Religions.generate(); Religions.generate();
@ -866,8 +863,8 @@ function openNearSeaLakes() {
const LIMIT = 22; // max height that can be breached by water const LIMIT = 22; // max height that can be breached by water
for (const i of cells.i) { for (const i of cells.i) {
const lake = cells.f[i]; const lakeFeatureId = cells.f[i];
if (features[lake].type !== "lake") continue; // not a lake cell if (features[lakeFeatureId].type !== "lake") continue; // not a lake
check_neighbours: for (const c of cells.c[i]) { check_neighbours: for (const c of cells.c[i]) {
if (cells.t[c] !== 1 || cells.h[c] > LIMIT) continue; // water cannot break this if (cells.t[c] !== 1 || cells.h[c] > LIMIT) continue; // water cannot break this
@ -875,22 +872,24 @@ function openNearSeaLakes() {
for (const n of cells.c[c]) { for (const n of cells.c[c]) {
const ocean = cells.f[n]; const ocean = cells.f[n];
if (features[ocean].type !== "ocean") continue; // not an ocean if (features[ocean].type !== "ocean") continue; // not an ocean
removeLake(c, lake, ocean); removeLake(c, lakeFeatureId, ocean);
break check_neighbours; break check_neighbours;
} }
} }
} }
function removeLake(threshold, lake, ocean) { function removeLake(thresholdCellId, lakeFeatureId, oceanFeatureId) {
debugger; cells.h[thresholdCellId] = 19;
console.log("removeLake", threshold, lake, ocean); cells.t[thresholdCellId] = -1;
cells.h[threshold] = 19; cells.f[thresholdCellId] = oceanFeatureId;
cells.t[threshold] = -1; cells.c[thresholdCellId].forEach(function (c) {
cells.f[threshold] = ocean;
cells.c[threshold].forEach(function (c) {
if (cells.h[c] >= 20) cells.t[c] = 1; // mark as coastline if (cells.h[c] >= 20) cells.t[c] = 1; // mark as coastline
}); });
features[lake].type = "ocean"; // mark former lake as ocean
cells.i.forEach(i => {
if (cells.f[i] === lakeFeatureId) cells.f[i] = oceanFeatureId;
});
features[lakeFeatureId].type = "ocean"; // mark former lake as ocean
} }
TIME && console.timeEnd("openLakes"); TIME && console.timeEnd("openLakes");
@ -1277,6 +1276,14 @@ function drawCoastline() {
features[f].vertices = vchain; features[f].vertices = vchain;
const path = round(lineGen(points)); const path = round(lineGen(points));
// debug
// .append("path")
// .attr("d", path)
// .attr("id", "feature_" + features[f].type)
// .attr("data-f", f) // draw the lake
// .attr("fill", getRandomColor());
if (features[f].type === "lake") { if (features[f].type === "lake") {
landMask landMask
.append("path") .append("path")
@ -1953,7 +1960,7 @@ function showStatistics() {
mapId = Date.now(); // unique map id is it's creation date number mapId = Date.now(); // unique map id is it's creation date number
mapHistory.push({seed, width: graphWidth, height: graphHeight, template: heightmap, created: mapId}); mapHistory.push({seed, width: graphWidth, height: graphHeight, template: heightmap, created: mapId});
INFO && console.log(stats); INFO && console.info(stats);
} }
const regenerateMap = debounce(async function (options) { const regenerateMap = debounce(async function (options) {

View file

@ -54,8 +54,6 @@ window.Cultures = (function () {
const colors = getColors(count); const colors = getColors(count);
const emblemShape = document.getElementById("emblemShape").value; const emblemShape = document.getElementById("emblemShape").value;
console.log("--- c1 ---", Math.random());
const codes = []; const codes = [];
cultures.forEach(function (c, i) { cultures.forEach(function (c, i) {
@ -73,33 +71,24 @@ window.Cultures = (function () {
return; return;
} }
console.log(JSON.stringify(c, null, 2));
console.log(Array.from(pack.cells.s).join());
const sortingFn = c.sort ? c.sort : i => cells.s[i]; const sortingFn = c.sort ? c.sort : i => cells.s[i];
const center = placeCenter(sortingFn); const center = placeCenter(sortingFn);
console.log("--- c2-1 ---", i, Math.random());
centers.add(cells.p[center]); centers.add(cells.p[center]);
c.center = center; c.center = center;
c.i = newId; c.i = newId;
delete c.odd; delete c.odd;
delete c.sort; delete c.sort;
c.color = colors[i]; c.color = colors[i];
console.log("--- c2-2 ---", i, Math.random());
c.type = defineCultureType(center); c.type = defineCultureType(center);
console.log("--- c2-3 ---", i, Math.random());
c.expansionism = defineCultureExpansionism(c.type); c.expansionism = defineCultureExpansionism(c.type);
c.origins = [0]; c.origins = [0];
c.code = abbreviate(c.name, codes); c.code = abbreviate(c.name, codes);
codes.push(c.code); codes.push(c.code);
cultureIds[center] = newId; cultureIds[center] = newId;
if (emblemShape === "random") c.shield = getRandomShield(); if (emblemShape === "random") c.shield = getRandomShield();
console.log("--- c2-4 ---", i, Math.random());
}); });
console.log("--- c3 ---", Math.random());
cells.culture = cultureIds; cells.culture = cultureIds;
function placeCenter(sortingFn) { function placeCenter(sortingFn) {

View file

@ -60,7 +60,7 @@ window.Cloud = (function () {
async save(fileName, contents) { async save(fileName, contents) {
const resp = await this.call("filesUpload", {path: "/" + fileName, contents}); const resp = await this.call("filesUpload", {path: "/" + fileName, contents});
DEBUG && console.log("Dropbox response:", resp); DEBUG && console.info("Dropbox response:", resp);
return true; return true;
}, },
@ -104,7 +104,7 @@ window.Cloud = (function () {
// Callback function for auth window // Callback function for auth window
async setDropBoxToken(token) { async setDropBoxToken(token) {
DEBUG && console.log("Access token:", token); DEBUG && console.info("Access token:", token);
setToken(this.name, token); setToken(this.name, token);
await this.connect(token); await this.connect(token);
this.authWindow.close(); this.authWindow.close();
@ -131,7 +131,7 @@ window.Cloud = (function () {
allow_download: true allow_download: true
}; };
const resp = await this.call("sharingCreateSharedLinkWithSettings", {path, settings}); const resp = await this.call("sharingCreateSharedLinkWithSettings", {path, settings});
DEBUG && console.log("Dropbox link object:", resp.result); DEBUG && console.info("Dropbox link object:", resp.result);
return resp.result.url; return resp.result.url;
} }
}; };

View file

@ -12,7 +12,7 @@ async function quickLoad() {
async function loadFromDropbox() { async function loadFromDropbox() {
const mapPath = byId("loadFromDropboxSelect")?.value; const mapPath = byId("loadFromDropboxSelect")?.value;
DEBUG && console.log("Loading map from Dropbox:", mapPath); DEBUG && console.info("Loading map from Dropbox:", mapPath);
const blob = await Cloud.providers.dropbox.load(mapPath); const blob = await Cloud.providers.dropbox.load(mapPath);
uploadMap(blob); uploadMap(blob);
} }

View file

@ -28,7 +28,7 @@ window.Submap = (function () {
const projection = options.projection; const projection = options.projection;
const inverse = options.inverse; const inverse = options.inverse;
const stage = s => INFO && console.log("SUBMAP:", s); const stage = s => INFO && console.info("SUBMAP:", s);
const timeStart = performance.now(); const timeStart = performance.now();
invokeActiveZooming(); invokeActiveZooming();
@ -36,7 +36,7 @@ window.Submap = (function () {
seed = parentMap.seed; seed = parentMap.seed;
Math.random = aleaPRNG(seed); Math.random = aleaPRNG(seed);
INFO && console.group("SubMap with seed: " + seed); INFO && console.group("SubMap with seed: " + seed);
DEBUG && console.log("Using Options:", options); DEBUG && console.info("Using Options:", options);
// create new grid // create new grid
applyGraphSize(); applyGraphSize();
@ -396,7 +396,7 @@ window.Submap = (function () {
b.removed = true; b.removed = true;
return; return;
} }
DEBUG && console.log(`Moving ${b.name} from ${cityCell} to ${newCell} near ${neighbor}.`); DEBUG && console.info(`Moving ${b.name} from ${cityCell} to ${newCell} near ${neighbor}.`);
[b.x, b.y] = b.port ? getMiddlePoint(newCell, neighbor) : cells.p[newCell]; [b.x, b.y] = b.port ? getMiddlePoint(newCell, neighbor) : cells.p[newCell];
if (b.port) b.port = cells.f[neighbor]; // copy feature number if (b.port) b.port = cells.f[neighbor]; // copy feature number
b.cell = newCell; b.cell = newCell;

View file

@ -221,9 +221,11 @@ function drawHeightmap() {
const skip = +ocean.attr("skip") + 1 || 1; const skip = +ocean.attr("skip") + 1 || 1;
const relax = +ocean.attr("relax") || 0; const relax = +ocean.attr("relax") || 0;
lineGen.curve(d3[ocean.attr("curve") || "curveBasisClosed"]);
let currentLayer = 0; let currentLayer = 0;
const heights = cells.i.sort((a, b) => cells.h[a] - cells.h[b]); const heights = Array.from(cells.i).sort((a, b) => cells.h[a] - cells.h[b]);
for (const i of heights) { for (const i of heights) {
const h = cells.h[i]; const h = cells.h[i];
if (h > currentLayer) currentLayer += skip; if (h > currentLayer) currentLayer += skip;
@ -248,9 +250,10 @@ function drawHeightmap() {
const skip = +land.attr("skip") + 1 || 1; const skip = +land.attr("skip") + 1 || 1;
const relax = +land.attr("relax") || 0; const relax = +land.attr("relax") || 0;
lineGen.curve(d3[land.attr("curve") || "curveBasisClosed"]);
let currentLayer = 20; let currentLayer = 20;
const heights = cells.i.sort((a, b) => cells.h[a] - cells.h[b]); const heights = Array.from(cells.i).sort((a, b) => cells.h[a] - cells.h[b]);
for (const i of heights) { for (const i of heights) {
const h = cells.h[i]; const h = cells.h[i];
if (h > currentLayer) currentLayer += skip; if (h > currentLayer) currentLayer += skip;
@ -268,8 +271,6 @@ function drawHeightmap() {
} }
} }
return;
// render paths // render paths
for (const height of d3.range(0, 101)) { for (const height of d3.range(0, 101)) {
const group = height < 20 ? ocean : land; const group = height < 20 ? ocean : land;
@ -298,8 +299,6 @@ function drawHeightmap() {
} }
if (paths[height] && paths[height].length >= 10) { if (paths[height] && paths[height].length >= 10) {
const curve = group.attr("curve") || "curveBasisClosed";
lineGen.curve(d3[curve]);
const terracing = group.attr("terracing") / 10 || 0; const terracing = group.attr("terracing") / 10 || 0;
const color = getColor(height, scheme); const color = getColor(height, scheme);

View file

@ -964,7 +964,7 @@ function textureProvideURL() {
} }
function fetchTextureURL(url) { function fetchTextureURL(url) {
INFO && console.log("Provided URL is", url); INFO && console.info("Provided URL is", url);
const img = new Image(); const img = new Image();
img.onload = function () { img.onload = function () {
const canvas = byId("texturePreview"); const canvas = byId("texturePreview");