UNPKG

toloframework

Version:

Javascript/HTML/CSS compiler for Firefox OS or nodewebkit apps using modules in the nodejs style.

404 lines (361 loc) 12.8 kB
"use strict"; module.exports = { m4: { identity: identity4, matrix: mat4, vector: vec4, projection: projection4, translation: translation4, rotationX: rotationX4, rotationY: rotationY4, rotationZ: rotationZ4, scaling: scaling4, copy, normalize, cameraPolar: cameraPolar4, perspective: perspective4, mul }, m3: { identity: identity3, matrix: mat3, projection: projection3, translation: translation3, rotation: rotation3, scaling: scaling3, copy, normalize, polar, mul } }; /** * Imagine the earth oriented with the Z axis from south top north. * This function will return a normalized vector from the center of the earth * to the point located by (lat, lng). * * @param {float} lat - Latitude in range [-PI/2, +PI/2]. * @param {float} lng - Longitude in range [0, 2*PI]. * @param {Float32Array} _vector - The vector where to store the result. * If missing, a new one will be created. * * @return {Float32Array} The resulting 3D vector. */ function polar(lat, lng, _vector) { const vector = typeof _vector !== "undefined" ? _vector : new Float32Array(3), radius = Math.cos(lat), z = Math.sin(lat), x = radius * Math.cos(lng), y = radius * Math.sin(lng); vector[0] = x; vector[1] = y; vector[2] = z; return vector; } function copy(arr) { return new Float32Array(arr); } /** * Make a vector have a length of 1. * * @param {Float32Array} arr - Input vector. * @returns {Float32Array} A new vector. */ function normalize(arr) { const n = copy(arr); let len = 0; for (const v of n) len += v * v; if (len > 0) { const coeff = 1 / Math.sqrt(len); for (let k = 0; k < n.length; k++) { n[k] *= coeff; } } return n; } function cameraPolar4(targetX, targetY, targetZ, dis, lat, lng, result) { result = result || new Float32Array(16); var cosLat = Math.cos(lat); var sinLat = Math.sin(lat); var cosLng = -Math.cos(lng + Math.PI * .5); var sinLng = -Math.sin(lng + Math.PI * .5); // Vecteur Z de la caméra. var Zx = cosLng * cosLat; var Zy = sinLng * cosLat; var Zz = sinLat; // V2/2 // Le vecteur X se déduit par un produit vectoriel de (0,0,1) avec Z. var Xx = -Zy; var Xy = Zx; var Xz = 0; // Comme (0,0,1) n'est pas orthogonal à Z, il faut normaliser X. var len = Math.sqrt(Xx * Xx + Xy * Xy + Xz * Xz); Xx /= len; Xy /= len; Xz /= len; // Y peut alors se déduire par le produit vectoriel de Z par X. // Et il n'y aura pas besoin de le normaliser. var Yx = Zy * Xz - Zz * Xy; var Yy = Xx * Zz - Xz * Zx; var Yz = Zx * Xy - Zy * Xx; // Translation. var Tx = -(Zx * dis + targetX); var Ty = -(Zy * dis + targetY); var Tz = -(Zz * dis + targetZ); // Le résultat est la multiplication de la projection avec la translation. result[0] = Xx; result[4] = Xy; result[8] = Xz; result[12] = Tx * Xx + Ty * Xy + Tz * Xz; result[1] = Yx; result[5] = Yy; result[9] = Yz; result[13] = Tx * Yx + Ty * Yy + Tz * Yz; result[2] = Zx; result[6] = Zy; result[10] = Zz; result[14] = Tx * Zx + Ty * Zy + Tz * Zz; result[3] = 0; result[7] = 0; result[11] = 0; result[15] = 1; return result; } /** * Define the `frustum`. * @param {number} fieldAngle - View angle in radians. Maximum is PI. * @param {number} aspect - (width / height) of the canvas. * @param {number} near - Clip every Z lower than `near`. * @param {number} far - Clip every Z greater than `far`. */ function perspective4(fieldAngle, aspect, near, far, result) { result = result || new Float32Array(16); var f = Math.tan(Math.PI * 0.5 - 0.5 * fieldAngle); var rangeInv = 1.0 / (near - far); result[0] = f / aspect; result[1] = 0; result[2] = 0; result[3] = 0; result[4] = 0; result[5] = f; result[6] = 0; result[7] = 0; result[8] = 0; result[9] = 0; result[10] = (near + far) * rangeInv; result[11] = -1; result[12] = 0; result[13] = 0; result[14] = near * far * rangeInv * 2; result[15] = 0; return result; } function identity3() { return mat3(1, 0, 0, 0, 1, 0, 0, 0, 1); } function identity4() { return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); } function inverse4(m, dst) { dst = dst || mat4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); var m00 = m[0]; var m01 = m[1]; var m02 = m[2]; var m03 = m[3]; var m10 = m[4]; var m12 = m[5]; var m11 = m[6]; var m13 = m[7]; var m20 = m[8]; var m21 = m[9]; var m22 = m[10]; var m23 = m[11]; var m30 = m[12]; var m31 = m[13]; var m32 = m[14]; var m33 = m[15]; var tmp_0 = m22 * m33; var tmp_1 = m32 * m23; var tmp_2 = m12 * m33; var tmp_3 = m32 * m13; var tmp_4 = m12 * m23; var tmp_5 = m22 * m13; var tmp_6 = m02 * m33; var tmp_7 = m32 * m03; var tmp_8 = m02 * m23; var tmp_9 = m22 * m03; var tmp_10 = m02 * m13; var tmp_11 = m12 * m03; var tmp_12 = m20 * m31; var tmp_13 = m30 * m21; var tmp_14 = m10 * m31; var tmp_15 = m30 * m11; var tmp_16 = m10 * m21; var tmp_17 = m20 * m11; var tmp_18 = m00 * m31; var tmp_19 = m30 * m01; var tmp_20 = m00 * m21; var tmp_21 = m20 * m01; var tmp_22 = m00 * m11; var tmp_23 = m10 * m01; var t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) - (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31); var t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) - (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31); var t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) - (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31); var t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) - (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21); var 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; } function projection3(width, height) { return mat3(2 / width, 0, 0, 0, -2 / height, 0, 0, 0, 1); } function projection4(width, height, depth) { return mat4(2 / width, 0, 0, 0, 0, -2 / height, 0, 0, 0, 0, 2 / depth, 0, 0, 0, 0, 1); } function translation3(tx, ty) { return mat3(1, 0, 0, 0, 1, 0, tx, ty, 1); } function translation4(tx, ty, tz) { return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1); } function rotation3(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return mat3(c, -s, 0, s, c, 0, 0, 0, 1); } function rotationX4(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return mat4(1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1); } function rotationY4(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return mat4(c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1); } function rotationZ4(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return mat4(c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); } function scaling3(sx, sy) { return mat3(sx, 0, 0, 0, sy, 0, 0, 0, 1); } function scaling4(sx, sy, sz) { return mat4(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1); } function mat2(v00, v10, v01, v11) { return Float32Array([v00, v10, v01, v11]); } function mat3(v00, v10, v20, v01, v11, v21, v02, v12, v22) { return new Float32Array([v00, v10, v20, v01, v11, v21, v02, v12, v22]); } function mat4(v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13, v23, v33) { return new Float32Array([v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13, v23, v33]); } function vec2(a, b) { return new Float32Array([a, b]); } function vec3(a, b, c) { return new Float32Array([a, b, c]); } function vec4(a, b, c, d) { return new Float32Array([a, b, c, d]); } const MUL = { m9m3(a, b, _result) { const result = _result || new Float32Array(3); result[0] = a[0] * b[0] + a[3] * b[1] + a[6] * b[2]; result[1] = a[1] * b[0] + a[4] * b[1] + a[7] * b[2]; result[2] = a[2] * b[0] + a[5] * b[1] + a[8] * b[2]; return result; }, m4m4(a, b, _result) { const result = _result || new Float32Array(4); result[0] = a[0] * b[0] + a[2] * b[1]; result[1] = a[1] * b[0] + a[3] * b[1]; result[2] = a[0] * b[2] + a[2] * b[3]; result[3] = a[1] * b[2] + a[3] * b[3]; return result; }, m9m9(a, b, _result) { const result = _result || new Float32Array(9); result[0] = a[0] * b[0] + a[3] * b[1] + a[6] * b[2]; result[1] = a[1] * b[0] + a[4] * b[1] + a[7] * b[2]; result[2] = a[2] * b[0] + a[5] * b[1] + a[8] * b[2]; result[3] = a[0] * b[3] + a[3] * b[4] + a[6] * b[5]; result[4] = a[1] * b[3] + a[4] * b[4] + a[7] * b[5]; result[5] = a[2] * b[3] + a[5] * b[4] + a[8] * b[5]; result[6] = a[0] * b[6] + a[3] * b[7] + a[6] * b[8]; result[7] = a[1] * b[6] + a[4] * b[7] + a[7] * b[8]; result[8] = a[2] * b[6] + a[5] * b[7] + a[8] * b[8]; return result; }, m16m16(a, b, _result) { const result = _result || new Float32Array(16); result[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3]; result[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3]; result[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3]; result[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3]; result[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7]; result[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7]; result[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7]; result[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7]; result[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11]; result[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11]; result[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11]; result[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11]; result[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15]; result[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15]; result[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15]; result[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]; return result; }, m16m4(a, b, _result) { const result = _result || new Float32Array(4); result[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3]; result[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3]; result[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3]; result[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3]; return result; } }; function mul(a, b, result) { var f = MUL['m' + a.length + 'm' + b.length]; if (typeof f !== 'function') { throw Error("[webgl.math.mul] I don't know how to multiply 'M" + a.length + "' with 'M" + b.length + "'!"); } return f(a, b, result); }