2020-04-05 15:28:22 +02:00
|
|
|
class VTUtils {
|
|
|
|
static random(min, max) {
|
|
|
|
let rand = Math.random();
|
|
|
|
if (typeof min === 'undefined') {
|
|
|
|
return rand;
|
|
|
|
} else if (typeof max === 'undefined') {
|
|
|
|
if (min instanceof Array) {
|
|
|
|
return min[Math.floor(rand * min.length)];
|
|
|
|
} else {
|
|
|
|
return rand * min;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (min > max) {
|
|
|
|
let tmp = min;
|
|
|
|
min = max;
|
|
|
|
max = tmp;
|
|
|
|
}
|
|
|
|
return rand * (max - min) + min;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static randomInt(min, max) {
|
|
|
|
return Math.floor(VTUtils.random(min, max));
|
|
|
|
}
|
|
|
|
|
|
|
|
static normalize(val, max, min) {
|
|
|
|
return (val - min) / (max - min);
|
|
|
|
};
|
|
|
|
|
|
|
|
static distance(x, y, x2, y2) {
|
|
|
|
let a = x - x2;
|
|
|
|
let b = y - y2;
|
|
|
|
|
|
|
|
return Math.sqrt(a * a + b * b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static map(n, start1, stop1, start2, stop2, withinBounds) {
|
|
|
|
let newVal = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
|
|
|
|
if (!withinBounds) {
|
|
|
|
return newVal;
|
|
|
|
}
|
|
|
|
if (start2 < stop2) {
|
|
|
|
return this.constrain(newVal, start2, stop2);
|
|
|
|
} else {
|
|
|
|
return this.constrain(newVal, stop2, start2);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static constrain(n, low, high) {
|
|
|
|
return Math.max(Math.min(n, high), low);
|
|
|
|
}
|
|
|
|
|
|
|
|
static hsvToRgb(h, s, v) {
|
|
|
|
var r, g, b;
|
|
|
|
|
|
|
|
var i = Math.floor(h * 6);
|
|
|
|
var f = h * 6 - i;
|
|
|
|
var p = v * (1 - s);
|
|
|
|
var q = v * (1 - f * s);
|
|
|
|
var t = v * (1 - (1 - f) * s);
|
|
|
|
|
|
|
|
switch (i % 6) {
|
|
|
|
case 0:
|
|
|
|
r = v, g = t, b = p;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
r = q, g = v, b = p;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r = p, g = v, b = t;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
r = p, g = q, b = v;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r = t, g = p, b = v;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
r = v, g = p, b = q;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {r: r, g: g, b: b};
|
|
|
|
}
|
|
|
|
|
|
|
|
static peakRGB(peak) {
|
|
|
|
return {
|
|
|
|
r: peak,
|
|
|
|
g: 1 - peak,
|
|
|
|
b: 0
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class VTVector {
|
|
|
|
constructor(x, y, z) {
|
|
|
|
this.x = x || 0;
|
|
|
|
this.y = y || 0;
|
|
|
|
this.z = z || 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//helper
|
|
|
|
static createRandom(x, y, z) {
|
|
|
|
x = x || 1;
|
|
|
|
y = y || 1;
|
|
|
|
z = z || 0;
|
|
|
|
return new VTVector(VTUtils.random(-x, x), VTUtils.random(-y, y), VTUtils.random(-z, z));
|
|
|
|
}
|
|
|
|
|
|
|
|
mult(times) {
|
|
|
|
this.x *= times;
|
|
|
|
this.y *= times;
|
|
|
|
this.z *= times;
|
|
|
|
}
|
|
|
|
|
|
|
|
set(vector) {
|
|
|
|
this.x = vector.x;
|
|
|
|
this.y = vector.y;
|
|
|
|
this.z = vector.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
add(vector) {
|
|
|
|
this.x = this.x + vector.x;
|
|
|
|
this.y = this.y + vector.y;
|
|
|
|
this.z = this.z + vector.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
addXYZ(x, y, z) {
|
|
|
|
this.x += x;
|
|
|
|
this.y += y;
|
|
|
|
this.z += z;
|
|
|
|
}
|
|
|
|
|
2020-04-07 21:44:46 +02:00
|
|
|
setXYZ(x, y, z) {
|
2020-04-05 15:28:22 +02:00
|
|
|
this.x = x || 0;
|
|
|
|
this.y = y || 0;
|
|
|
|
this.z = z || 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
clone() {
|
|
|
|
return new VTVector(this.x, this.y, this.z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class TDUtils {
|
|
|
|
static multiply(a, b) {
|
|
|
|
let b00 = b[0 * 4 + 0];
|
|
|
|
let b01 = b[0 * 4 + 1];
|
|
|
|
let b02 = b[0 * 4 + 2];
|
|
|
|
let b03 = b[0 * 4 + 3];
|
|
|
|
let b10 = b[1 * 4 + 0];
|
|
|
|
let b11 = b[1 * 4 + 1];
|
|
|
|
let b12 = b[1 * 4 + 2];
|
|
|
|
let b13 = b[1 * 4 + 3];
|
|
|
|
let b20 = b[2 * 4 + 0];
|
|
|
|
let b21 = b[2 * 4 + 1];
|
|
|
|
let b22 = b[2 * 4 + 2];
|
|
|
|
let b23 = b[2 * 4 + 3];
|
|
|
|
let b30 = b[3 * 4 + 0];
|
|
|
|
let b31 = b[3 * 4 + 1];
|
|
|
|
let b32 = b[3 * 4 + 2];
|
|
|
|
let b33 = b[3 * 4 + 3];
|
|
|
|
let a00 = a[0 * 4 + 0];
|
|
|
|
let a01 = a[0 * 4 + 1];
|
|
|
|
let a02 = a[0 * 4 + 2];
|
|
|
|
let a03 = a[0 * 4 + 3];
|
|
|
|
let a10 = a[1 * 4 + 0];
|
|
|
|
let a11 = a[1 * 4 + 1];
|
|
|
|
let a12 = a[1 * 4 + 2];
|
|
|
|
let a13 = a[1 * 4 + 3];
|
|
|
|
let a20 = a[2 * 4 + 0];
|
|
|
|
let a21 = a[2 * 4 + 1];
|
|
|
|
let a22 = a[2 * 4 + 2];
|
|
|
|
let a23 = a[2 * 4 + 3];
|
|
|
|
let a30 = a[3 * 4 + 0];
|
|
|
|
let a31 = a[3 * 4 + 1];
|
|
|
|
let a32 = a[3 * 4 + 2];
|
|
|
|
let a33 = a[3 * 4 + 3];
|
|
|
|
let dst = [];
|
|
|
|
dst[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
|
|
|
dst[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
|
|
|
dst[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
|
|
|
dst[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
|
|
|
dst[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
|
|
|
dst[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
|
|
|
dst[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
|
|
|
dst[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
|
|
|
dst[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
|
|
|
dst[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
|
|
|
dst[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
|
|
|
dst[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
|
|
|
dst[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
|
|
|
dst[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
|
|
|
dst[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
|
|
|
dst[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
2020-08-06 23:44:37 +02:00
|
|
|
static xRotation(angle) {
|
|
|
|
angle = TDUtils.degToRad(angle);
|
|
|
|
let c = Math.cos(angle);
|
|
|
|
let s = Math.sin(angle);
|
2020-04-05 15:28:22 +02:00
|
|
|
|
|
|
|
return [
|
|
|
|
1, 0, 0, 0,
|
|
|
|
0, c, s, 0,
|
|
|
|
0, -s, c, 0,
|
|
|
|
0, 0, 0, 1,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-08-06 23:44:37 +02:00
|
|
|
static yRotation(angle) {
|
|
|
|
angle = TDUtils.degToRad(angle);
|
|
|
|
let c = Math.cos(angle);
|
|
|
|
let s = Math.sin(angle);
|
2020-04-05 15:28:22 +02:00
|
|
|
|
|
|
|
return [
|
|
|
|
c, 0, -s, 0,
|
|
|
|
0, 1, 0, 0,
|
|
|
|
s, 0, c, 0,
|
|
|
|
0, 0, 0, 1,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-08-06 23:44:37 +02:00
|
|
|
static zRotation(angle) {
|
|
|
|
angle = TDUtils.degToRad(angle);
|
|
|
|
let c = Math.cos(angle);
|
|
|
|
let s = Math.sin(angle);
|
2020-04-05 15:28:22 +02:00
|
|
|
|
|
|
|
return [
|
|
|
|
c, s, 0, 0,
|
|
|
|
-s, c, 0, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 0, 1,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
static degToRad(d) {
|
|
|
|
return d * Math.PI / 180;
|
|
|
|
}
|
|
|
|
}
|
2020-04-07 21:44:46 +02:00
|
|
|
|
|
|
|
function $(sel, s) {
|
|
|
|
return $$(sel, s)[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
function $$(sel, s) {
|
|
|
|
s = s || document;
|
|
|
|
return s.querySelectorAll(sel);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node.prototype.addDelegatedEventListener = function (type, aim, cb) {
|
|
|
|
this.addEventListener(type, (event) => {
|
|
|
|
let target = event.target;
|
|
|
|
if (target.matches(aim)) {
|
|
|
|
cb(event, target);
|
|
|
|
} else {
|
|
|
|
let parent = target.closest(aim);
|
|
|
|
if (parent) {
|
|
|
|
cb(event, parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
function create(name, content) {
|
|
|
|
let d = document.createElement(name);
|
|
|
|
if (content) {
|
|
|
|
d.innerHTML = content;
|
|
|
|
}
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
function append(to, array) {
|
|
|
|
for (let item in array) {
|
|
|
|
to.appendChild(array[item]);
|
|
|
|
}
|
|
|
|
}
|