let SEED = "" + new Date().getTime();
createCanvas(windowWidth, windowHeight);
Math.random = function() {
Math.seed = function(x) {
SEED = x == "" ? SEED : x;
var Prng = new function() {
this.m = this.p * this.q;
this.hash = function(x) {
var y = window.btoa(JSON.stringify(x));
for (var i = 0; i < y.length; i++) {
z += y.charCodeAt(i) * Math.pow(128, i);
this.seed = function(x) {
x = new Date().getTime();
y = (Prng.hash(x) + z) % Prng.m;
while (y % Prng.p == 0 || y % Prng.q == 0 || y == 0 || y == 1) {
console.log(["int seed", x, Prng.s]);
for (var i = 0; i < 10; i++) {
Prng.s = (Prng.s * Prng.s) % Prng.m;
this.test = function(f) {
var t0 = new Date().getTime();
var chart = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (var i = 0; i < 10000000; i++) {
chart[Math.floor(F() * 10)] += 1;
console.log("finished in " + (new Date().getTime() - t0));
function parseArgs(key2f) {
var par = window.location.href.split("?")[1];
for (var i = 0; i < par.length; i++) {
var e = par[i].split("=");
var PolyTools = new function() {
this.midPt = function() {
arguments.length == 1 ? arguments[0] : Array.apply(null, arguments);
return [v[0] / plist.length + acc[0], v[1] / plist.length + acc[1]];
this.triangulate = function(plist, args) {
var args = args != undefined ? args : {};
var area = args.area != undefined ? args.area : 100;
var convex = args.convex != undefined ? args.convex : false;
var optimize = args.optimize != undefined ? args.optimize : true;
function lineExpr(pt0, pt1) {
var den = pt1[0] - pt0[0];
var m = den == 0 ? Infinity : (pt1[1] - pt0[1]) / den;
var k = pt0[1] - m * pt0[0];
function intersect(ln0, ln1) {
var le0 = lineExpr(...ln0);
var le1 = lineExpr(...ln1);
var den = le0[0] - le1[0];
var x = (le1[1] - le0[1]) / den;
var y = le0[0] * x + le0[1];
Math.min(ln[0][0], ln[1][0]) <= p[0] &&
p[0] <= Math.max(ln[0][0], ln[1][0]) &&
Math.min(ln[0][1], ln[1][1]) <= p[1] &&
p[1] <= Math.max(ln[0][1], ln[1][1])
if (onSeg([x, y], ln0) && onSeg([x, y], ln1)) {
function ptInPoly(pt, plist) {
for (var i = 0; i < plist.length; i++) {
var np = plist[i != plist.length - 1 ? i + 1 : 0];
[pt, [pt[0] + 999, pt[1] + 999]],
function lnInPoly(ln, plist) {
var lnc = [[0, 0], [0, 0]];
lnc[0][0] = ln[0][0] * (1 - ep) + ln[1][0] * ep;
lnc[0][1] = ln[0][1] * (1 - ep) + ln[1][1] * ep;
lnc[1][0] = ln[0][0] * ep + ln[1][0] * (1 - ep);
lnc[1][1] = ln[0][1] * ep + ln[1][1] * (1 - ep);
for (var i = 0; i < plist.length; i++) {
var np = plist[i != plist.length - 1 ? i + 1 : 0];
if (intersect(lnc, [pt, np]) != false) {
var mid = PolyTools.midPt(ln);
if (ptInPoly(mid, plist) == false) {
function sidesOf(plist) {
for (var i = 0; i < plist.length; i++) {
var np = plist[i != plist.length - 1 ? i + 1 : 0];
Math.pow(np[0] - pt[0], 2) + Math.pow(np[1] - pt[1], 2),
var slist = sidesOf(plist);
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
function sliverRatio(plist) {
var P = sidesOf(plist).reduce(function(m, n) {
function bestEar(plist) {
for (var i = 0; i < plist.length; i++) {
var lp = plist[i != 0 ? i - 1 : plist.length - 1];
var np = plist[i != plist.length - 1 ? i + 1 : 0];
var qlist = plist.slice();
if (convex || lnInPoly([lp, np], plist)) {
var c = [[lp, pt, np], qlist];
for (var i = 0; i < cuts.length; i++) {
var r = sliverRatio(cuts[i][0]);
function shatter(plist, a) {
var slist = sidesOf(plist);
(iMax, x, i, arr) => (x > arr[iMax] ? i : iMax),
var nind = (ind + 1) % plist.length;
var lind = (ind + 2) % plist.length;
var mid = PolyTools.midPt([plist[ind], plist[nind]]);
return shatter([plist[ind], mid, plist[lind]], a).concat(
shatter([plist[lind], plist[nind], mid], a),
return shatter(plist, area);
var cut = bestEar(plist);
return shatter(cut[0], area).concat(
PolyTools.triangulate(cut[1], args),
function distance(p0, p1) {
return Math.sqrt(Math.pow(p0[0] - p1[0], 2) + Math.pow(p0[1] - p1[1], 2));
function loopNoise(nslist) {
var dif = nslist[nslist.length - 1] - nslist[0];
for (var i = 0; i < nslist.length; i++) {
nslist[i] += (dif * (nslist.length - 1 - i)) / (nslist.length - 1);
if (nslist[i] < bds[0]) bds[0] = nslist[i];
if (nslist[i] > bds[1]) bds[1] = nslist[i];
for (var i = 0; i < nslist.length; i++) {
nslist[i] = map(nslist[i], bds[0], bds[1], 0, 1);
function randChoice(arr) {
return arr[Math.floor(arr.length * Math.random())];
function normRand(m, M) {
return map(Math.random(), 0, 1, m, M);
function randGaussian() {
return Math.pow(Math.E, -24 * Math.pow(x - 0.5, 2));
w = w == undefined ? 1 : w;
P = [P[0], PolyTools.midPt(P[0], P[1]), P[1]];
for (var j = 0; j < P.length - 2; j++) {
p0 = PolyTools.midPt(P[j], P[j + 1]);
p2 = PolyTools.midPt(P[j + 1], P[j + 2]);
for (var i = 0; i < pl + (j == P.length - 3); i += 1) {
var u = Math.pow(1 - t, 2) + 2 * t * (1 - t) * w + t * t;
(Math.pow(1 - t, 2) * p0[0] +
2 * t * (1 - t) * p1[0] * w +
(Math.pow(1 - t, 2) * p0[1] +
2 * t * (1 - t) * p1[1] * w +
function poly(plist, args) {
var args = args != undefined ? args : {};
var xof = args.xof != undefined ? args.xof : 0;
var yof = args.yof != undefined ? args.yof : 0;
var fil = args.fil != undefined ? args.fil : "rgba(0,0,0,0)";
var str = args.str != undefined ? args.str : fil;
var wid = args.wid != undefined ? args.wid : 0;
for (var i = 0; i < plist.length; i++) {
vertex((plist[i][0] + xof).toFixed(1), (plist[i][1] + yof).toFixed(1))
function mystroke(ptlist, args) {
var args = args != undefined ? args : {};
var xof = args.xof != undefined ? args.xof : 0;
var yof = args.yof != undefined ? args.yof : 0;
var wid = args.wid != undefined ? args.wid : 2;
var col = args.col != undefined ? args.col : "rgba(200,200,200,0.9)";
var noi = args.noi != undefined ? args.noi : 0.5;
var out = args.out != undefined ? args.out : 1;
return Math.sin(x * Math.PI);
if (ptlist.length == 0) {
var n0 = Math.random() * 10;
for (var i = 1; i < ptlist.length - 1; i++) {
var w = wid * fun(i / ptlist.length);
w = w * (1 - noi) + w * noi * noise(i * 0.5, n0);
ptlist[i][1] - ptlist[i - 1][1],
ptlist[i][0] - ptlist[i - 1][0],
ptlist[i][1] - ptlist[i + 1][1],
ptlist[i][0] - ptlist[i + 1][0],
ptlist[i][0] + w * Math.cos(a),
ptlist[i][1] + w * Math.sin(a),
ptlist[i][0] - w * Math.cos(a),
ptlist[i][1] - w * Math.sin(a),
vtxlist0.concat(vtxlist1.concat([ptlist[ptlist.length - 1]]).reverse()),
vtxlist.map(function(x) {
return [x[0] + xof, x[1] + yof];
{ fil: col, str: col, wid: out },
function blob(x, y, args) {
var args = args != undefined ? args : {};
var len = args.len != undefined ? args.len : 20;
var wid = args.wid != undefined ? args.wid : 5;
var ang = args.ang != undefined ? args.ang : 0;
var col = args.col != undefined ? args.col : "rgba(200,200,200,0.9)";
var noi = args.noi != undefined ? args.noi : 0.5;
var ret = args.ret != undefined ? args.ret : 0;
? Math.pow(Math.sin(x * Math.PI), 0.5)
: -Math.pow(Math.sin((x + 1) * Math.PI), 0.5);
for (var i = 0; i < reso + 1; i++) {
var xo = len / 2 - Math.abs(p - 1) * len;
var yo = (fun(p) * wid) / 2;
var a = Math.atan2(yo, xo);
var l = Math.sqrt(xo * xo + yo * yo);
var n0 = Math.random() * 10;
for (var i = 0; i < reso + 1; i++) {
nslist.push(noise(i * 0.05, n0));
for (var i = 0; i < lalist.length; i++) {
var ns = nslist[i] * noi + (1 - noi);
var nx = x + Math.cos(lalist[i][1] + ang) * lalist[i][0] * ns;
var ny = y + Math.sin(lalist[i][1] + ang) * lalist[i][0] * ns;
return poly(plist, { fil: col, str: col, wid: 0 });
function div(plist, reso) {
var tl = (plist.length - 1) * reso;
for (var i = 0; i < tl; i += 1) {
var lastp = plist[Math.floor(i / reso)];
var nextp = plist[Math.ceil(i / reso)];
var p = (i % reso) / reso;
var nx = lastp[0] * (1 - p) + nextp[0] * p;
var ny = lastp[1] * (1 - p) + nextp[1] * p;
var ang = Math.atan2(ny - ly, nx - lx);
rlist.push(plist[plist.length - 1]);
var mytexture = function(ptlist, args) {
var args = args != undefined ? args : {};
var xof = args.xof != undefined ? args.xof : 0;
var yof = args.yof != undefined ? args.yof : 0;
var tex = args.tex != undefined ? args.tex : 400;
var wid = args.wid != undefined ? args.wid : 1.5;
var len = args.len != undefined ? args.len : 0.2;
var sha = args.sha != undefined ? args.sha : 0;
var ret = args.ret != undefined ? args.ret : 0;
return "rgba(100,100,100," + (Math.random() * 0.3).toFixed(3) + ")";
if (Math.random() > 0.5) {
return (1 / 3) * Math.random();
return (1 * 2) / 3 + (1 / 3) * Math.random();
var reso = [ptlist.length, ptlist[0].length];
for (var i = 0; i < tex; i++) {
var mid = (dis() * reso[1]) | 0;
var hlen = Math.floor(Math.random() * (reso[1] * len));
start = Math.min(Math.max(start, 0), reso[1]);
end = Math.min(Math.max(end, 0), reso[1]);
var layer = (i / tex) * (reso[0] - 1);
for (var j = start; j < end; j++) {
var p = layer - Math.floor(layer);
ptlist[Math.floor(layer)][j][0] * p +
ptlist[Math.ceil(layer)][j][0] * (1 - p);
ptlist[Math.floor(layer)][j][1] * p +
ptlist[Math.ceil(layer)][j][1] * (1 - p);
noi(layer + 1) * (noise(x, j * 0.5) - 0.5),
noi(layer + 1) * (noise(y, j * 0.5) - 0.5),
texlist[texlist.length - 1].push([x + ns[0], y + ns[1]]);
for (var j = 0; j < texlist.length; j += 1 + (sha != 0)) {
texlist[j].map(function(x) {
return [x[0] + xof, x[1] + yof];
{ col: "rgba(100,100,100,0.1)", wid: sha },
for (var j = 0 + sha; j < texlist.length; j += 1 + sha) {
texlist[j].map(function(x) {
return [x[0] + xof, x[1] + yof];
{ col: col(j / texlist.length), wid: wid },
return ret ? texlist : canv;
var Tree = new function() {
this.tree01 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 50;
var wid = args.wid != undefined ? args.wid : 3;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
for (var i = 0; i < reso; i++) {
nslist.push([noise(i * 0.5), noise(i * 0.5, 0.5)]);
if (col.includes("rgba(")) {
leafcol = ["100", "100", "100", "0.5"];
for (var i = 0; i < reso; i++) {
var ny = y - (i * hei) / reso;
for (var j = 0; j < (reso - i) / 5; j++) {
nx + (Math.random() - 0.5) * wid * 1.2 * (reso - i),
ny + (Math.random() - 0.5) * wid,
len: Math.random() * 20 * (reso - i) * 0.2 + 10,
wid: Math.random() * 6 + 3,
ang: ((Math.random() - 0.5) * Math.PI) / 6,
(Math.random() * 0.2 + parseFloat(leafcol[3])).toFixed(1) +
line1.push([nx + (nslist[i][0] - 0.5) * wid - wid / 2, ny]);
line2.push([nx + (nslist[i][1] - 0.5) * wid + wid / 2, ny]);
poly(line1, { fil: "none", str: col, wid: 1.5 }) +
poly(line2, { fil: "none", str: col, wid: 1.5 });
this.tree02 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 16;
var wid = args.wid != undefined ? args.wid : 8;
var clu = args.clu != undefined ? args.clu : 5;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
if (col.includes("rgba(")) {
leafcol = ["100", "100", "100", "0.5"];
for (var i = 0; i < clu; i++) {
x + randGaussian() * clu * 4,
y + randGaussian() * clu * 4,
col: "rgba(100,100,100,0.8)",
? Math.pow(Math.sin(x * Math.PI) * x, 0.5)
: -Math.pow(Math.sin((x - 2) * Math.PI * (x - 2)), 0.5);
wid: Math.random() * wid * 0.75 + wid * 0.5,
len: Math.random() * hei * 0.75 + hei * 0.5,
this.tree03 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 50;
var wid = args.wid != undefined ? args.wid : 5;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
for (var i = 0; i < reso; i++) {
nslist.push([noise(i * 0.5), noise(i * 0.5, 0.5)]);
if (col.includes("rgba(")) {
leafcol = ["100", "100", "100", "0.5"];
for (var i = 0; i < reso; i++) {
var nx = x + ben(i / reso) * 100;
var ny = y - (i * hei) / reso;
for (var j = 0; j < (reso - i) * 2; j++) {
var shape = function(x) {
return Math.log(50 * x + 1) / 3.95;
var ox = Math.random() * wid * 2 * shape((reso - i) / reso);
nx + ox * randChoice([-1, 1]),
ny + (Math.random() - 0.5) * wid * 2,
wid: Math.random() * 6 + 3,
ang: ((Math.random() - 0.5) * Math.PI) / 6,
(Math.random() * 0.2 + parseFloat(leafcol[3])).toFixed(3) +
nx + (((nslist[i][0] - 0.5) * wid - wid / 2) * (reso - i)) / reso,
nx + (((nslist[i][1] - 0.5) * wid + wid / 2) * (reso - i)) / reso,
var lc = line1.concat(line2.reverse());
canv += poly(lc, { fil: "white", str: col, wid: 1.5 });
var branch = function(args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 300;
var wid = args.wid != undefined ? args.wid : 6;
var ang = args.ang != undefined ? args.ang : 0;
var det = args.det != undefined ? args.det : 10;
var ben = args.ben != undefined ? args.ben : Math.PI * 0.2;
for (var i = 0; i < g; i++) {
a0 += (ben / 2 + (Math.random() * ben) / 2) * randChoice([-1, 1]);
nx += (Math.cos(a0) * hei) / g;
ny -= (Math.sin(a0) * hei) / g;
tlist[tlist.length - 1][1],
tlist[tlist.length - 1][0],
for (var i = 0; i < tlist.length; i++) {
var a = Math.atan2(tlist[i][1], tlist[i][0]);
tlist[i][0] * tlist[i][0] + tlist[i][1] * tlist[i][1],
tlist[i][0] = d * Math.cos(a - ta + ang);
tlist[i][1] = d * Math.sin(a - ta + ang);
var tl = (tlist.length - 1) * span;
for (var i = 0; i < tl; i += 1) {
var lastp = tlist[Math.floor(i / span)];
var nextp = tlist[Math.ceil(i / span)];
var p = (i % span) / span;
var nx = lastp[0] * (1 - p) + nextp[0] * p;
var ny = lastp[1] * (1 - p) + nextp[1] * p;
var ang = Math.atan2(ny - ly, nx - lx);
var woff = ((noise(i * 0.3) - 0.5) * wid * hei) / 80;
var nw = wid * (((tl - i) / tl) * 0.5 + 0.5);
nx + Math.cos(ang + Math.PI / 2) * (nw + woff + b),
ny + Math.sin(ang + Math.PI / 2) * (nw + woff + b),
nx + Math.cos(ang - Math.PI / 2) * (nw - woff + b),
ny + Math.sin(ang - Math.PI / 2) * (nw - woff + b),
return [trlist1, trlist2];
var twig = function(tx, ty, dep, args) {
var args = args != undefined ? args : {};
var dir = args.dir != undefined ? args.dir : 1;
var sca = args.sca != undefined ? args.sca : 1;
var wid = args.wid != undefined ? args.wid : 1;
var ang = args.ang != undefined ? args.ang : 0;
var lea = args.lea != undefined ? args.lea : [true, 12];
var hs = Math.random() * 0.5 + 0.5;
return -1 / Math.pow(i / tl + 1, 5) + 1;
var tfun = randChoice([fun2]);
var a0 = ((Math.random() * Math.PI) / 6) * dir + ang;
for (var i = 0; i < tl; i++) {
var mx = dir * tfun(i / tl) * 50 * sca * hs;
var a = Math.atan2(my, mx);
var d = Math.pow(mx * mx + my * my, 0.5);
var nx = Math.cos(a + a0) * d;
var ny = Math.sin(a + a0) * d;
twlist.push([nx + tx, ny + ty]);
if ((i == ((tl / 3) | 0) || i == (((tl * 2) / 3) | 0)) && dep > 0) {
canv += twig(nx + tx, ny + ty, dep - 1, {
dir: dir * randChoice([-1, 1]),
if (i == tl - 1 && lea[0] == true) {
for (var j = 0; j < 5; j++) {
nx + tx + Math.cos(ang) * dj * wid,
ny + ty + (Math.sin(ang) * dj - lea[1] / (dep + 1)) * wid,
wid: (6 + 3 * Math.random()) * wid,
len: (15 + 12 * Math.random()) * wid,
ang / 2 + Math.PI / 2 + Math.PI * 0.2 * (Math.random() - 0.5),
col: "rgba(100,100,100," + (0.5 + dep * 0.2).toFixed(3) + ")",
? Math.pow(Math.sin(x * Math.PI) * x, 0.5)
: -Math.pow(Math.sin((x - 2) * Math.PI * (x - 2)), 0.5);
canv += mystroke(twlist, {
return Math.cos((x * Math.PI) / 2);
col: "rgba(100,100,100,0.5)",
var barkify = function(x, y, trlist) {
function bark(x, y, wid, ang) {
var len = 10 + 10 * Math.random();
? Math.pow(Math.sin(x * Math.PI), 0.5)
: -Math.pow(Math.sin((x + 1) * Math.PI), 0.5);
for (var i = 0; i < reso + 1; i++) {
var xo = len / 2 - Math.abs(p - 1) * len;
var yo = (fun(p) * wid) / 2;
var a = Math.atan2(yo, xo);
var l = Math.sqrt(xo * xo + yo * yo);
var n0 = Math.random() * 10;
for (var i = 0; i < reso + 1; i++) {
nslist.push(noise(i * 0.05, n0));
for (var i = 0; i < lalist.length; i++) {
var ns = nslist[i] * noi + (1 - noi);
var nx = x + Math.cos(lalist[i][1] + ang) * lalist[i][0] * ns;
var ny = y + Math.sin(lalist[i][1] + ang) * lalist[i][0] * ns;
canv += mystroke(brklist, {
col: "rgba(100,100,100,0.4)",
return Math.sin((x + fr) * Math.PI * 3);
for (var i = 2; i < trlist[0].length - 1; i++) {
trlist[0][i][1] - trlist[0][i - 1][1],
trlist[0][i][0] - trlist[0][i - 1][0],
trlist[1][i][1] - trlist[1][i - 1][1],
trlist[1][i][0] - trlist[1][i - 1][0],
var nx = trlist[0][i][0] * (1 - p) + trlist[1][i][0] * p;
var ny = trlist[0][i][1] * (1 - p) + trlist[1][i][1] * p;
if (Math.random() < 0.2) {
canv += blob(nx + x, ny + y, {
wid: 6 - Math.abs(p - 0.5) * 10,
col: "rgba(100,100,100,0.6)",
5 - Math.abs(p - 0.5) * 10,
if (Math.random() < 0.05) {
var jl = Math.random() * 2 + 2;
[trlist[0][i][0], trlist[0][i][1], a0],
[trlist[1][i][0], trlist[1][i][1], a1],
for (var j = 0; j < jl; j++) {
xya[0] + x + Math.cos(xya[2]) * (j - jl / 2) * 4,
xya[1] + y + Math.sin(xya[2]) * (j - jl / 2) * 4,
len: 4 + 6 * Math.random(),
col: "rgba(100,100,100,0.6)",
var trflist = trlist[0].concat(trlist[1].slice().reverse());
for (var i = 0; i < trflist.length; i++) {
if (Math.random() < 0.5) {
rglist[rglist.length - 1].push(trflist[i]);
for (var i = 0; i < rglist.length; i++) {
rglist[i] = div(rglist[i], 4);
for (var j = 0; j < rglist[i].length; j++) {
(noise(i, j * 0.1, 1) - 0.5) * (15 + 5 * randGaussian());
(noise(i, j * 0.1, 2) - 0.5) * (15 + 5 * randGaussian());
rglist[i].map(function(v) {
return [v[0] + x, v[1] + y];
{ wid: 1.5, col: "rgba(100,100,100,0.7)", out: 0 },
this.tree04 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 300;
var wid = args.wid != undefined ? args.wid : 6;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
var trlist = branch({ hei: hei, wid: wid, ang: -Math.PI / 2 });
txcanv += barkify(x, y, trlist);
trlist = trlist[0].concat(trlist[1].reverse());
for (var i = 0; i < trlist.length; i++) {
(i >= trlist.length * 0.3 &&
i <= trlist.length * 0.7 &&
i == trlist.length / 2 - 1
var ba = Math.PI * 0.2 - Math.PI * 1.4 * (i > trlist.length / 2);
hei: hei * (Math.random() + 1) * 0.3,
return [v[0] + trlist[i][0], v[1] + trlist[i][1]];
txcanv += barkify(x, y, [brlist[0].map(foff), brlist[1].map(foff)]);
for (var j = 0; j < brlist[0].length; j++) {
if (Math.random() < 0.2 || j == brlist[0].length - 1) {
brlist[0][j][0] + trlist[i][0] + x,
brlist[0][j][1] + trlist[i][1] + y,
ang: ba > -Math.PI / 2 ? ba : ba + Math.PI,
dir: ba > -Math.PI / 2 ? 1 : -1,
brlist = brlist[0].concat(brlist[1].reverse());
trmlist = trmlist.concat(
return [v[0] + trlist[i][0], v[1] + trlist[i][1]];
canv += poly(trmlist, { xof: x, yof: y, fil: "white", str: col, wid: 0 });
trmlist.splice(trmlist.length - 1, 1);
trmlist.map(function(v) {
return [v[0] + x, v[1] + y];
"rgba(100,100,100," + (0.4 + Math.random() * 0.1).toFixed(3) + ")",
this.tree05 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 300;
var wid = args.wid != undefined ? args.wid : 5;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
var trlist = branch({ hei: hei, wid: wid, ang: -Math.PI / 2, ben: 0 });
txcanv += barkify(x, y, trlist);
trlist = trlist[0].concat(trlist[1].reverse());
for (var i = 0; i < trlist.length; i++) {
var p = Math.abs(i - trlist.length * 0.5) / (trlist.length * 0.5);
(i >= trlist.length * 0.2 &&
i <= trlist.length * 0.8 &&
i == trlist.length / 2 - 1
var bar = Math.random() * 0.2;
-bar * Math.PI - (1 - bar * 2) * Math.PI * (i > trlist.length / 2);
hei: hei * (0.3 * p - Math.random() * 0.05),
return [v[0] + trlist[i][0], v[1] + trlist[i][1]];
for (var j = 0; j < brlist[0].length; j++) {
if (j % 20 == 0 || j == brlist[0].length - 1) {
brlist[0][j][0] + trlist[i][0] + x,
brlist[0][j][1] + trlist[i][1] + y,
ang: ba > -Math.PI / 2 ? ba : ba + Math.PI,
dir: ba > -Math.PI / 2 ? 1 : -1,
brlist = brlist[0].concat(brlist[1].reverse());
trmlist = trmlist.concat(
return [v[0] + trlist[i][0], v[1] + trlist[i][1]];
canv += poly(trmlist, { xof: x, yof: y, fil: "white", str: col, wid: 0 });
trmlist.splice(trmlist.length - 1, 1);
trmlist.map(function(v) {
return [v[0] + x, v[1] + y];
"rgba(100,100,100," + (0.4 + Math.random() * 0.1).toFixed(3) + ")",
this.tree06 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 100;
var wid = args.wid != undefined ? args.wid : 6;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
function fracTree(xoff, yoff, dep, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 300;
var wid = args.wid != undefined ? args.wid : 5;
var ang = args.ang != undefined ? args.ang : 0;
var ben = args.ben != undefined ? args.ben : Math.PI * 0.2;
txcanv += barkify(xoff, yoff, trlist);
trlist = trlist[0].concat(trlist[1].reverse());
for (var i = 0; i < trlist.length; i++) {
var p = Math.abs(i - trlist.length * 0.5) / (trlist.length * 0.5);
((Math.random() < 0.025 &&
i >= trlist.length * 0.2 &&
i <= trlist.length * 0.8) ||
i == ((trlist.length / 2) | 0) - 1 ||
i == ((trlist.length / 2) | 0) + 1) &&
var bar = 0.02 + Math.random() * 0.08;
bar * Math.PI - bar * 2 * Math.PI * (i > trlist.length / 2);
hei: hei * (0.7 + Math.random() * 0.2),
for (var j = 0; j < brlist.length; j++) {
if (Math.random() < 0.03) {
brlist[j][0] + trlist[i][0] + xoff,
brlist[j][1] + trlist[i][1] + yoff,
ang: ba * (Math.random() * 0.5 + 0.75),
trmlist = trmlist.concat(
return [v[0] + trlist[i][0], v[1] + trlist[i][1]];
var trmlist = fracTree(x, y, 3, {
canv += poly(trmlist, { xof: x, yof: y, fil: "white", str: col, wid: 0 });
trmlist.splice(trmlist.length - 1, 1);
trmlist.map(function(v) {
return [v[0] + x, v[1] + y];
"rgba(100,100,100," + (0.4 + Math.random() * 0.1).toFixed(3) + ")",
this.tree07 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 60;
var wid = args.wid != undefined ? args.wid : 4;
return Math.sqrt(x) * 0.2;
var col = args.col != undefined ? args.col : "rgba(100,100,100,1)";
var noi = args.noi != undefined ? args.noi : 0.5;
for (var i = 0; i < reso; i++) {
nslist.push([noise(i * 0.5), noise(i * 0.5, 0.5)]);
if (col.includes("rgba(")) {
leafcol = ["100", "100", "100", "1"];
for (var i = 0; i < reso; i++) {
var nx = x + ben(i / reso) * 100;
var ny = y - (i * hei) / reso;
for (var j = 0; j < 1; j++) {
nx + (Math.random() - 0.5) * wid * 1.2 * (reso - i) * 0.5,
ny + (Math.random() - 0.5) * wid * 0.5,
len: Math.random() * 50 + 20,
wid: Math.random() * 12 + 12,
ang: (-Math.random() * Math.PI) / 6,
parseFloat(leafcol[3]).toFixed(3) +
? 2.75 * x * Math.pow(1 - x, 1 / 1.8)
: 2.75 * (x - 2) * Math.pow(x - 1, 1 / 1.8);
PolyTools.triangulate(bpl, {
line1.push([nx + (nslist[i][0] - 0.5) * wid - wid / 2, ny]);
line2.push([nx + (nslist[i][1] - 0.5) * wid + wid / 2, ny]);
T = PolyTools.triangulate(line1.concat(line2.reverse()), {
for (var k = 0; k < T.length; k++) {
var m = PolyTools.midPt(T[k]);
var c = (noise(m[0] * 0.02, m[1] * 0.02) * 200 + 50) | 0;
var co = "rgba(" + c + "," + c + "," + c + ",0.8)";
canv += poly(T[k], { fil: co, str: co, wid: 0 });
this.tree08 = function(x, y, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 80;
var wid = args.wid != undefined ? args.wid : 1;
var col = args.col != undefined ? args.col : "rgba(100,100,100,0.5)";
var noi = args.noi != undefined ? args.noi : 0.5;
var ang = normRand(-1, 1) * Math.PI * 0.2;
trlist = trlist[0].concat(trlist[1].reverse());
function fracTree(xoff, yoff, dep, args) {
var args = args != undefined ? args : {};
var ang = args.ang != undefined ? args.ang : -Math.PI / 2;
var len = args.len != undefined ? args.len : 15;
var ben = args.ben != undefined ? args.ben : 0;
return Math.cos(0.5 * Math.PI * x);
var ept = [xoff + Math.cos(ang) * len, yoff + Math.sin(ang) * len];
var trmlist = [[xoff, yoff], [xoff + len, yoff]];
return Math.sin(x * Math.PI);
return -Math.sin(x * Math.PI);
trmlist = div(trmlist, 10);
for (var i = 0; i < trmlist.length; i++) {
trmlist[i][1] += bfun(i / trmlist.length) * 2;
for (var i = 0; i < trmlist.length; i++) {
var d = distance(trmlist[i], spt);
var a = Math.atan2(trmlist[i][1] - spt[1], trmlist[i][0] - spt[0]);
trmlist[i][0] = spt[0] + d * Math.cos(a + ang);
trmlist[i][1] = spt[1] + d * Math.sin(a + ang);
tcanv += mystroke(trmlist, {
col: "rgba(100,100,100,0.5)",
var nben = ben + randChoice([-1, 1]) * Math.PI * 0.001 * dep * dep;
if (Math.random() < 0.5) {
tcanv += fracTree(ept[0], ept[1], dep - 1, {
randChoice([normRand(-1, 0.5), normRand(0.5, 1)]) *
len: len * normRand(0.8, 0.9),
tcanv += fracTree(ept[0], ept[1], dep - 1, {
randChoice([normRand(-1, -0.5), normRand(0.5, 1)]) *
len: len * normRand(0.8, 0.9),
tcanv += fracTree(ept[0], ept[1], dep - 1, {
len: len * normRand(0.8, 0.9),
for (var i = 0; i < trlist.length; i++) {
if (Math.random() < 0.2) {
Math.floor(4 * Math.random()),
{ hei: 20, ang: -Math.PI / 2 - ang * Math.random() },
} else if (i == Math.floor(trlist.length / 2)) {
twcanv += fracTree(x + trlist[i][0], y + trlist[i][1], 3, {
canv += poly(trlist, { xof: x, yof: y, fil: "white", str: col, wid: 0 });
return [v[0] + x, v[1] + y];
"rgba(100,100,100," + (0.6 + Math.random() * 0.1).toFixed(3) + ")",
var Mount = new function() {
var foot = function(ptlist, args) {
var args = args != undefined ? args : {};
var xof = args.xof != undefined ? args.xof : 0;
var yof = args.yof != undefined ? args.yof : 0;
var ret = args.ret != undefined ? args.ret : 0;
for (var i = 0; i < ptlist.length - 2; i += 1) {
ni = Math.min(ni + randChoice([1, 2]), ptlist.length - 1);
for (var j = 0; j < Math.min(ptlist[i].length / 8, 10); j++) {
ftlist[ftlist.length - 2].push([
ptlist[i][j][0] + noise(j * 0.1, i) * 10,
ftlist[ftlist.length - 1].push([
ptlist[i][ptlist[i].length - 1 - j][0] -
ptlist[i][ptlist[i].length - 1 - j][1],
ftlist[ftlist.length - 2] = ftlist[ftlist.length - 2].reverse();
ftlist[ftlist.length - 1] = ftlist[ftlist.length - 1].reverse();
for (var j = 0; j < span; j++) {
var x1 = ptlist[i][0][0] * (1 - p) + ptlist[ni][0][0] * p;
var y1 = ptlist[i][0][1] * (1 - p) + ptlist[ni][0][1] * p;
ptlist[i][ptlist[i].length - 1][0] * (1 - p) +
ptlist[ni][ptlist[i].length - 1][0] * p;
ptlist[i][ptlist[i].length - 1][1] * (1 - p) +
ptlist[ni][ptlist[i].length - 1][1] * p;
var vib = -1.7 * (p - 1) * Math.pow(p, 1 / 5);
y1 += vib * 5 + noise(xof * 0.05, i) * 5;
y2 += vib * 5 + noise(xof * 0.05, i) * 5;
ftlist[ftlist.length - 2].push([x1, y1]);
ftlist[ftlist.length - 1].push([x2, y2]);
for (var i = 0; i < ftlist.length; i++) {
canv += poly(ftlist[i], {
for (var j = 0; j < ftlist.length; j++) {
ftlist[j].map(function(x) {
return [x[0] + xof, x[1] + yof];
(0.1 + Math.random() * 0.1).toFixed(3) +
return ret ? ftlist : canv;
this.mountain = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 100 + Math.random() * 400;
var wid = args.wid != undefined ? args.wid : 400 + Math.random() * 200;
var tex = args.tex != undefined ? args.tex : 200;
var veg = args.veg != undefined ? args.veg : true;
var ret = args.ret != undefined ? args.ret : 0;
var col = args.col != undefined ? args.col : undefined;
seed = seed != undefined ? seed : 0;
for (var j = 0; j < reso[0]; j++) {
hoff += (Math.random() * yoff) / 100;
for (var i = 0; i < reso[1]; i++) {
var x = (i / reso[1] - 0.5) * Math.PI;
y *= noise(x + 10, j * 0.15, seed);
ptlist[ptlist.length - 1].push([
function vegetate(treeFunc, growthRule, proofRule) {
for (var i = 0; i < ptlist.length; i += 1) {
for (var j = 0; j < ptlist[i].length; j += 1) {
veglist.push([ptlist[i][j][0], ptlist[i][j][1]]);
for (var i = 0; i < veglist.length; i++) {
if (proofRule(veglist, i)) {
canv += treeFunc(veglist[i][0], veglist[i][1]);
return Tree.tree02(x + xoff, y + yoff - 5, {
(noise(0.01 * x, 0.01 * y) * 0.5 * 0.3 + 0.5).toFixed(3) +
var ns = noise(j * 0.1, seed);
i == 0 && ns * ns * ns < 0.1 && Math.abs(ptlist[i][j][1]) / h > 0.2
canv += poly(ptlist[0].concat([[0, reso[0] * 4]]), {
ptlist[0].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
{ col: "rgba(100,100,100,0.3)", noi: 1, wid: 3 },
canv += foot(ptlist, { xof: xoff, yof: yoff });
canv += mytexture(ptlist, {
sha: randChoice([0, 0, 0, 0, 5]),
return Tree.tree02(x + xoff, y + yoff, {
(noise(0.01 * x, 0.01 * y) * 0.5 * 0.3 + 0.5).toFixed(3) +
var ns = noise(i * 0.1, j * 0.1, seed + 2);
return ns * ns * ns < 0.1 && Math.abs(ptlist[i][j][1]) / h > 0.5;
var ht = ((h + y) / h) * 70;
ht = ht * 0.3 + Math.random() * ht * 0.7;
return Tree.tree01(x + xoff, y + yoff, {
wid: Math.random() * 3 + 1,
(noise(0.01 * x, 0.01 * y) * 0.5 * 0.3 + 0.3).toFixed(3) +
var ns = noise(i * 0.2, j * 0.05, seed);
ns * ns * ns * ns < 0.012 &&
Math.abs(ptlist[i][j][1]) / h < 0.3
for (var j = 0; j < veglist.length; j++) {
Math.pow(veglist[i][0] - veglist[j][0], 2) +
Math.pow(veglist[i][1] - veglist[j][1], 2) <
var ht = ((h + y) / h) * 120;
ht = ht * 0.5 + Math.random() * ht * 0.5;
var bc = Math.random() * 0.1;
return Tree.tree03(x + xoff, y + yoff, {
return Math.pow(x * bc, bp);
(noise(0.01 * x, 0.01 * y) * 0.5 * 0.3 + 0.3).toFixed(3) +
var ns = noise(i * 0.2, j * 0.05, seed);
(j == 0 || j == ptlist[i].length - 1) && ns * ns * ns * ns < 0.012
var tt = randChoice([0, 0, 1, 1, 1, 2]);
return Arch.arch02(x + xoff, y + yoff, seed, {
sto: randChoice([1, 2, 2, 3]),
sty: randChoice([1, 2, 3]),
return Arch.arch04(x + xoff, y + yoff, seed, {
sto: randChoice([1, 1, 1, 2, 2]),
var ns = noise(i * 0.2, j * 0.05, seed + 10);
(j == 1 || j == ptlist[i].length - 2) &&
ns * ns * ns * ns < 0.008
return Arch.arch03(x + xoff, y + yoff, seed, {
wid: 40 + Math.random() * 20,
Math.abs(j - ptlist[i].length / 2) < 1 &&
return Arch.transmissionTower01(x + xoff, y + yoff, seed);
var ns = noise(i * 0.2, j * 0.05, seed + 20 * Math.PI);
(j == 1 || j == ptlist[i].length - 2) &&
ns * ns * ns * ns < 0.002
return Mount.rock(x + xoff, y + yoff, seed, {
wid: 20 + Math.random() * 20,
hei: 20 + Math.random() * 20,
return (j == 0 || j == ptlist[i].length - 1) && Math.random() < 0.1;
this.flatMount = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 40 + Math.random() * 400;
var wid = args.wid != undefined ? args.wid : 400 + Math.random() * 200;
var tex = args.tex != undefined ? args.tex : 80;
var cho = args.cho != undefined ? args.cho : 0.5;
var ret = args.ret != undefined ? args.ret : 0;
seed = seed != undefined ? seed : 0;
for (var j = 0; j < reso[0]; j++) {
hoff += (Math.random() * yoff) / 100;
for (var i = 0; i < reso[1]; i++) {
var x = (i / reso[1] - 0.5) * Math.PI;
var y = Math.cos(x * 2) + 1;
y *= noise(x + 10, j * 0.1, seed);
var p = 1 - (j / reso[0]) * 0.6;
var nx = (x / Math.PI) * wid * p;
var ny = -y * hei * p + hoff;
if (ny < -h * cho + hoff) {
if (flat[flat.length - 1].length % 2 == 0) {
flat[flat.length - 1].push([nx, ny]);
if (flat[flat.length - 1].length % 2 == 1) {
flat[flat.length - 1].push(
ptlist[ptlist.length - 1][ptlist[ptlist.length - 1].length - 1],
ptlist[ptlist.length - 1].push([nx, ny]);
canv += poly(ptlist[0].concat([[0, reso[0] * 4]]), {
ptlist[0].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
{ col: "rgba(100,100,100,0.3)", noi: 1, wid: 3 },
canv += mytexture(ptlist, {
if (Math.random() > 0.5) {
return 0.1 + 0.4 * Math.random();
return 0.9 - 0.4 * Math.random();
for (var i = 0; i < flat.length; i += 2) {
if (flat[i].length >= 2) {
grlist1.push(flat[i][0]);
grlist2.push(flat[i][flat[i].length - 1]);
if (grlist1.length == 0) {
var wb = [grlist1[0][0], grlist2[0][0]];
for (var i = 0; i < 3; i++) {
grlist1.unshift([wb[0] * p, grlist1[0][1] - 5]);
grlist2.unshift([wb[1] * p, grlist2[0][1] - 5]);
wb = [grlist1[grlist1.length - 1][0], grlist2[grlist2.length - 1][0]];
for (var i = 0; i < 3; i++) {
var p = 0.6 - i * i * 0.1;
grlist1.push([wb[0] * p, grlist1[grlist1.length - 1][1] + 1]);
grlist2.push([wb[1] * p, grlist2[grlist2.length - 1][1] + 1]);
grlist1 = div(grlist1, d);
grlist2 = div(grlist2, d);
var grlist = grlist1.reverse().concat(grlist2.concat([grlist1[0]]));
for (var i = 0; i < grlist.length; i++) {
var v = (1 - Math.abs((i % d) - d / 2) / (d / 2)) * 0.12;
grlist[i][0] *= 1 - v + noise(grlist[i][1] * 0.5) * v;
canv += mystroke(grlist.map(x => [x[0] + xoff, x[1] + yoff]), {
col: "rgba(100,100,100,0.2)",
var bound = function(plist) {
for (var i = 0; i < plist.length; i++) {
if (xmin == undefined || plist[i][0] < xmin) {
if (xmax == undefined || plist[i][0] > xmax) {
if (ymin == undefined || plist[i][1] < ymin) {
if (ymax == undefined || plist[i][1] > ymax) {
return { xmin: xmin, xmax: xmax, ymin: ymin, ymax: ymax };
canv += this.flatDec(xoff, yoff, bound(grlist));
this.flatDec = function(xoff, yoff, grbd) {
var tt = randChoice([0, 0, 1, 2, 3, 4]);
for (var j = 0; j < Math.random() * 5; j++) {
xoff + normRand(grbd.xmin, grbd.xmax),
yoff + (grbd.ymin + grbd.ymax) / 2 + normRand(-10, 10) + 10,
wid: 10 + Math.random() * 20,
hei: 10 + Math.random() * 20,
for (var j = 0; j < randChoice([0, 0, 1, 2]); j++) {
var xr = xoff + normRand(grbd.xmin, grbd.xmax);
var yr = yoff + (grbd.ymin + grbd.ymax) / 2 + normRand(-5, 5) + 20;
for (var k = 0; k < 2 + Math.random() * 3; k++) {
xr + Math.min(Math.max(normRand(-30, 30), grbd.xmin), grbd.xmax),
{ hei: 60 + Math.random() * 40 },
for (var j = 0; j < Math.random() * 3; j++) {
xoff + normRand(grbd.xmin, grbd.xmax),
yoff + (grbd.ymin + grbd.ymax) / 2 + normRand(-5, 5) + 20,
wid: 50 + Math.random() * 20,
hei: 40 + Math.random() * 20,
var pmin = Math.random() * 0.5;
var pmax = Math.random() * 0.5 + 0.5;
var xmin = grbd.xmin * (1 - pmin) + grbd.xmax * pmin;
var xmax = grbd.xmin * (1 - pmax) + grbd.xmax * pmax;
for (var i = xmin; i < xmax; i += 30) {
xoff + i + 20 * normRand(-1, 1),
yoff + (grbd.ymin + grbd.ymax) / 2 + 20,
{ hei: 100 + Math.random() * 200 },
for (var j = 0; j < Math.random() * 4; j++) {
xoff + normRand(grbd.xmin, grbd.xmax),
yoff + (grbd.ymin + grbd.ymax) / 2 + normRand(-5, 5) + 20,
wid: 50 + Math.random() * 20,
hei: 40 + Math.random() * 20,
for (var i = 0; i < randChoice([1, 1, 1, 1, 2, 2, 3]); i++) {
var xr = normRand(grbd.xmin, grbd.xmax);
var yr = (grbd.ymin + grbd.ymax) / 2;
canv += Tree.tree04(xoff + xr, yoff + yr + 20, {});
for (var j = 0; j < Math.random() * 2; j++) {
Math.min(grbd.xmax, xr + normRand(-50, 50)),
yoff + yr + normRand(-5, 5) + 20,
j * i * Math.random() * 100,
wid: 50 + Math.random() * 20,
hei: 40 + Math.random() * 20,
for (var i = 0; i < randChoice([1, 1, 1, 1, 2, 2, 3]); i++) {
xoff + normRand(grbd.xmin, grbd.xmax),
yoff + (grbd.ymin + grbd.ymax) / 2,
{ hei: 60 + Math.random() * 60 },
var pmin = Math.random() * 0.5;
var pmax = Math.random() * 0.5 + 0.5;
var xmin = grbd.xmin * (1 - pmin) + grbd.xmax * pmin;
var xmax = grbd.xmin * (1 - pmax) + grbd.xmax * pmax;
for (var i = xmin; i < xmax; i += 20) {
xoff + i + 20 * normRand(-1, 1),
yoff + (grbd.ymin + grbd.ymax) / 2 + normRand(-1, 1) + 0,
{ hei: normRand(40, 80) },
for (var i = 0; i < 50 * Math.random(); i++) {
xoff + normRand(grbd.xmin, grbd.xmax),
yoff + normRand(grbd.ymin, grbd.ymax),
var ts = randChoice([0, 0, 0, 0, 1]);
if (ts == 1 && tt != 4) {
xoff + normRand(grbd.xmin, grbd.xmax),
yoff + (grbd.ymin + grbd.ymax) / 2 + 20,
this.distMount = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 300;
var len = args.len != undefined ? args.len : 2000;
var seg = args.seg != undefined ? args.seg : 5;
seed = seed != undefined ? seed : 0;
for (var i = 0; i < len / span / seg; i++) {
for (var j = 0; j < seg + 1; j++) {
Math.pow(Math.sin((Math.PI * k) / (len / span)), 0.5),
ptlist[ptlist.length - 1].push(tran(i * seg + j));
for (var j = 0; j < seg / 2 + 1; j++) {
noise(k * 0.05, 2, seed) *
Math.pow(Math.sin((Math.PI * k) / (len / span)), 1),
ptlist[ptlist.length - 1].unshift(tran(i * seg + j * 2));
for (var i = 0; i < ptlist.length; i++) {
var getCol = function(x, y) {
var c = (noise(x * 0.02, y * 0.02, yoff) * 55 + 200) | 0;
return "rgb(" + c + "," + c + "," + c + ")";
canv += poly(ptlist[i], {
fil: getCol(...ptlist[i][ptlist[i].length - 1]),
var T = PolyTools.triangulate(ptlist[i], {
for (var k = 0; k < T.length; k++) {
var m = PolyTools.midPt(T[k]);
var co = getCol(m[0], m[1]);
canv += poly(T[k], { fil: co, str: co, wid: 1 });
this.rock = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 80;
var wid = args.wid != undefined ? args.wid : 100;
var tex = args.tex != undefined ? args.tex : 40;
var ret = args.ret != undefined ? args.ret : 0;
var sha = args.sha != undefined ? args.sha : 10;
seed = seed != undefined ? seed : 0;
for (var i = 0; i < reso[0]; i++) {
for (var j = 0; j < reso[1]; j++) {
nslist.push(noise(i, j * 0.2, seed));
for (var j = 0; j < reso[1]; j++) {
var a = (j / reso[1]) * Math.PI * 2 - Math.PI / 2;
Math.pow(hei * Math.cos(a), 2) + Math.pow(wid * Math.sin(a), 2),
l *= 0.7 + 0.3 * nslist[j];
var nx = Math.cos(a) * l * p;
var ny = -Math.sin(a) * l * p;
if (Math.PI < a || a < 0) {
ny += hei * (i / reso[0]) * 0.2;
ptlist[ptlist.length - 1].push([nx, ny]);
canv += poly(ptlist[0].concat([[0, 0]]), {
ptlist[0].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
{ col: "rgba(100,100,100,0.3)", noi: 1, wid: 3 },
canv += mytexture(ptlist, {
"rgba(180,180,180," + (0.3 + Math.random() * 0.3).toFixed(3) + ")"
if (Math.random() > 0.5) {
return 0.15 + 0.15 * Math.random();
return 0.85 - 0.15 * Math.random();
for (var i = 0; i < reso[0]; i++) {
var Arch = new function() {
var flip = function(ptlist, axis) {
axis = axis == undefined ? 0 : axis;
for (var i = 0; i < ptlist.length; i++) {
if (ptlist[i].length > 0) {
if (typeof ptlist[i][0] == "object") {
for (var j = 0; j < ptlist[i].length; j++) {
ptlist[i][j][0] = axis - (ptlist[i][j][0] - axis);
ptlist[i][0] = axis - (ptlist[i][0] - axis);
var hut = function(xoff, yoff, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 40;
var wid = args.wid != undefined ? args.wid : 180;
var tex = args.tex != undefined ? args.tex : 300;
for (var i = 0; i < reso[0]; i++) {
var heir = hei + hei * 0.2 * Math.random();
for (var j = 0; j < reso[1]; j++) {
wid * (i / (reso[0] - 1) - 0.5) * Math.pow(j / (reso[1] - 1), 0.7);
var ny = heir * (j / (reso[1] - 1));
ptlist[ptlist.length - 1].push([nx, ny]);
.concat(ptlist[ptlist.length - 1].slice(0, -1).reverse()),
{ xof: xoff, yof: yoff, fil: "white", str: "none" },
canv += poly(ptlist[0], {
str: "rgba(100,100,100,0.3)",
canv += poly(ptlist[ptlist.length - 1], {
str: "rgba(100,100,100,0.3)",
canv += mytexture(ptlist, {
"rgba(120,120,120," + (0.3 + Math.random() * 0.3).toFixed(3) + ")"
return wtrand(a => a * a);
for (var i = 0; i < reso[0]; i++) {
var box = function(xoff, yoff, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 20;
var wid = args.wid != undefined ? args.wid : 120;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 4;
var tra = args.tra != undefined ? args.tra : true;
var bot = args.bot != undefined ? args.bot : true;
var wei = args.wei != undefined ? args.wei : 3;
var mid = -wid * 0.5 + wid * rot;
var bmid = -wid * 0.5 + wid * (1 - rot);
ptlist.push(div([[-wid * 0.5, -hei], [-wid * 0.5, 0]], 5));
ptlist.push(div([[wid * 0.5, -hei], [wid * 0.5, 0]], 5));
ptlist.push(div([[-wid * 0.5, 0], [mid, per]], 5));
ptlist.push(div([[wid * 0.5, 0], [mid, per]], 5));
ptlist.push(div([[mid, -hei], [mid, per]], 5));
ptlist.push(div([[-wid * 0.5, 0], [bmid, -per]], 5));
ptlist.push(div([[wid * 0.5, 0], [bmid, -per]], 5));
ptlist.push(div([[bmid, -hei], [bmid, -per]], 5));
var surf = (rot < 0.5) * 2 - 1;
pul: [surf * wid * 0.5, -hei],
pdl: [surf * wid * 0.5, 0],
for (var i = 0; i < ptlist.length; i++) {
ptlist[i].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
col: "rgba(100,100,100,0.4)",
var deco = function(style, args) {
var args = args != undefined ? args : {};
var pul = args.pul != undefined ? args.pul : [0, 0];
var pur = args.pur != undefined ? args.pur : [0, 100];
var pdl = args.pdl != undefined ? args.pdl : [100, 0];
var pdr = args.pdr != undefined ? args.pdr : [100, 100];
var hsp = args.hsp != undefined ? args.hsp : [1, 3];
var vsp = args.vsp != undefined ? args.vsp : [1, 2];
var dl = div([pul, pdl], vsp[1]);
var dr = div([pur, pdr], vsp[1]);
var du = div([pul, pur], hsp[1]);
var dd = div([pdl, pdr], hsp[1]);
var mru = du[du.length - 1 - hsp[0]];
var mrd = dd[du.length - 1 - hsp[0]];
for (var i = vsp[0]; i < dl.length - vsp[0]; i += vsp[0]) {
var mml = div([mlu, mld], vsp[1])[i];
var mmr = div([mru, mrd], vsp[1])[i];
plist.push(div([mml, ml], 5));
plist.push(div([mmr, mr], 5));
plist.push(div([mlu, mld], 5));
plist.push(div([mru, mrd], 5));
for (var i = hsp[0]; i < du.length - hsp[0]; i += hsp[0]) {
plist.push(div([mu, md], 5));
var mru = du[du.length - 1 - hsp[0]];
var mrd = dd[du.length - 1 - hsp[0]];
for (var i = vsp[0]; i < dl.length - vsp[0]; i += vsp[0]) {
var mml = div([mlu, mld], vsp[1])[i];
var mmr = div([mru, mrd], vsp[1])[i];
var mmu = div([mlu, mru], vsp[1])[i];
var mmd = div([mld, mrd], vsp[1])[i];
plist.push(div([mml, mmr], 5));
plist.push(div([mmu, mmd], 5));
plist.push(div([mlu, mld], 5));
plist.push(div([mru, mrd], 5));
var rail = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 20;
var wid = args.wid != undefined ? args.wid : 180;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 4;
var seg = args.seg != undefined ? args.seg : 4;
var wei = args.wei != undefined ? args.wei : 1;
var tra = args.tra != undefined ? args.tra : true;
var fro = args.fro != undefined ? args.fro : true;
seed = seed != undefined ? seed : 0;
var mid = -wid * 0.5 + wid * rot;
var bmid = -wid * 0.5 + wid * (1 - rot);
ptlist.push(div([[-wid * 0.5, 0], [mid, per]], seg));
ptlist.push(div([[mid, per], [wid * 0.5, 0]], seg));
ptlist.push(div([[-wid * 0.5, 0], [bmid, -per]], seg));
ptlist.push(div([[bmid, -per], [wid * 0.5, 0]], seg));
ptlist.push(div([[-wid * 0.5, -hei], [mid, -hei + per]], seg));
ptlist.push(div([[mid, -hei + per], [wid * 0.5, -hei]], seg));
ptlist.push(div([[-wid * 0.5, -hei], [bmid, -hei - per]], seg));
ptlist.push(div([[bmid, -hei - per], [wid * 0.5, -hei]], seg));
var open = Math.floor(Math.random() * ptlist.length);
ptlist[open] = ptlist[open].slice(0, -1);
ptlist[(open + ptlist.length) % ptlist.length] = ptlist[
(open + ptlist.length) % ptlist.length
for (var i = 0; i < ptlist.length / 2; i++) {
for (var j = 0; j < ptlist[i].length; j++) {
ptlist[i][j][1] += (noise(i, j * 0.5, seed) - 0.5) * hei;
ptlist[(ptlist.length / 2 + i) % ptlist.length][
j % ptlist[(ptlist.length / 2 + i) % ptlist.length].length
][1] += (noise(i + 0.5, j * 0.5, seed) - 0.5) * hei;
ptlist[(ptlist.length / 2 + i) % ptlist.length][
j % ptlist[(ptlist.length / 2 + i) % ptlist.length].length
ln[0][0] += (Math.random() - 0.5) * hei * 0.5;
str: "rgba(100,100,100,0.5)",
for (var i = 0; i < ptlist.length; i++) {
ptlist[i].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
col: "rgba(100,100,100,0.5)",
var roof = function(xoff, yoff, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 20;
var wid = args.wid != undefined ? args.wid : 120;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 4;
var cor = args.cor != undefined ? args.cor : 5;
var wei = args.wei != undefined ? args.wei : 3;
var pla = args.pla != undefined ? args.pla : [0, ""];
var opf = function(ptlist) {
var rrot = rot < 0.5 ? 1 - rot : rot;
var mid = -wid * 0.5 + wid * rrot;
var bmid = -wid * 0.5 + wid * (1 - rrot);
var quat = (mid + wid * 0.5) * 0.5 - mid;
[-wid * 0.5 + quat, -hei - per / 2],
[-wid * 0.5 + quat * 0.5, -hei / 2 - per / 4],
[(mid + quat + wid * 0.5) / 2, -hei / 2],
[mid + quat / 2, -hei / 2 + per / 2],
ptlist.push(div(opf([[-wid * 0.5 - cor, 0], [mid + cor, per]]), 5));
ptlist.push(div(opf([[wid * 0.5 + cor, 0], [mid + cor, per]]), 5));
div(opf([[-wid * 0.5 + quat, -hei - per / 2], [mid + quat, -hei]]), 5),
[-wid * 0.5 + quat, -hei - per / 2],
canv += poly(polist, { xof: xoff, yof: yoff, str: "none", fil: "white" });
for (var i = 0; i < ptlist.length; i++) {
ptlist[i].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
col: "rgba(100,100,100,0.4)",
[mid + quat / 2, -hei / 2 + per / 2],
[-wid * 0.5 + quat * 0.5, -hei / 2 - per / 4],
if (pp[0][0] > pp[1][0]) {
var mp = PolyTools.midPt(pp);
var a = Math.atan2(pp[1][1] - pp[0][1], pp[1][0] - pp[0][0]);
var adeg = (a * 180) / Math.PI;
"' font-family='Verdana'" +
" style='fill:rgba(100,100,100,0.9)'" +
" text-anchor='middle' transform='translate(" +
var pagroof = function(xoff, yoff, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 20;
var wid = args.wid != undefined ? args.wid : 120;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 4;
var cor = args.cor != undefined ? args.cor : 10;
var sid = args.sid != undefined ? args.sid : 4;
var wei = args.wei != undefined ? args.wei : 3;
var polist = [[0, -hei]];
for (var i = 0; i < sid; i++) {
var fx = wid * ((i * 1.0) / (sid - 1) - 0.5);
var fy = per * (1 - Math.abs((i * 1.0) / (sid - 1) - 0.5) * 2);
var fxx = (wid + cor) * ((i * 1.0) / (sid - 1) - 0.5);
ptlist.push([ptlist[ptlist.length - 1][2], [fxx, fy]]);
ptlist.push([[0, -hei], [fx * 0.5, (-hei + fy) * 0.5], [fxx, fy]]);
canv += poly(polist, { xof: xoff, yof: yoff, str: "none", fil: "white" });
for (var i = 0; i < ptlist.length; i++) {
div(ptlist[i], 5).map(function(x) {
return [x[0] + xoff, x[1] + yoff];
col: "rgba(100,100,100,0.4)",
this.arch01 = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 70;
var wid = args.wid != undefined ? args.wid : 180;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 5;
seed = seed != undefined ? seed : 0;
var p = 0.4 + Math.random() * 0.2;
canv += hut(xoff, yoff - hei, { hei: h0, wid: wid });
canv += box(xoff, yoff, {
canv += rail(xoff, yoff, seed, {
seg: (3 + Math.random() * 3) | 0,
var mcnt = randChoice([0, 1, 1, 2]);
canv += Man.man(xoff + normRand(-wid / 3, wid / 3), yoff, {
fli: randChoice([true, false]),
canv += Man.man(xoff + normRand(-wid / 4, -wid / 5), yoff, {
canv += Man.man(xoff + normRand(wid / 5, wid / 4), yoff, {
canv += rail(xoff, yoff, seed, {
seg: (3 + Math.random() * 3) | 0,
this.arch02 = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 10;
var wid = args.wid != undefined ? args.wid : 50;
var rot = args.rot != undefined ? args.rot : 0.3;
var per = args.per != undefined ? args.per : 5;
var sto = args.sto != undefined ? args.sto : 3;
var sty = args.sty != undefined ? args.sty : 1;
var rai = args.rai != undefined ? args.rai : false;
seed = seed != undefined ? seed : 0;
for (var i = 0; i < sto; i++) {
canv += box(xoff, yoff - hoff, {
wid: wid * Math.pow(0.85, i),
hsp: [[], [1, 5], [1, 5], [1, 4]][sty],
vsp: [[], [1, 2], [1, 2], [1, 3]][sty],
? rail(xoff, yoff - hoff, i * 0.2, {
wid: wid * Math.pow(0.85, i) * 1.1,
if (sto == 1 && Math.random() < 1 / 3) {
canv += roof(xoff, yoff - hoff - hei, {
wid: wid * Math.pow(0.9, i),
this.arch03 = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 10;
var wid = args.wid != undefined ? args.wid : 50;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 5;
var sto = args.sto != undefined ? args.sto : 7;
seed = seed != undefined ? seed : 0;
for (var i = 0; i < sto; i++) {
canv += box(xoff, yoff - hoff, {
wid: wid * Math.pow(0.85, i),
return deco(1, Object.assign({}, a, { hsp: [1, 4], vsp: [1, 2] }));
canv += rail(xoff, yoff - hoff, i * 0.2, {
wid: wid * Math.pow(0.85, i) * 1.1,
canv += pagroof(xoff, yoff - hoff - hei, {
wid: wid * Math.pow(0.9, i),
this.arch04 = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 15;
var wid = args.wid != undefined ? args.wid : 30;
var rot = args.rot != undefined ? args.rot : 0.7;
var per = args.per != undefined ? args.per : 5;
var sto = args.sto != undefined ? args.sto : 2;
seed = seed != undefined ? seed : 0;
for (var i = 0; i < sto; i++) {
canv += box(xoff, yoff - hoff, {
wid: wid * Math.pow(0.85, i),
canv += rail(xoff, yoff - hoff, i * 0.2, {
wid: wid * Math.pow(0.85, i) * 1.2,
canv += pagroof(xoff, yoff - hoff - hei, {
wid: wid * Math.pow(0.9, i),
this.boat01 = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var len = args.len != undefined ? args.len : 120;
var sca = args.sca != undefined ? args.sca : 1;
var fli = args.fli != undefined ? args.fli : false;
canv += Man.man(xoff + 20 * sca * dir, yoff, {
len: [0, 30, 20, 30, 10, 30, 30, 30, 30],
return Math.pow(Math.sin(x * Math.PI), 0.5) * 7 * sca;
return Math.pow(Math.sin(x * Math.PI), 0.5) * 10 * sca;
for (var i = 0; i < len * sca; i += 5 * sca) {
plist1.push([i * dir, fun1(i / len)]);
plist2.push([i * dir, fun2(i / len)]);
var plist = plist1.concat(plist2.reverse());
canv += poly(plist, { xof: xoff, yof: yoff, fil: "white" });
canv += mystroke(plist.map(v => [xoff + v[0], yoff + v[1]]), {
return Math.sin(x * Math.PI * 2);
col: "rgba(100,100,100,0.4)",
this.transmissionTower01 = function(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 100;
var wid = args.wid != undefined ? args.wid : 20;
var toGlobal = function(v) {
return [v[0] + xoff, v[1] + yoff];
var quickstroke = function(pl) {
return mystroke(div(pl, 5).map(toGlobal), {
col: "rgba(100,100,100,0.4)",
var p00 = [-wid * 0.05, -hei];
var p01 = [wid * 0.05, -hei];
var p10 = [-wid * 0.1, -hei * 0.9];
var p11 = [wid * 0.1, -hei * 0.9];
var p20 = [-wid * 0.2, -hei * 0.5];
var p21 = [wid * 0.2, -hei * 0.5];
var p30 = [-wid * 0.5, 0];
var p31 = [wid * 0.5, 0];
var bch = [[0.7, -0.85], [1, -0.675], [0.7, -0.5]];
for (var i = 0; i < bch.length; i++) {
[-bch[i][0] * wid, bch[i][1] * hei],
[bch[i][0] * wid, bch[i][1] * hei],
[-bch[i][0] * wid, bch[i][1] * hei],
[0, (bch[i][1] - 0.05) * hei],
[bch[i][0] * wid, bch[i][1] * hei],
[0, (bch[i][1] - 0.05) * hei],
[-bch[i][0] * wid, bch[i][1] * hei],
[-bch[i][0] * wid, (bch[i][1] + 0.1) * hei],
[bch[i][0] * wid, bch[i][1] * hei],
[bch[i][0] * wid, (bch[i][1] + 0.1) * hei],
var l10 = div([p00, p10, p20, p30], 5);
var l11 = div([p01, p11, p21, p31], 5);
for (var i = 0; i < l10.length - 1; i++) {
canv += quickstroke([l10[i], l11[i + 1]]);
canv += quickstroke([l11[i], l10[i + 1]]);
canv += quickstroke([p00, p01]);
canv += quickstroke([p10, p11]);
canv += quickstroke([p20, p21]);
canv += quickstroke([p00, p10, p20, p30]);
canv += quickstroke([p01, p11, p21, p31]);
var Man = new function() {
var expand = function(ptlist, wfun) {
var n0 = Math.random() * 10;
for (var i = 1; i < ptlist.length - 1; i++) {
var w = wfun(i / ptlist.length);
ptlist[i][1] - ptlist[i - 1][1],
ptlist[i][0] - ptlist[i - 1][0],
ptlist[i][1] - ptlist[i + 1][1],
ptlist[i][0] - ptlist[i + 1][0],
ptlist[i][0] + w * Math.cos(a),
ptlist[i][1] + w * Math.sin(a),
ptlist[i][0] - w * Math.cos(a),
ptlist[i][1] - w * Math.sin(a),
var l = ptlist.length - 1;
Math.atan2(ptlist[1][1] - ptlist[0][1], ptlist[1][0] - ptlist[0][0]) -
ptlist[l][1] - ptlist[l - 1][1],
ptlist[l][0] - ptlist[l - 1][0],
ptlist[0][0] + w0 * Math.cos(a0),
ptlist[0][1] + w0 * Math.sin(a0),
ptlist[0][0] - w0 * Math.cos(a0),
ptlist[0][1] - w0 * Math.sin(a0),
ptlist[l][0] + w1 * Math.cos(a1),
ptlist[l][1] + w1 * Math.sin(a1),
ptlist[l][0] - w1 * Math.cos(a1),
ptlist[l][1] - w1 * Math.sin(a1),
return [vtxlist0, vtxlist1];
var tranpoly = function(p0, p1, ptlist) {
var plist = ptlist.map(function(v) {
var ang = Math.atan2(p1[1] - p0[1], p1[0] - p0[0]) - Math.PI / 2;
var scl = distance(p0, p1);
var qlist = plist.map(function(v) {
var d = distance(v, [0, 0]);
var a = Math.atan2(v[1], v[0]);
p0[0] + d * scl * Math.cos(ang + a),
p0[1] + d * scl * Math.sin(ang + a),
var flipper = function(plist) {
return plist.map(function(v) {
this.hat01 = function(p0, p1, args) {
var args = args != undefined ? args : {};
var fli = args.fli != undefined ? args.fli : false;
var seed = Math.random();
{ fil: "rgba(100,100,100,0.8)" },
for (var i = 0; i < 10; i++) {
-0.3 - noise(i * 0.2, seed) * i * 0.1,
canv += poly(tranpoly(p0, p1, f(qlist1)), {
str: "rgba(100,100,100,0.8)",
this.hat02 = function(p0, p1, args) {
var args = args != undefined ? args : {};
var fli = args.fli != undefined ? args.fli : false;
var seed = Math.random();
{ fil: "rgba(100,100,100,0.8)" },
this.stick01 = function(p0, p1, args) {
var args = args != undefined ? args : {};
var fli = args.fli != undefined ? args.fli : false;
var seed = Math.random();
for (var i = 0; i < l; i++) {
-noise(i * 0.1, seed) * 0.1 * Math.sin((i / l) * Math.PI) * 5,
canv += poly(tranpoly(p0, p1, f(qlist1)), {
str: "rgba(100,100,100,0.5)",
this.man = function(xoff, yoff, args) {
var args = args != undefined ? args : {};
var sca = args.sca != undefined ? args.sca : 0.5;
var hat = args.hat != undefined ? args.hat : Man.hat01;
var fli = args.fli != undefined ? args.fli : true;
(Math.PI / 4) * Math.random(),
((Math.PI * 3) / 4) * Math.random(),
(-Math.PI * 3) / 4 - (Math.PI / 4) * Math.random(),
args.len != undefined ? args.len : [0, 30, 20, 30, 30, 30, 30, 30, 30];
len = len.map(function(v) {
0: { 1: { 2: {}, 5: { 6: {} }, 7: { 8: {} } }, 3: { 4: {} } },
var toGlobal = function(v) {
return [(fli ? -1 : 1) * v[0] + xoff, v[1] + yoff];
function gpar(sct, ind) {
var keys = Object.keys(sct);
for (var i = 0; i < keys.length; i++) {
var r = gpar(sct[keys[i]], ind);
return [parseFloat(keys[i])].concat(r);
function grot(sct, ind) {
var par = gpar(sct, ind);
for (var i = 0; i < par.length; i++) {
function gpos(sct, ind) {
var par = gpar(sct, ind);
for (var i = 0; i < par.length; i++) {
var a = grot(sct, par[i]);
pos[0] += len[par[i]] * Math.cos(a);
pos[1] += len[par[i]] * Math.sin(a);
for (var i = 0; i < ang.length; i++) {
for (var i = 1; i < pts.length; i++) {
var p0 = gpos(sct, par[par.length - 2]);
var s = div([p0, pts[i]], 10);
var cloth = function(plist, fun) {
var tlist = bezmh(plist, 2);
var [tlist1, tlist2] = expand(tlist, fun);
canv += poly(tlist1.concat(tlist2.reverse()).map(toGlobal), {
canv += mystroke(tlist1.map(toGlobal), {
col: "rgba(100,100,100,0.5)",
canv += mystroke(tlist2.map(toGlobal), {
col: "rgba(100,100,100,0.6)",
var fsleeve = function(x) {
(Math.sin(0.5 * x * Math.PI) * Math.pow(Math.sin(x * Math.PI), 0.1) +
var fbody = function(x) {
(Math.sin(0.5 * x * Math.PI) * Math.pow(Math.sin(x * Math.PI), 0.1) +
var fhead = function(x) {
return sca * 7 * Math.pow(0.25 - Math.pow(x - 0.5, 2), 0.3);
canv += ite(toGlobal(pts[8]), toGlobal(pts[6]), { fli: fli });
canv += cloth([pts[1], pts[7], pts[8]], fsleeve);
canv += cloth([pts[1], pts[0], pts[3], pts[4]], fbody);
canv += cloth([pts[1], pts[5], pts[6]], fsleeve);
canv += cloth([pts[1], pts[2]], fhead);
var hlist = bezmh([pts[1], pts[2]], 2);
var [hlist1, hlist2] = expand(hlist, fhead);
hlist1.splice(0, Math.floor(hlist1.length * 0.1));
hlist2.splice(0, Math.floor(hlist2.length * 0.95));
canv += poly(hlist1.concat(hlist2.reverse()).map(toGlobal), {
fil: "rgba(100,100,100,0.6)",
canv += hat(toGlobal(pts[1]), toGlobal(pts[2]), { fli: fli });
function water(xoff, yoff, seed, args) {
var args = args != undefined ? args : {};
var hei = args.hei != undefined ? args.hei : 2;
var len = args.len != undefined ? args.len : 800;
var clu = args.clu != undefined ? args.clu : 10;
for (var i = 0; i < clu; i++) {
var xk = (Math.random() - 0.5) * (len / 8);
var lk = len / 4 + Math.random() * (len / 4);
for (var j = -lk; j < lk; j += reso) {
ptlist[ptlist.length - 1].push([
Math.sin(j * 0.2) * hei * noise(j * 0.1) - 20 + yk,
for (var j = 1; j < ptlist.length; j += 1) {
ptlist[j].map(function(x) {
return [x[0] + xoff, x[1] + yoff];
"rgba(100,100,100," + (0.3 + Math.random() * 0.3).toFixed(3) + ")",
function mountplanner(xmin, xmax) {
function locmax(x, y, f, r) {
for (var i = x - r; i < x + r; i++) {
for (var j = y - r; j < y + r; j++) {
function chadd(r, mind) {
mind = mind == undefined ? 10 : mind;
for (var k = 0; k < reg.length; k++) {
if (Math.abs(reg[k].x - r.x) < mind) {
var ns = function(x, y) {
return Math.max(noise(x * samp) - 0.55, 0) * 2;
return 1 - noise(x * samp);
var nnns = function(x, y) {
return Math.max(noise(x * samp * 2, 2) - 0.55, 0) * 2;
return noise(x * 0.01, Math.PI);
for (var i = xmin; i < xmax; i += xstep) {
var i1 = Math.floor(i / xstep);
MEM.planmtx[i1] = MEM.planmtx[i1] || 0;
for (var i = xmin; i < xmax; i += xstep) {
for (var j = 0; j < yr(i) * 480; j += 30) {
if (locmax(i, j, ns, 2)) {
var xof = i + 2 * (Math.random() - 0.5) * 500;
var r = { tag: "mount", x: xof, y: yof, h: ns(i, j) };
var k = Math.floor((xof - mwid) / xstep);
k < (xof + mwid) / xstep;
if (Math.abs(i) % 1000 < Math.max(1, xstep - 1)) {
y: 280 - Math.random() * 50,
console.log([xmin, xmax]);
for (var i = xmin; i < xmax; i += xstep) {
if (MEM.planmtx[Math.floor(i / xstep)] == 0) {
if (Math.random() < 0.01) {
for (var j = 0; j < 4 * Math.random(); j++) {
x: i + 2 * (Math.random() - 0.5) * 700,
for (var i = xmin; i < xmax; i += xstep) {
if (Math.random() < 0.2) {
var r = { tag: "boat", x: i, y: 300 + Math.random() * 390 };
function chunkloader(xmin, xmax) {
var addData = function(type, nch) {
if (MEM.water.length == 0) {
if (nch.y <= MEM.water[0].y) {
} else if (nch.y >= MEM.water[MEM.water.length - 1].y) {
for (var j = 0; j < MEM.water.length - 1; j++) {
if (MEM.water[j].y <= nch.y && nch.y <= MEM.water[j + 1].y) {
MEM.water.splice(j + 1, 0, nch);
} else if (type === 'mountain') {
if (MEM.mountain.length == 0) {
if (nch.y <= MEM.mountain[0].y) {
MEM.mountain.unshift(nch);
} else if (nch.y >= MEM.mountain[MEM.mountain.length - 1].y) {
for (var j = 0; j < MEM.mountain.length - 1; j++) {
if (MEM.mountain[j].y <= nch.y && nch.y <= MEM.mountain[j + 1].y) {
MEM.mountain.splice(j + 1, 0, nch);
if (MEM[type].length == 0) {
if (nch.y <= MEM[type][0].y) {
} else if (nch.y >= MEM[type][MEM[type].length - 1].y) {
for (var j = 0; j < MEM[type].length - 1; j++) {
if (MEM[type][j].y <= nch.y && nch.y <= MEM[type][j + 1].y) {
MEM[type].splice(j + 1, 0, nch);
while (xmax > MEM.xmax - MEM.cwid || xmin < MEM.xmin + MEM.cwid) {
console.log("generating new chunk...");
if (xmax > MEM.xmax - MEM.cwid) {
plan = mountplanner(MEM.xmax, MEM.xmax + MEM.cwid);
MEM.xmax = MEM.xmax + MEM.cwid;
plan = mountplanner(MEM.xmin - MEM.cwid, MEM.xmin);
MEM.xmin = MEM.xmin - MEM.cwid;
for (var i = 0; i < plan.length; i++) {
if (plan[i].tag == "mount") {
i: i * 2 * Math.random(),
} else if (plan[i].tag == "flatmount") {
} else if (plan[i].tag == "distmount") {
} else if (plan[i].tag == "boat") {
function chunkrender(xmin, xmax) {
for (var i = 0; i < MEM.distmount.length; i++) {
xmin - MEM.cwid < MEM.distmount[i].x &&
MEM.distmount[i].x < xmax + MEM.cwid
Mount.distMount(plan[i].x, plan[i].y, Math.random() * 100, {
len: randChoice([500, 1000, 1500]),
for (var i = 0; i < MEM.water.length; i++) {
xmin - MEM.cwid < MEM.water[i].x &&
MEM.water[i].x < xmax + MEM.cwid
water(plan[i].x, plan[i].y, plan[i].i, plan[i].i ? {} : {clu: 4})
for (var i = 0; i < MEM.mountain.length; i++) {
xmin - MEM.cwid < MEM.mountain[i].x &&
MEM.mountain[i].x < xmax + MEM.cwid
Mount.mountain(plan[i].x, plan[i].y, plan[i].i)
for (var i = 0; i < MEM.boat.length; i++) {
xmin - MEM.cwid < MEM.boat[i].x &&
MEM.boat[i].x < xmax + MEM.cwid
Arch.boat01(plan[i].x, plan[i].y, Math.random(), {
fli: randChoice([true, false]),
for (var i = 0; i < MEM.flatmount.length; i++) {
xmin - MEM.cwid < MEM.flatmount[i].x &&
MEM.flatmount[i].x < xmax + MEM.cwid
2 * Math.random() * Math.PI,
wid: 600 + Math.random() * 400,
cho: 0.5 + Math.random() * 0.2,
self.chunkloader(MEM.cursx, MEM.cursx + MEM.windx);
self.chunkrender(MEM.cursx, MEM.cursx + MEM.windx);