// most of the functions are from https://webglfundamentals.org/webgl/resources/m4.js! but i doesnt want to use them all and make some adjustment to them! class TDUtils { static lastMatrix = {m: null}; static multiply(a, b) { let b00 = b[0]; let b01 = b[1]; let b02 = b[2]; let b03 = b[3]; let b10 = b[4]; let b11 = b[5]; let b12 = b[6]; let b13 = b[7]; let b20 = b[8]; let b21 = b[9]; let b22 = b[10]; let b23 = b[11]; let b30 = b[12]; let b31 = b[13]; let b32 = b[14]; let b33 = b[15]; let a00 = a[0]; let a01 = a[1]; let a02 = a[2]; let a03 = a[3]; let a10 = a[4]; let a11 = a[5]; let a12 = a[6]; let a13 = a[7]; let a20 = a[8]; let a21 = a[9]; let a22 = a[10]; let a23 = a[11]; let a30 = a[12]; let a31 = a[13]; let a32 = a[14]; let a33 = a[15]; return [ b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30, b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31, b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32, b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33, b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30, b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31, b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32, b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33, b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30, b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31, b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32, b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33, b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30, b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31, b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32, b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33 ]; } static translate(m, tx, ty, tz, dst) { dst = dst || new Float32Array(16); let m00 = m[0], m01 = m[1], m02 = m[2], m03 = m[3], m10 = m[4], m11 = m[5], m12 = m[6], m13 = m[7], m20 = m[8], m21 = m[9], m22 = m[10], m23 = m[11], m30 = m[12], m31 = m[13], m32 = m[14], m33 = m[15]; dst[0] = m00; dst[1] = m01; dst[2] = m02; dst[3] = m03; dst[4] = m10; dst[5] = m11; dst[6] = m12; dst[7] = m13; dst[8] = m20; dst[9] = m21; dst[10] = m22; dst[11] = m23; dst[12] = m00 * tx + m10 * ty + m20 * tz + m30; dst[13] = m01 * tx + m11 * ty + m21 * tz + m31; dst[14] = m02 * tx + m12 * ty + m22 * tz + m32; dst[15] = m03 * tx + m13 * ty + m23 * tz + m33; return dst; } static xRotation(angle) { angle = TDUtils.degToRad(angle); let c = Math.cos(angle); let s = Math.sin(angle); return [ 1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, ]; } static yRotation(angle) { angle = TDUtils.degToRad(angle); let c = Math.cos(angle); let s = Math.sin(angle); return [ c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1, ]; } static zRotation(angle) { angle = TDUtils.degToRad(angle); let c = Math.cos(angle); let s = Math.sin(angle); 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; } static scale(sx, sy, sz, dst) { dst = dst || new Float32Array(16); dst[0] = sx; dst[5] = sy; dst[10] = sz; return dst; } static lookAt(cameraPosition, target, up, dst) { dst = dst || new Float32Array(16); let zAxis = TDUtils.normalize( TDUtils.subtractVectors(cameraPosition, target)); let xAxis = TDUtils.normalize(TDUtils.cross(up, zAxis)); let yAxis = TDUtils.normalize(TDUtils.cross(zAxis, xAxis)); dst[0] = xAxis[0]; dst[1] = xAxis[1]; dst[2] = xAxis[2]; dst[4] = yAxis[0]; dst[5] = yAxis[1]; dst[6] = yAxis[2]; dst[8] = zAxis[0]; dst[9] = zAxis[1]; dst[10] = zAxis[2]; dst[12] = cameraPosition[0]; dst[13] = cameraPosition[1]; dst[14] = cameraPosition[2]; dst[15] = 1; return dst; } static cross(a, b, dst) { dst = dst || new Float32Array(3); dst[0] = a[1] * b[2] - a[2] * b[1]; dst[1] = a[2] * b[0] - a[0] * b[2]; dst[2] = a[0] * b[1] - a[1] * b[0]; return dst; } static normalize(v, dst) { dst = dst || new Float32Array(3); let length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); if (length > 0.00001) { dst[0] = v[0] / length; dst[1] = v[1] / length; dst[2] = v[2] / length; } return dst; } static subtractVectors(a, b, dst) { dst = dst || new Float32Array(3); dst[0] = a[0] - b[0]; dst[1] = a[1] - b[1]; dst[2] = a[2] - b[2]; return dst; } static perspective(fieldOfViewInRadians, aspect, near, far, dst) { dst = dst || new Float32Array(16); let f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewInRadians), rangeInv = 1.0 / (near - far); dst[0] = f / aspect; dst[5] = f; dst[10] = (near + far) * rangeInv; dst[11] = -1; dst[14] = near * far * rangeInv * 2; return dst; } static inverse(m, dst) { dst = dst || new Float32Array(16); let m00 = m[0], m01 = m[1], m02 = m[2], m03 = m[3], m10 = m[4], m11 = m[5], m12 = m[6], m13 = m[7], m20 = m[8], m21 = m[9], m22 = m[10], m23 = m[11], m30 = m[12], m31 = m[13], m32 = m[14], m33 = m[15], tmp_0 = m22 * m33, tmp_1 = m32 * m23, tmp_2 = m12 * m33, tmp_3 = m32 * m13, tmp_4 = m12 * m23, tmp_5 = m22 * m13, tmp_6 = m02 * m33, tmp_7 = m32 * m03, tmp_8 = m02 * m23, tmp_9 = m22 * m03, tmp_10 = m02 * m13, tmp_11 = m12 * m03, tmp_12 = m20 * m31, tmp_13 = m30 * m21, tmp_14 = m10 * m31, tmp_15 = m30 * m11, tmp_16 = m10 * m21, tmp_17 = m20 * m11, tmp_18 = m00 * m31, tmp_19 = m30 * m01, tmp_20 = m00 * m21, tmp_21 = m20 * m01, tmp_22 = m00 * m11, tmp_23 = m10 * m01, t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) - (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31), t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) - (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31), t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) - (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31), t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) - (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21), d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3); dst[0] = d * t0; dst[1] = d * t1; dst[2] = d * t2; dst[3] = d * t3; dst[4] = d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) - (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)); dst[5] = d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) - (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)); dst[6] = d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) - (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)); dst[7] = d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) - (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)); dst[8] = d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) - (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)); dst[9] = d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) - (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)); dst[10] = d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) - (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)); dst[11] = d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) - (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)); dst[12] = d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) - (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)); dst[13] = d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) - (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)); dst[14] = d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) - (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)); dst[15] = d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) - (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)); return dst; } static aspectView(aspect) { return [ 1 * aspect, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] } static getMatrix(fov, aspect, near, far, camAngle, radius) { let lMat = this.lastMatrix, u = TDUtils; if (!u.isSame('fov', fov) || !u.isSame('aspect', aspect) || !u.isSame('near', near) || !u.isSame('far', far) || !u.isSame('cam', camAngle) || !u.isSame('radius', radius) ) { let matrix = TDUtils.perspective(TDUtils.degToRad(fov), aspect, near, far), cameraMatrix = TDUtils.yRotation(TDUtils.degToRad(camAngle)); cameraMatrix = TDUtils.translate(cameraMatrix, 0, 0, radius * 1.5); let viewMatrix = TDUtils.inverse(cameraMatrix); matrix = TDUtils.multiply(matrix, viewMatrix) lMat.m = matrix; } return lMat.m; } static isSame(key, value) { let lMat = this.lastMatrix; if (lMat[key] !== value) { lMat[key] = value; return false; } return true; } static updateRotate(rotation, def) { let value = vConf.get(rotation, def) + vConf.get(rotation + '-inc', 0) if (value > 360) { value -= 360; } else if (value < -360) { value += 360; } vConf.set(rotation, value); } }