3d preview to Heightmap editor (#329)

This commit is contained in:
evolvedexperiment 2019-10-17 22:12:16 +02:00 committed by Azgaar
parent efd9159737
commit 0e308079aa
8 changed files with 51152 additions and 2 deletions

150
modules/ui/3dutils.js Normal file
View file

@ -0,0 +1,150 @@
var _3dheightMapExponent = null;
var _3dmaxHeight = null;
var _3dcolorLookup = null;
function _2dto1d(source) {
var r = [];
var w = source[0].length;
var h = source.length;
var i=0;
for (var y=0; y < h; y++) {
for (var x=0; x < w; x++) {
r[i] = source[y][x];
i++;
}
}
return r;
}
function _1dto2d(source, w, h) {
var r = [];
var i=0;
for (var y=0; y < h; y++) {
r[y] = [];
for (var x=0; x < w; x++) {
r[y][x] = source[i];
i++;
}
}
return r;
}
function getSVGImage(type, width, height) {
// clone svg
const cloneEl = document.getElementById("map").cloneNode(true);
cloneEl.id = "fantasyMap";
document.getElementsByTagName("body")[0].appendChild(cloneEl);
const clone = d3.select("#fantasyMap");
if (type === "svg") {
clone.select("#viewbox").attr("transform", null); // reset transform to show whole map
}
clone.attr("width", width).attr("height", height);
// remove unused elements
if (!clone.select("#terrain").selectAll("use").size()) clone.select("#defs-relief").remove();
if (!clone.select("#prec").selectAll("circle").size()) clone.select("#prec").remove();
if (!clone.select("#scaleBar").selectAll("use").size()) clone.select("#scaleBar").remove();
// default to water - on Firefox, ocean pattern appears as alternating blocks of ocean and water pattern
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox) {
if (!clone.select("#oceanPattern").selectAll("use").size()) clone.select("#oceanPattern").remove();
}
const removeEmptyGroups = function() {
let empty = 0;
clone.selectAll("g").each(function() {
if (!this.hasChildNodes() || this.style.display === "none") {empty++; this.remove();}
if (this.hasAttribute("display") && this.style.display === "inline") this.removeAttribute("display");
});
return empty;
}
while(removeEmptyGroups()) {removeEmptyGroups();}
// for each g element get inline style
const emptyG = clone.append("g").node();
const defaultStyles = window.getComputedStyle(emptyG);
clone.selectAll("g, #ruler > g > *, #scaleBar > text").each(function(d) {
const compStyle = window.getComputedStyle(this);
let style = "";
for (let i=0; i < compStyle.length; i++) {
const key = compStyle[i];
const value = compStyle.getPropertyValue(key);
// Firefox mask hack
if (key === "mask-image" && value !== defaultStyles.getPropertyValue(key)) {
style += "mask-image: url('#land');";
continue;
}
if (key === "cursor") continue; // cursor should be default
if (this.hasAttribute(key)) continue; // don't add style if there is the same attribute
if (value === defaultStyles.getPropertyValue(key)) continue;
style += key + ':' + value + ';';
}
if (style != "") this.setAttribute('style', style);
});
emptyG.remove();
// load fonts as dataURI so they will be available in downloaded svg/png
const svg_xml = (new XMLSerializer()).serializeToString(clone.node());
clone.remove();
const blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'});
const url = window.URL.createObjectURL(blob);
return url;
}
function getHeightmap() {
var mh = 0;
grid.cells.h.forEach((height, i) => {
h = grid.cells.h[i];
if (h > mh) mh = h;
});
if (mh > 82) { mh = 82; }
_3dheightMapExponent = heightExponentInput.value;
// _3dmaxHeight = Math.pow(mh, _3dheightMapExponent);
_3dmaxHeight = Math.pow(82, _3dheightMapExponent);
var heightMap = [];
for (var y=0; y < grid.cellsY; y++) {
heightMap[y] = [];
}
var y = 0, x = 0;
// convert height from map heights to a linear height
grid.cells.h.forEach((height, i) => {
h = grid.cells.h[i];
// add heightmap exponent
if (h >= 20) height = Math.pow(h - 18, _3dheightMapExponent);
// else if (h > 0) height = (h - 20) / h * 50;
else height = 0;
// get heightmap as a percentage
let v = (height / _3dmaxHeight);
// convert to 0-255
v = (v * 255);
heightMap[y][x] = Math.floor(v);
x++;
if (x >= grid.cellsX) { x = 0; y++ }
});
var hm = _2dto1d(heightMap);
return hm;
}
function getPreviewTexture(width, height) {
return getSVGImage("svg", width, height);
}