mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-18 10:01:23 +01:00
fix: bug fixes, 3d mode controls change to MapContol
This commit is contained in:
parent
07d0729cfc
commit
34b880e10f
19 changed files with 398 additions and 182 deletions
|
|
@ -22,25 +22,6 @@ window.Burgs = (() => {
|
|||
pack.burgs = burgs;
|
||||
TIME && console.timeEnd("generateBurgs");
|
||||
|
||||
function getCapitalsNumber() {
|
||||
let number = +byId("statesNumber").value;
|
||||
|
||||
if (populatedCells.length < number * 10) {
|
||||
WARN && console.warn(`Not enough populated cells. Generating only ${number} capitals/states`);
|
||||
number = Math.floor(sorted.length / 10);
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
function getTownsNumber() {
|
||||
const manorsInput = byId("manorsInput");
|
||||
const isAuto = manorsInput.value === "1000"; // '1000' is considered as auto
|
||||
if (isAuto) return rn(populatedCells.length / 5 / (grid.points.length / 10000) ** 0.8);
|
||||
|
||||
return Math.min(manorsInput.valueAsNumber, sorted.length);
|
||||
}
|
||||
|
||||
function generateCapitals() {
|
||||
const randomize = score => score * (0.5 + Math.random() * 0.5);
|
||||
const score = new Int16Array(cells.s.map(randomize));
|
||||
|
|
@ -110,6 +91,25 @@ window.Burgs = (() => {
|
|||
}
|
||||
}
|
||||
|
||||
function getCapitalsNumber() {
|
||||
let number = +byId("statesNumber").value;
|
||||
|
||||
if (populatedCells.length < number * 10) {
|
||||
number = Math.floor(populatedCells.length / 10);
|
||||
WARN && console.warn(`Not enough populated cells. Generating only ${number} capitals/states`);
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
function getTownsNumber() {
|
||||
const manorsInput = byId("manorsInput");
|
||||
const isAuto = manorsInput.value === "1000"; // '1000' is considered as auto
|
||||
if (isAuto) return rn(populatedCells.length / 5 / (grid.points.length / 10000) ** 0.8);
|
||||
|
||||
return Math.min(manorsInput.valueAsNumber, populatedCells.length);
|
||||
}
|
||||
|
||||
// define port status and shift ports and burgs on rivers
|
||||
function shiftBurgs() {
|
||||
const {cells, features} = pack;
|
||||
|
|
@ -321,7 +321,7 @@ window.Burgs = (() => {
|
|||
|
||||
const defaultGroup = options.burgs.groups.find(g => g.isDefault);
|
||||
if (!defaultGroup) {
|
||||
ERROR & console.error("No default group defined");
|
||||
ERROR && console.error("No default group defined");
|
||||
return;
|
||||
}
|
||||
burg.group = defaultGroup.name;
|
||||
|
|
|
|||
|
|
@ -951,7 +951,7 @@ export function resolveVersionConflicts(mapVersion) {
|
|||
.attr("stroke", null);
|
||||
|
||||
// pole can be missing for some states/provinces
|
||||
BurgsAndStates.getPoles();
|
||||
States.getPoles();
|
||||
Provinces.getPoles();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ window.Features = (function () {
|
|||
}
|
||||
|
||||
// add properties to pack features
|
||||
function specify() {
|
||||
function defineGroups() {
|
||||
const gridCellsNumber = grid.cells.i.length;
|
||||
const OCEAN_MIN_SIZE = gridCellsNumber / 25;
|
||||
const SEA_MIN_SIZE = gridCellsNumber / 1000;
|
||||
|
|
@ -223,12 +223,8 @@ window.Features = (function () {
|
|||
for (const feature of pack.features) {
|
||||
if (!feature || feature.type === "ocean") continue;
|
||||
|
||||
if (feature.type === "lake") feature.height = Lakes.getHeight(feature);
|
||||
feature.group = defineGroup(feature);
|
||||
|
||||
if (feature.type === "lake") {
|
||||
feature.height = Lakes.getHeight(feature);
|
||||
feature.name = Lakes.getName(feature);
|
||||
}
|
||||
}
|
||||
|
||||
function defineGroup(feature) {
|
||||
|
|
@ -267,5 +263,5 @@ window.Features = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
return {markupGrid, markupPack, specify};
|
||||
return {markupGrid, markupPack, defineGroups};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -106,11 +106,18 @@ window.Lakes = (function () {
|
|||
return rn(minShoreHeight - LAKE_ELEVATION_DELTA, 2);
|
||||
};
|
||||
|
||||
const defineNames = function () {
|
||||
pack.features.forEach(feature => {
|
||||
if (feature.type !== "lake") return;
|
||||
feature.name = getName(feature);
|
||||
});
|
||||
};
|
||||
|
||||
const getName = function (feature) {
|
||||
const landCell = pack.cells.c[feature.firstCell].find(c => pack.cells.h[c] >= 20);
|
||||
const landCell = feature.shoreline[0];
|
||||
const culture = pack.cells.culture[landCell];
|
||||
return Names.getCulture(culture);
|
||||
};
|
||||
|
||||
return {defineClimateData, cleanupLakeData, detectCloseLakes, getHeight, getName};
|
||||
return {defineClimateData, cleanupLakeData, detectCloseLakes, getHeight, defineNames, getName};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ function createIconGroups() {
|
|||
});
|
||||
|
||||
// create groups for each burg group and apply stored or default style
|
||||
const defaultIconStyle = style.burgIcons.town || Object.values(style.burgIcons)[0];
|
||||
const defaultAnchorStyle = style.anchors.town || Object.values(style.anchors)[0];
|
||||
const defaultIconStyle = style.burgIcons.town || Object.values(style.burgIcons)[0] || {};
|
||||
const defaultAnchorStyle = style.anchors.town || Object.values(style.anchors)[0] || {};
|
||||
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
|
||||
for (const {name} of sortedGroups) {
|
||||
const burgGroup = burgIcons.append("g");
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ function createLabelGroups() {
|
|||
});
|
||||
|
||||
// create groups for each burg group and apply stored or default style
|
||||
const defaultStyle = style.burgLabels.town || Object.values(style.burgLabels)[0];
|
||||
const defaultStyle = style.burgLabels.town || Object.values(style.burgLabels)[0] || {};
|
||||
const sortedGroups = [...options.burgs.groups].sort((a, b) => a.order - b.order);
|
||||
for (const {name} of sortedGroups) {
|
||||
const group = burgLabels.append("g");
|
||||
|
|
|
|||
|
|
@ -187,11 +187,27 @@ window.Resample = (function () {
|
|||
|
||||
function getBurgCoordinates(burg, closestCell, cell, xp, yp) {
|
||||
const haven = pack.cells.haven[cell];
|
||||
if (burg.port && haven) return BurgsAndStates.getCloseToEdgePoint(cell, haven);
|
||||
if (burg.port && haven) return getCloseToEdgePoint(cell, haven);
|
||||
|
||||
if (closestCell !== cell) return pack.cells.p[cell];
|
||||
return [rn(xp, 2), rn(yp, 2)];
|
||||
}
|
||||
|
||||
function getCloseToEdgePoint(cell1, cell2) {
|
||||
const {cells, vertices} = pack;
|
||||
|
||||
const [x0, y0] = cells.p[cell1];
|
||||
const commonVertices = cells.v[cell1].filter(vertex => vertices.c[vertex].some(cell => cell === cell2));
|
||||
const [x1, y1] = vertices.p[commonVertices[0]];
|
||||
const [x2, y2] = vertices.p[commonVertices[1]];
|
||||
const xEdge = (x1 + x2) / 2;
|
||||
const yEdge = (y1 + y2) / 2;
|
||||
|
||||
const x = rn(x0 + 0.95 * (xEdge - x0), 2);
|
||||
const y = rn(y0 + 0.95 * (yEdge - y0), 2);
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
}
|
||||
|
||||
function restoreStates(parentMap, projection) {
|
||||
|
|
@ -202,7 +218,7 @@ window.Resample = (function () {
|
|||
return {...state, removed: true, lock: false};
|
||||
});
|
||||
|
||||
BurgsAndStates.getPoles();
|
||||
States.getPoles();
|
||||
const regimentCellsMap = {};
|
||||
const VERTICAL_GAP = 8;
|
||||
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ window.Routes = (function () {
|
|||
// connect cell with routes system by land
|
||||
function connect(cellId) {
|
||||
const getCost = createCostEvaluator({isWater: false, connections: new Map()});
|
||||
const isExit = cellId => isLand(cellId) && isConnected(cellId);
|
||||
const isExit = c => isLand(c) && isConnected(c);
|
||||
const pathCells = findPath(cellId, isExit, getCost);
|
||||
if (!pathCells) return;
|
||||
|
||||
|
|
@ -372,9 +372,9 @@ window.Routes = (function () {
|
|||
pack.routes.push(newRoute);
|
||||
|
||||
for (let i = 0; i < pathCells.length; i++) {
|
||||
const cellId = pathCells[i];
|
||||
const currentCell = pathCells[i];
|
||||
const nextCellId = pathCells[i + 1];
|
||||
if (nextCellId) addConnection(cellId, nextCellId, routeId);
|
||||
if (nextCellId) addConnection(currentCell, nextCellId, routeId);
|
||||
}
|
||||
|
||||
return newRoute;
|
||||
|
|
@ -446,6 +446,7 @@ window.Routes = (function () {
|
|||
|
||||
const connectivity = Object.values(connections).reduce((acc, routeId) => {
|
||||
const route = pack.routes.find(route => route.i === routeId);
|
||||
if (!route) return acc;
|
||||
const rate = connectivityRateMap[route.group] || connectivityRateMap.default;
|
||||
return acc + rate;
|
||||
}, 0.8);
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ window.States = (() => {
|
|||
function createStates() {
|
||||
const states = [{i: 0, name: "Neutrals"}];
|
||||
const each5th = each(5);
|
||||
const sizeVariety = byId("sizeVariety").valueAsNumber;
|
||||
|
||||
pack.burgs.forEach(burg => {
|
||||
if (!burg.i || !burg.capital) return;
|
||||
|
||||
const expansionism = rn(Math.random() * byId("sizeVariety").value + 1, 1);
|
||||
const expansionism = rn(Math.random() * sizeVariety + 1, 1);
|
||||
const basename = burg.name.length < 9 && each5th(burg.cell) ? burg.name : Names.getCultureShort(burg.culture);
|
||||
const name = Names.getState(basename, burg.culture);
|
||||
const type = pack.cultures[burg.culture].type;
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ window.Submap = (function () {
|
|||
// it's safe to recalculate.
|
||||
stage("Regenerating Biome");
|
||||
Biomes.define();
|
||||
Features.defineGroups();
|
||||
// recalculate suitability and population
|
||||
// TODO: normalize according to the base-map
|
||||
rankCells();
|
||||
|
|
@ -259,7 +260,7 @@ window.Submap = (function () {
|
|||
regenerateRoutes();
|
||||
|
||||
Rivers.specify();
|
||||
Features.specify();
|
||||
Lakes.defineNames();
|
||||
|
||||
stage("Porting military");
|
||||
for (const s of pack.states) {
|
||||
|
|
|
|||
124
modules/ui/3d.js
124
modules/ui/3d.js
|
|
@ -68,10 +68,11 @@ window.ThreeD = (function () {
|
|||
|
||||
// try to clean the memory as much as possible
|
||||
const stop = function () {
|
||||
if (controls) controls.dispose();
|
||||
cancelAnimationFrame(animationFrame);
|
||||
texture.dispose();
|
||||
geometry.dispose();
|
||||
material.dispose();
|
||||
if (texture) texture.dispose();
|
||||
if (geometry) geometry.dispose();
|
||||
if (material) material.dispose();
|
||||
if (waterPlane) waterPlane.dispose();
|
||||
if (waterMaterial) waterMaterial.dispose();
|
||||
deleteLabels();
|
||||
|
|
@ -255,7 +256,6 @@ window.ThreeD = (function () {
|
|||
async function newMesh(canvas) {
|
||||
const loaded = await loadTHREE();
|
||||
if (!loaded) return tip("Cannot load 3d library", false, "error", 4000);
|
||||
|
||||
scene = new THREE.Scene();
|
||||
|
||||
// light
|
||||
|
|
@ -267,7 +267,6 @@ window.ThreeD = (function () {
|
|||
spotLight.shadow.mapSize.width = 2048;
|
||||
spotLight.shadow.mapSize.height = 2048;
|
||||
scene.add(spotLight);
|
||||
// scene.add(new THREE.SpotLightHelper(spotLight));
|
||||
|
||||
// Renderer
|
||||
Renderer = new THREE.WebGLRenderer({canvas, antialias: true, preserveDrawingBuffer: true});
|
||||
|
|
@ -277,22 +276,32 @@ window.ThreeD = (function () {
|
|||
if (options.extendedWater) extendWater(graphWidth, graphHeight);
|
||||
createMesh(graphWidth, graphHeight, grid.cellsX, grid.cellsY);
|
||||
|
||||
// camera
|
||||
camera = new THREE.PerspectiveCamera(70, canvas.width / canvas.height, 0.1, 2000);
|
||||
camera.position.set(0, rn(svgWidth / 3.5), 500);
|
||||
camera.position.set(0, 400, 500); // Set initial camera position for isometric view
|
||||
controls = await MapControls(camera, canvas); // Google Maps-style navigation
|
||||
if (!controls) return false;
|
||||
|
||||
// controls
|
||||
controls = await OrbitControls(camera, canvas);
|
||||
controls.listenToKeyEvents(window);
|
||||
controls.zoomSpeed = 0.25;
|
||||
// Set initial target at map center
|
||||
if (controls.target) controls.target.set(0, 0, 0);
|
||||
|
||||
controls.panSpeed = 0.5;
|
||||
controls.minDistance = 100;
|
||||
// Configure for bird's eye view with Google Maps-style controls
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.05;
|
||||
controls.screenSpacePanning = false;
|
||||
controls.minDistance = 50;
|
||||
controls.maxDistance = 1000;
|
||||
controls.maxPolarAngle = Math.PI / 2;
|
||||
controls.minZoom = 0.05;
|
||||
controls.maxZoom = 4;
|
||||
controls.zoomSpeed = 0.6;
|
||||
controls.panSpeed = 1.6;
|
||||
controls.enableRotate = true;
|
||||
controls.rotateSpeed = 0.5;
|
||||
controls.maxPolarAngle = Math.PI / 2; // Prevent camera from going below horizon
|
||||
controls.minPolarAngle = 0; // Allow full 90 degrees top-down view
|
||||
|
||||
controls.autoRotate = Boolean(options.rotateMesh);
|
||||
controls.autoRotateSpeed = options.rotateMesh;
|
||||
if (controls.autoRotate) animate();
|
||||
animate();
|
||||
|
||||
controls.addEventListener("change", render);
|
||||
return true;
|
||||
|
|
@ -344,10 +353,10 @@ window.ThreeD = (function () {
|
|||
|
||||
const stateOptions = {
|
||||
font: states.attr("font-family"),
|
||||
size: +states.attr("data-size"),
|
||||
size: +states.attr("data-size") / 2,
|
||||
color: states.attr("fill"),
|
||||
elevation: 20,
|
||||
quality: 20
|
||||
quality: 80
|
||||
};
|
||||
|
||||
// Cache icon materials and geometries by group to avoid recreating them
|
||||
|
|
@ -377,7 +386,7 @@ window.ThreeD = (function () {
|
|||
size,
|
||||
color,
|
||||
elevation,
|
||||
quality: 20,
|
||||
quality: 40,
|
||||
iconSize,
|
||||
iconColor
|
||||
};
|
||||
|
|
@ -545,9 +554,20 @@ window.ThreeD = (function () {
|
|||
|
||||
if (texture) texture.dispose();
|
||||
if (!options.wireframe) {
|
||||
texture = new THREE.TextureLoader().load(await createMeshTextureUrl(), render);
|
||||
texture.needsUpdate = true;
|
||||
texture.anisotropy = Renderer.capabilities.getMaxAnisotropy();
|
||||
const url = await createMeshTextureUrl();
|
||||
await new Promise(resolve => {
|
||||
texture = new THREE.TextureLoader().load(
|
||||
url,
|
||||
t => {
|
||||
resolve(t);
|
||||
},
|
||||
undefined,
|
||||
() => resolve(null)
|
||||
);
|
||||
});
|
||||
if (texture) {
|
||||
texture.anisotropy = Renderer.capabilities.getMaxAnisotropy();
|
||||
}
|
||||
}
|
||||
|
||||
if (material) material.dispose();
|
||||
|
|
@ -589,10 +609,11 @@ window.ThreeD = (function () {
|
|||
mesh.castShadow = true;
|
||||
mesh.receiveShadow = true;
|
||||
scene.add(mesh);
|
||||
render();
|
||||
|
||||
if (options.labels3d) {
|
||||
render();
|
||||
await createLabels();
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -671,18 +692,59 @@ window.ThreeD = (function () {
|
|||
// camera
|
||||
camera = new THREE.PerspectiveCamera(45, canvas.width / canvas.height, 0.1, 1000).translateZ(5);
|
||||
|
||||
// controls
|
||||
controls = await OrbitControls(camera, Renderer.domElement);
|
||||
controls = await OrbitControls(camera, Renderer.domElement); // OrbitControls for globe view
|
||||
if (!controls) return false;
|
||||
controls.zoomSpeed = 0.25;
|
||||
controls.minDistance = 1.5;
|
||||
controls.maxDistance = 10;
|
||||
controls.autoRotate = Boolean(options.rotateGlobe);
|
||||
controls.autoRotateSpeed = options.rotateGlobe;
|
||||
|
||||
// ensure OrbitControls behavior (reset potentially changed defaults by MapControls)
|
||||
controls.mouseButtons = {
|
||||
LEFT: THREE.MOUSE.ROTATE,
|
||||
MIDDLE: THREE.MOUSE.DOLLY,
|
||||
RIGHT: THREE.MOUSE.PAN
|
||||
};
|
||||
controls.screenSpacePanning = true;
|
||||
controls.minPolarAngle = 0;
|
||||
controls.maxPolarAngle = Math.PI;
|
||||
|
||||
controls.addEventListener("change", render);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function OrbitControls(camera, domElement) {
|
||||
if (THREE.OrbitControls) return new THREE.OrbitControls(camera, domElement);
|
||||
|
||||
return new Promise(resolve => {
|
||||
const script = document.createElement("script");
|
||||
script.src = "libs/orbitControls.min.js";
|
||||
document.head.append(script);
|
||||
script.onload = () => resolve(new THREE.OrbitControls(camera, domElement));
|
||||
script.onerror = () => resolve(false);
|
||||
});
|
||||
}
|
||||
|
||||
function MapControls(camera, domElement) {
|
||||
if (THREE.MapControls) return new THREE.MapControls(camera, domElement);
|
||||
|
||||
return new Promise(resolve => {
|
||||
const script = document.createElement("script");
|
||||
script.src = "libs/mapControls.min.js";
|
||||
document.head.append(script);
|
||||
script.onload = () => {
|
||||
if (THREE.MapControls) {
|
||||
resolve(new THREE.MapControls(camera, domElement));
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
};
|
||||
script.onerror = () => resolve(false);
|
||||
});
|
||||
}
|
||||
|
||||
async function updateGlobeTexure(addMesh) {
|
||||
const world = mapCoordinates.latT > 179; // define if map covers whole world
|
||||
|
||||
|
|
@ -751,7 +813,7 @@ window.ThreeD = (function () {
|
|||
// animate 3d scene and camera
|
||||
function animate() {
|
||||
animationFrame = requestAnimationFrame(animate);
|
||||
controls.update();
|
||||
if (controls && controls.update) controls.update();
|
||||
}
|
||||
|
||||
function loadTHREE() {
|
||||
|
|
@ -778,18 +840,6 @@ window.ThreeD = (function () {
|
|||
});
|
||||
}
|
||||
|
||||
function OrbitControls(camera, domElement) {
|
||||
if (THREE.OrbitControls) return new THREE.OrbitControls(camera, domElement);
|
||||
|
||||
return new Promise(resolve => {
|
||||
const script = document.createElement("script");
|
||||
script.src = "libs/orbitControls.min.js";
|
||||
document.head.append(script);
|
||||
script.onload = () => resolve(new THREE.OrbitControls(camera, domElement));
|
||||
script.onerror = () => resolve(false);
|
||||
});
|
||||
}
|
||||
|
||||
function OBJExporter() {
|
||||
if (THREE.OBJExporter) return new THREE.OBJExporter();
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ function editBurgGroups() {
|
|||
<option value="" ${!group.preview ? "selected" : ""}>no</option>
|
||||
<option value="watabou-city" ${group.preview === "watabou-city" ? "selected" : ""}>Watabou City</option>
|
||||
<option value="watabou-village" ${group.preview === "watabou-village" ? "selected" : ""}>Watabou Village</option>
|
||||
<option value="watabou-dwelling" ${group.preview === "watabou-dwellings" ? "selected" : ""}>Watabou Dwelling</option>
|
||||
<option value="watabou-dwelling" ${group.preview === "watabou-dwelling" ? "selected" : ""}>Watabou Dwelling</option>
|
||||
</select>
|
||||
</td>
|
||||
<td data-tip="Set min population constraint"><input type="number" name="min" min="0" step="any" value="${group.min || ''}" /></td>
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ function editHeightmap(options) {
|
|||
}
|
||||
|
||||
Biomes.define();
|
||||
Features.defineGroups();
|
||||
|
||||
rankCells();
|
||||
Cultures.generate();
|
||||
|
|
@ -256,7 +257,7 @@ function editHeightmap(options) {
|
|||
Provinces.getPoles();
|
||||
|
||||
Rivers.specify();
|
||||
Features.specify();
|
||||
Lakes.defineNames();
|
||||
|
||||
Military.generate();
|
||||
Markers.generate();
|
||||
|
|
@ -345,7 +346,10 @@ function editHeightmap(options) {
|
|||
reGraph();
|
||||
Features.markupPack();
|
||||
|
||||
if (erosionAllowed) Rivers.generate(true);
|
||||
if (erosionAllowed) {
|
||||
Rivers.generate(true);
|
||||
Features.defineGroups();
|
||||
}
|
||||
|
||||
// assign saved pack data from grid back to pack
|
||||
const n = pack.cells.i.length;
|
||||
|
|
@ -439,7 +443,7 @@ function editHeightmap(options) {
|
|||
|
||||
if (erosionAllowed) {
|
||||
Rivers.specify();
|
||||
Features.specify();
|
||||
Lakes.defineNames();
|
||||
}
|
||||
|
||||
// restore zones from grid
|
||||
|
|
|
|||
|
|
@ -987,8 +987,7 @@ async function enter3dView(type) {
|
|||
|
||||
canvas.style.display = "block";
|
||||
canvas.onmouseenter = () => {
|
||||
const help =
|
||||
"Left mouse to change angle, middle mouse. Mousewheel to zoom. Right mouse or hold Shift to pan. <b>O</b> to toggle options";
|
||||
const help = "Drag to pan • Scroll to zoom • Right-click drag to rotate • <b>O</b> to toggle options";
|
||||
+canvas.dataset.hovered > 2 ? tip("") : tip(help);
|
||||
canvas.dataset.hovered = (+canvas.dataset.hovered | 0) + 1;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ function regenerateRoutes() {
|
|||
function regenerateRivers() {
|
||||
Rivers.generate();
|
||||
Rivers.specify();
|
||||
Features.specify();
|
||||
Features.defineGroups();
|
||||
Lakes.defineNames();
|
||||
if (layerIsOn("toggleRivers")) drawRivers();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ function editWorld() {
|
|||
Rivers.specify();
|
||||
pack.cells.h = new Float32Array(heights);
|
||||
Biomes.define();
|
||||
Features.specify();
|
||||
Features.defineGroups();
|
||||
Lakes.defineNames();
|
||||
|
||||
if (layerIsOn("toggleTemperature")) drawTemperature();
|
||||
if (layerIsOn("togglePrecipitation")) drawPrecipitation();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue