diff --git a/modules/ui/3d.js b/modules/ui/3d.js
index 42552f2d..898e02f2 100644
--- a/modules/ui/3d.js
+++ b/modules/ui/3d.js
@@ -11,7 +11,7 @@ const options = {scale: 50, lightness: .7, shadow: .5, sun: {x: 100, y: 600, z:
// set variables
let Renderer, scene, camera, controls, animationFrame, material, texture,
geometry, mesh, ambientLight, spotLight, waterPlane, waterMaterial, waterMesh,
- objexporter;
+ objexporter, square_geometry, texture_loader;
const drawSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg");
document.body.appendChild(drawSVG);
let textMeshs = [], iconMeshs = [];
@@ -116,14 +116,14 @@ const toggleSky = function() {
}
const toggleLabels = function() {
+ options.labels3d = !options.labels3d;
+
if (options.labels3d) {
+ createLabels().then(() => update());
+ } else {
deleteLabels();
update();
- } else {
- createLabels().then(() => update());
}
-
- options.labels3d = !options.labels3d;
}
const setColors = function(sky, water) {
@@ -207,14 +207,14 @@ function svg2mesh(svg, sx=1, sy=1) {
svg.setAttribute("width", bbox.width);
svg.setAttribute("height", bbox.height);
- const texture = new THREE.TextureLoader().load(svg2base64(svg));
+ const texture = new texture_loader.load(svg2base64(svg));
texture.minFilter = THREE.LinearFilter; // remove `texture has been resized` warning
- const material = new THREE.MeshBasicMaterial({map: texture, side:THREE.DoubleSide, depthWrite: false});
+ const material = new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide, depthWrite: false});
material.transparent = true;
const mesh = new THREE.Mesh(
- new THREE.PlaneGeometry(1, 1),
+ square_geometry,
material
);
mesh.scale.x = bbox.width * (sx / 100);
@@ -227,7 +227,7 @@ function svg2mesh(svg, sx=1, sy=1) {
async function createStateText(font, size, color, label) {
drawSVG.innerHTML = "";
drawSVG.appendChild(label.cloneNode(true));
- if (fontCache[font] == undefined) {fontCache[font] = await GFontToDataURI(`https://fonts.googleapis.com/css?family=${font}`)}
+ if (fontCache[font] == undefined) {fontCache[font] = (await GFontToDataURI(`https://fonts.googleapis.com/css?family=${font}`)).join('\n');}
drawSVG.children[0].innerHTML = ``;
drawSVG.children[0].appendChild(svg.select(label.childNodes[0].href.baseVal).node().cloneNode(true)); // href of path in defs
drawSVG.children[1].setAttribute("transform", `scale(${5} ${5})`)
@@ -241,11 +241,11 @@ async function createStateText(font, size, color, label) {
return mesh;
}
-async function createBurgText(text, font, size, color) {
- if (fontCache[font] == undefined) {fontCache[font] = await GFontToDataURI(`https://fonts.googleapis.com/css?family=${font}`)}
- drawSVG.innerHTML = `${text}
+async function createBurgText(text, font, size, color, quality=1) { // for quality: lower value mean higher quality
+ if (fontCache[font] == undefined) {fontCache[font] = (await GFontToDataURI(`https://fonts.googleapis.com/css?family=${font}`)).join("\n");}
+ drawSVG.innerHTML = `${text}
`;
- return svg2mesh(drawSVG, 7*2, 7*2);
+ return svg2mesh(drawSVG, 7*quality, 7*quality);
}
function get3dCoords(base_x, base_y) {
@@ -256,12 +256,19 @@ function get3dCoords(base_x, base_y) {
}
async function createLabels() {
+ square_geometry = new THREE.PlaneGeometry(1, 1);
+ texture_loader = new THREE.TextureLoader();
+
// Burg labels
const cities = svg.select("#viewbox #labels #burgLabels #cities");
const towns = svg.select('#viewbox #labels #burgLabels #towns');
const cities_icons = svg.select('#viewbox #icons #burgIcons #cities');
const towns_icons = svg.select('#viewbox #icons #burgIcons #towns');
+ const citie_icon_material = new THREE.MeshBasicMaterial({color: cities_icons.attr('fill')});
+ const town_icon_material = new THREE.MeshBasicMaterial({color: towns_icons.attr('fill')});
+ const citie_icon_geometry = new THREE.SphereGeometry(cities_icons.attr("size") * 2, 16, 16);
+ const town_icon_geometry = new THREE.SphereGeometry(towns_icons.attr("size") * 2, 16, 16);
for (const burg of pack.burgs) {
const [x, y, z] = get3dCoords(burg.x, burg.y)
@@ -300,10 +307,9 @@ async function createLabels() {
// Icon
if(layerIsOn("toggleIcons")) {
- const icon_material = new THREE.MeshBasicMaterial({color: burg.capital ? cities_icons.attr('fill') : towns_icons.attr('fill')});
const icon_mesh = new THREE.Mesh(
- new THREE.SphereGeometry((burg.capital ? cities_icons.attr("size") : towns_icons.attr("size")) * 2, 16, 16),
- icon_material
+ burg.capital ? citie_icon_geometry : town_icon_geometry,
+ burg.capital ? citie_icon_material : town_icon_material
);
icon_mesh.position.set(x, y, z)
icon_mesh.base_x = burg.x
@@ -332,18 +338,31 @@ async function createLabels() {
}
function deleteLabels() {
- for (const mesh of textMeshs) {
+ if (square_geometry) square_geometry.dispose();
+ square_geometry = undefined;
+ texture_loader = undefined;
+
+ for (const [i, mesh] of textMeshs.entries()) {
+ scene.remove(mesh);
mesh.material.map.dispose();
mesh.material.dispose();
mesh.geometry.dispose();
- scene.remove(mesh);
+ delete mesh.material.map;
+ delete mesh.material;
+ delete mesh.geometry;
+ delete textMeshs[i];
}
+ textMeshs = [];
- for (const mesh of iconMeshs) {
+ for (const [i, mesh] of iconMeshs.entries()) {
+ scene.remove(mesh);
mesh.material.dispose();
mesh.geometry.dispose();
- scene.remove(mesh);
+ delete mesh.material;
+ delete mesh.geometry;
+ delete iconMeshs[i];
}
+ iconMeshs = [];
}
// create a mesh from pixel data
@@ -376,8 +395,6 @@ async function createMesh(width, height, segmentsX, segmentsY) {
scene.add(mesh);
deleteLabels();
- textMeshs = [];
- iconMeshs = [];
if (options.labels3d) {
await createLabels();