UNPKG

matrix-engine-wgpu

Version:

Networking implemented - based on kurento openvidu server. fix arcball camera,instanced draws added also effect pipeline blend with instancing option.Normalmap added, Fixed shadows casting vs camera/video texture, webGPU powered pwa application. Crazy fas

1,793 lines (1,707 loc) 963 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.application = void 0; var _world = _interopRequireDefault(require("./src/world.js")); var _loaderObj = require("./src/engine/loader-obj.js"); var _utils = require("./src/engine/utils.js"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } let application = exports.application = new _world.default({ useSingleRenderPass: true, mainCameraParams: { type: 'WASD', responseCoef: 1000 }, canvasSize: 'fullscreen' }, () => { window.app = application; // for now window.downloadMeshes = _loaderObj.downloadMeshes; console.info(`%c matrix-engine-wgpu [ready]`, _utils.LOG_MATRIX); }); },{"./src/engine/loader-obj.js":34,"./src/engine/utils.js":41,"./src/world.js":64}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _bvhLoader = require("./module/bvh-loader"); var _default = exports.default = _bvhLoader.MEBvh; },{"./module/bvh-loader":3}],3:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MEBvhJoint = exports.MEBvh = void 0; exports.degToRad = degToRad; exports.dot3vs1 = dot3vs1; exports.euler2mat = euler2mat; exports.mat2euler = mat2euler; exports.multiply = multiply; var _webgpuMatrix = require("webgpu-matrix"); /** * @description Manual convert python script BVH * from https://github.com/dabeschte/npybvh to the JS. * @author Nikola Lukic * @license GPL-V3 */ function degToRad(degrees) { return degrees * Math.PI / 180; } ; function arraySum3(a, b) { var rez1 = a[0] + b[0]; var rez2 = a[1] + b[1]; var rez3 = a[2] + b[2]; return [rez1, rez2, rez3]; } function deg2rad(degrees) { return degrees * (Math.PI / 180); } function npdeg2rad(degrees) { return [degrees[0] * (Math.PI / 180), degrees[1] * (Math.PI / 180), degrees[2] * (Math.PI / 180)]; } function rad2deg(radians) { return radians * (180 / Math.PI); } function byId(id) { return document.getElementById(id); } // fix for .dot N-dim vs 1D-dim Array function dot3vs1(a, b) { var aNumRows = a.length, aNumCols = a[0].length, bNumRows = b.length; var REZ1 = 0, REZ2 = 0, REZ3 = 0; if (aNumRows == 3 && aNumCols == 3 && bNumRows == 3) { for (var j = 0; j < a.length; j++) { // First root of 3x3 a. REZ1 += a[0][j] * b[j]; REZ2 += a[1][j] * b[j]; REZ3 += a[2][j] * b[j]; } var finalRez = [REZ1, REZ2, REZ3]; return finalRez; } else { console.error("Bad arguments for dot3vs1"); } } function multiply(a, b) { var aNumRows = a.length, aNumCols = a[0].length, bNumRows = b.length, bNumCols = b[0].length, m = new Array(aNumRows); for (var r = 0; r < aNumRows; ++r) { m[r] = new Array(bNumCols); for (var c = 0; c < bNumCols; ++c) { m[r][c] = 0; for (var i = 0; i < aNumCols; ++i) { m[r][c] += a[r][i] * b[i][c]; } } } return m; } /** * @description * Euler's rotation theorem tells us that any rotation in 3D can be described by 3 * angles. Let's call the 3 angles the *Euler angle vector* and call the angles * in the vector :Math:`alpha`, :Math:`beta` and :Math:`gamma`. The vector is [ * :Math:`alpha`, :Math:`beta`. :Math:`gamma` ] and, in this description, the * order of the parameters specifies the order in which the rotations occur (so * the rotation corresponding to :Math:`alpha` is applied first). * @source https://github.com/matthew-brett/transforms3d/blob/master/transforms3d/euler.py */ // map axes strings to/from tuples of inner axis, parity, repetition, frame var _AXES2TUPLE = { 'sxyz': [0, 0, 0, 0], 'sxyx': [0, 0, 1, 0], 'sxzy': [0, 1, 0, 0], 'sxzx': [0, 1, 1, 0], 'syzx': [1, 0, 0, 0], 'syzy': [1, 0, 1, 0], 'syxz': [1, 1, 0, 0], 'syxy': [1, 1, 1, 0], 'szxy': [2, 0, 0, 0], 'szxz': [2, 0, 1, 0], 'szyx': [2, 1, 0, 0], 'szyz': [2, 1, 1, 0], 'rzyx': [0, 0, 0, 1], 'rxyx': [0, 0, 1, 1], 'ryzx': [0, 1, 0, 1], 'rxzx': [0, 1, 1, 1], 'rxzy': [1, 0, 0, 1], 'ryzy': [1, 0, 1, 1], 'rzxy': [1, 1, 0, 1], 'ryxy': [1, 1, 1, 1], 'ryxz': [2, 0, 0, 1], 'rzxz': [2, 0, 1, 1], 'rxyz': [2, 1, 0, 1], 'rzyz': [2, 1, 1, 1] }; // axis sequences for Euler angles var _NEXT_AXIS = [1, 2, 0, 1]; function euler2mat(ai, aj, ak, axes) { if (typeof axes === 'undefined') var axes = 'sxyz'; // Return rotation matrix from Euler angles and axis sequence. // Parameters /* ai : float First rotation angle (according to `axes`). aj : float Second rotation angle (according to `axes`). ak : float Third rotation angle (according to `axes`). axes : str, optional Axis specification; one of 24 axis sequences as string or encoded tuple - e.g. ``sxyz`` (the default). Returns ------- mat : array (3, 3) Rotation matrix or affine. Examples -------- >>> R = euler2mat(1, 2, 3, 'syxz') >>> np.allclose(np.sum(R[0]), -1.34786452) True >>> R = euler2mat(1, 2, 3, (0, 1, 0, 1)) >>> np.allclose(np.sum(R[0]), -0.383436184) True */ try { var firstaxis = _AXES2TUPLE[axes][0], parity = _AXES2TUPLE[axes][1], repetition = _AXES2TUPLE[axes][2], frame = _AXES2TUPLE[axes][3]; } catch (AttributeError) { // _TUPLE2AXES[axes] # validation // firstaxis, parity, repetition, frame = axes console.error("AttributeError: ", AttributeError); } var i = firstaxis; var j = _NEXT_AXIS[i + parity]; var k = _NEXT_AXIS[i - parity + 1]; if (frame) { ai = ak; ak = ai; } if (parity) { ai = -ai; aj = -aj; ak = -ak; } var si = Math.sin(ai); var sj = Math.sin(aj); var sk = Math.sin(ak); var ci = Math.cos(ai); var cj = Math.cos(aj); var ck = Math.cos(ak); var cc = ci * ck; var cs = ci * sk; var sc = si * ck; var ss = si * sk; // M = np.eye(3) var M = [[1., 0., 0], [0., 1., 0], [0., 0., 1]]; if (repetition) { M[i][i] = cj; M[i][j] = sj * si; M[i][k] = sj * ci; M[j][i] = sj * sk; M[j][j] = -cj * ss + cc; M[j][k] = -cj * cs - sc; M[k][i] = -sj * ck; M[k][j] = cj * sc + cs; M[k][k] = cj * cc - ss; } else { M[i][i] = cj * ck; M[i][j] = sj * sc - cs; M[i][k] = sj * cc + ss; M[j][i] = cj * sk; M[j][j] = sj * ss + cc; M[j][k] = sj * cs - sc; M[k][i] = -sj; M[k][j] = cj * si; M[k][k] = cj * ci; } return M; } /** * @description * How to calculate the angle from rotation matrix. */ function mat2euler(M, rad2deg_flag) { var pitch_1, pitch_2, roll_1, roll_2, yaw_1, yaw_2, pitch, roll, yaw; if (M[2][0] != 1 & M[2][0] != -1) { pitch_1 = -1 * Math.asin(M[2][0]); pitch_2 = Math.PI - pitch_1; roll_1 = Math.atan2(M[2][1] / Math.cos(pitch_1), M[2][2] / Math.cos(pitch_1)); roll_2 = Math.atan2(M[2][1] / Math.cos(pitch_2), M[2][2] / Math.cos(pitch_2)); yaw_1 = Math.atan2(M[1][0] / Math.cos(pitch_1), M[0][0] / Math.cos(pitch_1)); yaw_2 = Math.atan2(M[1][0] / Math.cos(pitch_2), M[0][0] / Math.cos(pitch_2)); pitch = pitch_1; roll = roll_1; yaw = yaw_1; } else { yaw = 0; if (M[2][0] == -1) { pitch = Math.PI / 2; roll = yaw + Math.atan2(M[0][1], M[0][2]); } else { pitch = -Math.PI / 2; roll = -1 * yaw + Math.atan2(-1 * M[0][1], -1 * M[0][2]); } } if (typeof rad2deg_flag !== "undefined") { // convert from radians to degrees roll = roll * 180 / Math.PI; pitch = pitch * 180 / Math.PI; yaw = yaw * 180 / Math.PI; } return [roll, pitch, yaw]; } class MEBvhJoint { constructor(name, parent) { this.name = name; this.parent = parent; this.offset = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; this.channels = []; this.children = []; // New: where in the frame array this joint’s channels start ??? this.channelOffset = 0; } add_child(child) { this.children.push(child); } __repr__() { return this.name; } position_animated() { var detFlag = false; for (const item in this.channels) { if (this.channels[item].endsWith("position") == true) { detFlag = true; } } return detFlag; } rotation_animated() { var detFlag = false; for (const item in this.channels) { if (this.channels[item].endsWith("rotation") == true) { detFlag = true; } } return detFlag; } createIdentityMatrix() { // Returns a flat Float32Array of length 16 (column-major) return new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); } matrixFromKeyframe(frameData) { const m = this.createIdentityMatrix(); let t = [0, 0, 0]; let r = [0, 0, 0]; for (let i = 0; i < this.channels.length; i++) { const channel = this.channels[i]; const value = frameData[this.channelOffset + i]; // channelOffset = index into frameData where this joint’s values start switch (channel) { case 'Xposition': t[0] = value; break; case 'Yposition': t[1] = value; break; case 'Zposition': t[2] = value; break; case 'Xrotation': r[0] = degToRad(value); break; case 'Yrotation': r[1] = degToRad(value); break; case 'Zrotation': r[2] = degToRad(value); break; } } // Apply translation _webgpuMatrix.mat4.translate(m, t, m); // Apply rotations in BVH order (important!) _webgpuMatrix.mat4.rotateX(m, r[0], m); _webgpuMatrix.mat4.rotateY(m, r[1], m); _webgpuMatrix.mat4.rotateZ(m, r[2], m); return m; } } exports.MEBvhJoint = MEBvhJoint; class MEBvh { constructor() { this.joints = {}; this.root = null; this.keyframes = null; this.frames = 0; this.fps = 0; this.myName = "MATRIX-ENGINE-BVH"; // new this.jointOrder = []; // array to store joints in order } computeJointOrder() { this.jointOrder = []; const traverse = joint => { this.jointOrder.push(joint.name); for (const child of joint.children) { traverse(child); } }; traverse(this.root); // root is your MEBvhJoint } computeChannelOffsets() { let offset = 0; const walk = joint => { joint.channelOffset = offset; // assign offset += joint.channels.length; // advance for (const child of joint.children) { walk(child); } }; if (this.root) walk(this.root); this.totalChannels = offset; // store total for frame allocation } async parse_file(link) { return new Promise((resolve, reject) => { fetch(link).then(event => { event.text().then(text => { var hierarchy = text.split("MOTION")[0]; var motion = text.split("MOTION")[1]; var newLog = document.createElement("div"); newLog.innerHTML += '<h2>Hierarchy</h2>'; newLog.innerHTML += '<p>' + hierarchy + '</p>'; var newLog2 = document.createElement("span"); newLog2.innerHTML += '<h2>Motion</h2>'; newLog2.innerHTML += '<p class="paragraf fixHeight" >' + motion + '</p>'; if (byId && byId('log') !== null) { byId('log').appendChild(newLog2); byId('log').appendChild(newLog); } this._parse_hierarchy(hierarchy); this.computeJointOrder(); this.computeChannelOffsets(); // <— must do this here NEW this.parse_motion(motion); resolve(); }); }); }); } _parse_hierarchy(text) { var lines = text.split(/\s*\n+\s*/); var joint_stack = []; for (var key in lines) { var line = lines[key]; var words = line.split(/\s+/); var instruction = words[0]; var parent = null; if (instruction == "JOINT" || instruction == "ROOT") { if (instruction == "JOINT") { // -1 py -> last item parent = joint_stack[joint_stack.length - 1]; } else { parent = null; } var joint = new MEBvhJoint(words[1], parent); this.joints[joint.name] = joint; if (parent != null) { parent.add_child(joint); } joint_stack.push(joint); if (instruction == "ROOT") { this.root = joint; } } else if (instruction == "CHANNELS") { for (var j = 2; j < words.length; j++) { joint_stack[joint_stack.length - 1].channels.push(words[j]); } } else if (instruction == "OFFSET") { for (var j = 1; j < words.length; j++) { joint_stack[joint_stack.length - 1].offset[j - 1] = parseFloat(words[j]); } } else if (instruction == "End") { var joint = new MEBvhJoint(joint_stack[joint_stack.length - 1].name + "_end", joint_stack[joint_stack.length - 1]); joint_stack[joint_stack.length - 1].add_child(joint); joint_stack.push(joint); this.joints[joint.name] = joint; } else if (instruction == "}") { joint_stack.pop(); } } } _add_pose_recursive(joint, offset, poses) { var newLog1 = document.createElement("span"); newLog1.innerHTML += '<h2>add_pose_recursive</h2>'; newLog1.innerHTML += '<p class="paragraf" >Joint Name: ' + joint.name + '</p>'; newLog1.innerHTML += '<p>joint.parent : ' + (joint.parent != null ? joint.parent.name : 'null') + '</p>'; newLog1.innerHTML += '<p>joint.offset : ' + joint.offset + '</p>'; newLog1.innerHTML += '<p>joint.children.length : ' + joint.children.length + '</p>'; joint.children.length != 0 ? newLog1.innerHTML += '<p> Childrens: ' : newLog1.innerHTML += 'No Childrens '; joint.children.forEach(iJoint => { newLog1.innerHTML += ' ' + iJoint['name'] + ' , '; }); newLog1.innerHTML += '</p>'; newLog1.innerHTML += '<p>Argument offset : ' + offset + '</p>'; byId('log').appendChild(newLog1); var pose = arraySum3(joint.offset, offset); poses.push(pose); for (var c in joint.children) { this._add_pose_recursive(joint.children[c], pose, poses); } } plot_hierarchy() { // import matplotlib.pyplot as plt // from mpl_toolkits.mplot3d import axes3d, Axes3D var poses = []; this._add_pose_recursive(this.root, [0, 0, 0], poses); // pos = np.array(poses); /* Draw staff DISABLED fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(pos[:, 0], pos[:, 2], pos[:, 1]) ax.set_xlim(-30, 30) ax.set_ylim(-30, 30) ax.set_zlim(-30, 30) plt.show() */ } parse_motion(text) { var lines = text.split(/\s*\n+\s*/); var frame = 0; for (var key in lines) { var line = lines[key]; if (line == "") { continue; } var words = line.split(/\s+/); if (line.startsWith("Frame Time:")) { this.fps = Math.round(1 / parseFloat(words[2])); continue; } if (line.startsWith("Frames:")) { this.frames = parseInt(words[1]); continue; } if (this.keyframes == null) { // OK this is just costruction (define) with random values. var localArr = Array.from(Array(this.frames), () => new Array(words.length)); this.keyframes = localArr; } for (var angle_index = 0; angle_index < words.length; angle_index++) { this.keyframes[frame][angle_index] = parseFloat(words[angle_index]); } frame += 1; } } _extract_rotation(frame_pose, index_offset, joint) { var local_rotation = [0, 0, 0], M_rotation; for (var key in joint.channels) { var channel = joint.channels[key]; if (channel.endsWith("position")) { continue; } if (channel == "Xrotation") { local_rotation[0] = frame_pose[index_offset]; } else if (channel == "Yrotation") { local_rotation[1] = frame_pose[index_offset]; } else if (channel == "Zrotation") { local_rotation[2] = frame_pose[index_offset]; } else { console.warn("Unknown channel {channel}"); // raise Exception(f"Unknown channel {channel}"); } index_offset += 1; } local_rotation = npdeg2rad(local_rotation); M_rotation = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; for (key in joint.channels) { var channel = joint.channels[key]; if (channel.endsWith("position")) { continue; } var euler_rot; if (channel == "Xrotation") { // console.warn("local_rotation " + local_rotation); euler_rot = [local_rotation[0], 0., 0.]; } else if (channel == "Yrotation") { euler_rot = [0., local_rotation[1], 0.]; } else if (channel == "Zrotation") { euler_rot = [0., 0., local_rotation[2]]; } else { console.warn("Unknown channel {channel}"); } var M_channel = euler2mat(euler_rot[0], euler_rot[1], euler_rot[2], euler_rot[3]); var M_rotation = multiply(M_rotation, M_channel); } return [M_rotation, index_offset]; } _extract_position(joint, frame_pose, index_offset) { var offset_position = [0, 0, 0]; for (var key in joint.channels) { var channel = joint.channels[key]; if (channel.endsWith("rotation")) { continue; } if (channel == "Xposition") { offset_position[0] = frame_pose[index_offset]; } else if (channel == "Yposition") { offset_position[1] = frame_pose[index_offset]; } else if (channel == "Zposition") { offset_position[2] = frame_pose[index_offset]; } else { console.warn("Unknown channel {channel}"); // raise Exception(f"Unknown channel {channel}") } index_offset += 1; } return [offset_position, index_offset]; } _recursive_apply_frame(joint, frame_pose, index_offset, p, r, M_parent, p_parent) { var joint_index; if (joint.position_animated()) { var local = this._extract_position(joint, frame_pose, index_offset); var offset_position = local[0], index_offset = local[1]; } else { var offset_position = [0, 0, 0]; } if (joint.channels.length == 0) { var local2 = 0; for (var item in this.joints) { if (joint.name == item) { joint_index = local2; } local2++; } p[joint_index] = arraySum3(p_parent, dot3vs1(M_parent, joint.offset)); r[joint_index] = mat2euler(M_parent); return index_offset; } if (joint.rotation_animated()) { var local2 = this._extract_rotation(frame_pose, index_offset, joint); var M_rotation = local2[0]; index_offset = local2[1]; } else { var M_rotation = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; } var M = multiply(M_parent, M_rotation); // https://www.khanacademy.org/math/precalculus/x9e81a4f98389efdf:matrices/x9e81a4f98389efdf:adding-and-subtracting-matrices/e/matrix_addition_and_subtraction var position = arraySum3(p_parent, dot3vs1(M_parent, joint.offset)); position = arraySum3(position, offset_position); var rotation = mat2euler(M, "rad2deg"); // just find by id var local = 0; for (const item in this.joints) { if (joint.name == item) { joint_index = local; } local++; } p[joint_index] = position; r[joint_index] = rotation; for (var c in joint.children) { index_offset = this._recursive_apply_frame(joint.children[c], frame_pose, index_offset, p, r, M, position); } return index_offset; } frame_pose(frame) { var jointLength = 0; for (var x in this.joints) { jointLength++; } var p = Array.from(Array(jointLength), () => [0, 0, 0]); var r = Array.from(Array(jointLength), () => [0, 0, 0]); var frame_pose = this.keyframes[frame]; var M_parent = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; M_parent[0][0] = 1; M_parent[1][1] = 1; M_parent[2][2] = 1; this._recursive_apply_frame(this.root, frame_pose, 0, p, r, M_parent, [0, 0, 0]); return [p, r]; } all_frame_poses() { var jointLength = 0; for (var x in this.joints) { jointLength++; } var p = Array.from({ length: this.frames }, () => Array.from({ length: jointLength }, () => [0, 0, 0])); var r = Array.from({ length: this.frames }, () => Array.from({ length: jointLength }, () => [0, 0, 0])); for (var frame = 0; frame < this.keyframes.length; frame++) { var local3 = this.frame_pose(frame); p[frame] = local3[0]; r[frame] = local3[1]; } return [p, r]; } _plot_pose(p, r, fig, ax) { /* _plot_pose(p, r, fig=None, ax=None) { import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import axes3d, Axes3D if fig is None: fig = plt.figure() if ax is None: ax = fig.add_subplot(111, projection='3d') ax.cla() ax.scatter(p[:, 0], p[:, 2], p[:, 1]) ax.set_xlim(-30, 30) ax.set_ylim(-30, 30) ax.set_zlim(-1, 59) plt.draw() plt.pause(0.001) */ } // Meybe helps for draw // plot_frame(frame, fig=None, ax=None) { plot_frame(frame, fig, ax) { // ???? // p, (r = this.frame_pose(frame)); // this._plot_pose(p, r, fig, ax); } joint_names() { var keys = []; for (var key in this.joints) { keys.push(key); } return keys; } plot_all_frames() { /* import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import axes3d, Axes3D fig = plt.figure() ax = fig.add_subplot(111, projection='3d') for i in range(self.frames) { self.plot_frame(i, fig, ax); } */ } __repr__() { return `BVH.JS ${this.joints.keys().length} joints, ${this.frames} frames`; } } exports.MEBvh = MEBvh; },{"webgpu-matrix":15}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RANDOM = exports.EPSILON = exports.ARRAY_TYPE = exports.ANGLE_ORDER = void 0; exports.equals = equals; exports.round = round; exports.setMatrixArrayType = setMatrixArrayType; exports.toDegree = toDegree; exports.toRadian = toRadian; /** * Common utilities * @module glMatrix */ // Configuration Constants var EPSILON = exports.EPSILON = 0.000001; var ARRAY_TYPE = exports.ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array; var RANDOM = exports.RANDOM = Math.random; var ANGLE_ORDER = exports.ANGLE_ORDER = "zyx"; /** * Symmetric round * see https://www.npmjs.com/package/round-half-up-symmetric#user-content-detailed-background * * @param {Number} a value to round */ function round(a) { if (a >= 0) return Math.round(a); return a % 0.5 === 0 ? Math.floor(a) : Math.round(a); } /** * Sets the type of array used when creating new vectors and matrices * * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array */ function setMatrixArrayType(type) { exports.ARRAY_TYPE = ARRAY_TYPE = type; } var degree = Math.PI / 180; var radian = 180 / Math.PI; /** * Convert Degree To Radian * * @param {Number} a Angle in Degrees */ function toRadian(a) { return a * degree; } /** * Convert Radian To Degree * * @param {Number} a Angle in Radians */ function toDegree(a) { return a * radian; } /** * Tests whether or not the arguments have approximately the same value, within an absolute * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less * than or equal to 1.0, and a relative tolerance is used for larger values) * * @param {Number} a The first number to test. * @param {Number} b The second number to test. * @param {Number} tolerance Absolute or relative tolerance (default glMatrix.EPSILON) * @returns {Boolean} True if the numbers are approximately equal, false otherwise. */ function equals(a, b) { var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : EPSILON; return Math.abs(a - b) <= tolerance * Math.max(1, Math.abs(a), Math.abs(b)); } },{}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.vec4 = exports.vec3 = exports.vec2 = exports.quat2 = exports.quat = exports.mat4 = exports.mat3 = exports.mat2d = exports.mat2 = exports.glMatrix = void 0; var glMatrix = _interopRequireWildcard(require("./common.js")); exports.glMatrix = glMatrix; var mat2 = _interopRequireWildcard(require("./mat2.js")); exports.mat2 = mat2; var mat2d = _interopRequireWildcard(require("./mat2d.js")); exports.mat2d = mat2d; var mat3 = _interopRequireWildcard(require("./mat3.js")); exports.mat3 = mat3; var mat4 = _interopRequireWildcard(require("./mat4.js")); exports.mat4 = mat4; var quat = _interopRequireWildcard(require("./quat.js")); exports.quat = quat; var quat2 = _interopRequireWildcard(require("./quat2.js")); exports.quat2 = quat2; var vec2 = _interopRequireWildcard(require("./vec2.js")); exports.vec2 = vec2; var vec3 = _interopRequireWildcard(require("./vec3.js")); exports.vec3 = vec3; var vec4 = _interopRequireWildcard(require("./vec4.js")); exports.vec4 = vec4; function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } },{"./common.js":4,"./mat2.js":6,"./mat2d.js":7,"./mat3.js":8,"./mat4.js":9,"./quat.js":10,"./quat2.js":11,"./vec2.js":12,"./vec3.js":13,"./vec4.js":14}],6:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LDU = LDU; exports.add = add; exports.adjoint = adjoint; exports.clone = clone; exports.copy = copy; exports.create = create; exports.determinant = determinant; exports.equals = equals; exports.exactEquals = exactEquals; exports.frob = frob; exports.fromRotation = fromRotation; exports.fromScaling = fromScaling; exports.fromValues = fromValues; exports.identity = identity; exports.invert = invert; exports.mul = void 0; exports.multiply = multiply; exports.multiplyScalar = multiplyScalar; exports.multiplyScalarAndAdd = multiplyScalarAndAdd; exports.rotate = rotate; exports.scale = scale; exports.set = set; exports.str = str; exports.sub = void 0; exports.subtract = subtract; exports.transpose = transpose; var glMatrix = _interopRequireWildcard(require("./common.js")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /** * 2x2 Matrix * @module mat2 */ /** * Creates a new identity mat2 * * @returns {mat2} a new 2x2 matrix */ function create() { var out = new glMatrix.ARRAY_TYPE(4); if (glMatrix.ARRAY_TYPE != Float32Array) { out[1] = 0; out[2] = 0; } out[0] = 1; out[3] = 1; return out; } /** * Creates a new mat2 initialized with values from an existing matrix * * @param {ReadonlyMat2} a matrix to clone * @returns {mat2} a new 2x2 matrix */ function clone(a) { var out = new glMatrix.ARRAY_TYPE(4); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; } /** * Copy the values from one mat2 to another * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the source matrix * @returns {mat2} out */ function copy(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out; } /** * Set a mat2 to the identity matrix * * @param {mat2} out the receiving matrix * @returns {mat2} out */ function identity(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; return out; } /** * Create a new mat2 with the given values * * @param {Number} m00 Component in column 0, row 0 position (index 0) * @param {Number} m01 Component in column 0, row 1 position (index 1) * @param {Number} m10 Component in column 1, row 0 position (index 2) * @param {Number} m11 Component in column 1, row 1 position (index 3) * @returns {mat2} out A new 2x2 matrix */ function fromValues(m00, m01, m10, m11) { var out = new glMatrix.ARRAY_TYPE(4); out[0] = m00; out[1] = m01; out[2] = m10; out[3] = m11; return out; } /** * Set the components of a mat2 to the given values * * @param {mat2} out the receiving matrix * @param {Number} m00 Component in column 0, row 0 position (index 0) * @param {Number} m01 Component in column 0, row 1 position (index 1) * @param {Number} m10 Component in column 1, row 0 position (index 2) * @param {Number} m11 Component in column 1, row 1 position (index 3) * @returns {mat2} out */ function set(out, m00, m01, m10, m11) { out[0] = m00; out[1] = m01; out[2] = m10; out[3] = m11; return out; } /** * Transpose the values of a mat2 * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the source matrix * @returns {mat2} out */ function transpose(out, a) { // If we are transposing ourselves we can skip a few steps but have to cache // some values if (out === a) { var a1 = a[1]; out[1] = a[2]; out[2] = a1; } else { out[0] = a[0]; out[1] = a[2]; out[2] = a[1]; out[3] = a[3]; } return out; } /** * Inverts a mat2 * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the source matrix * @returns {mat2 | null} out, or null if source matrix is not invertible */ function invert(out, a) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; // Calculate the determinant var det = a0 * a3 - a2 * a1; if (!det) { return null; } det = 1.0 / det; out[0] = a3 * det; out[1] = -a1 * det; out[2] = -a2 * det; out[3] = a0 * det; return out; } /** * Calculates the adjugate of a mat2 * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the source matrix * @returns {mat2} out */ function adjoint(out, a) { // Caching this value is necessary if out == a var a0 = a[0]; out[0] = a[3]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a0; return out; } /** * Calculates the determinant of a mat2 * * @param {ReadonlyMat2} a the source matrix * @returns {Number} determinant of a */ function determinant(a) { return a[0] * a[3] - a[2] * a[1]; } /** * Multiplies two mat2's * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the first operand * @param {ReadonlyMat2} b the second operand * @returns {mat2} out */ function multiply(out, a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; out[0] = a0 * b0 + a2 * b1; out[1] = a1 * b0 + a3 * b1; out[2] = a0 * b2 + a2 * b3; out[3] = a1 * b2 + a3 * b3; return out; } /** * Rotates a mat2 by the given angle * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat2} out */ function rotate(out, a, rad) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; var s = Math.sin(rad); var c = Math.cos(rad); out[0] = a0 * c + a2 * s; out[1] = a1 * c + a3 * s; out[2] = a0 * -s + a2 * c; out[3] = a1 * -s + a3 * c; return out; } /** * Scales the mat2 by the dimensions in the given vec2 * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the matrix to rotate * @param {ReadonlyVec2} v the vec2 to scale the matrix by * @returns {mat2} out **/ function scale(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; var v0 = v[0], v1 = v[1]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; out[3] = a3 * v1; return out; } /** * Creates a matrix from a given angle * This is equivalent to (but much faster than): * * mat2.identity(dest); * mat2.rotate(dest, dest, rad); * * @param {mat2} out mat2 receiving operation result * @param {Number} rad the angle to rotate the matrix by * @returns {mat2} out */ function fromRotation(out, rad) { var s = Math.sin(rad); var c = Math.cos(rad); out[0] = c; out[1] = s; out[2] = -s; out[3] = c; return out; } /** * Creates a matrix from a vector scaling * This is equivalent to (but much faster than): * * mat2.identity(dest); * mat2.scale(dest, dest, vec); * * @param {mat2} out mat2 receiving operation result * @param {ReadonlyVec2} v Scaling vector * @returns {mat2} out */ function fromScaling(out, v) { out[0] = v[0]; out[1] = 0; out[2] = 0; out[3] = v[1]; return out; } /** * Returns a string representation of a mat2 * * @param {ReadonlyMat2} a matrix to represent as a string * @returns {String} string representation of the matrix */ function str(a) { return "mat2(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ")"; } /** * Returns Frobenius norm of a mat2 * * @param {ReadonlyMat2} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ function frob(a) { return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3]); } /** * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix * @param {ReadonlyMat2} L the lower triangular matrix * @param {ReadonlyMat2} D the diagonal matrix * @param {ReadonlyMat2} U the upper triangular matrix * @param {ReadonlyMat2} a the input matrix to factorize */ function LDU(L, D, U, a) { L[2] = a[2] / a[0]; U[0] = a[0]; U[1] = a[1]; U[3] = a[3] - L[2] * U[1]; return [L, D, U]; } /** * Adds two mat2's * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the first operand * @param {ReadonlyMat2} b the second operand * @returns {mat2} out */ function add(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; return out; } /** * Subtracts matrix b from matrix a * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the first operand * @param {ReadonlyMat2} b the second operand * @returns {mat2} out */ function subtract(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; out[3] = a[3] - b[3]; return out; } /** * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) * * @param {ReadonlyMat2} a The first matrix. * @param {ReadonlyMat2} b The second matrix. * @returns {Boolean} True if the matrices are equal, false otherwise. */ function exactEquals(a, b) { return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3]; } /** * Returns whether or not the matrices have approximately the same elements in the same position. * * @param {ReadonlyMat2} a The first matrix. * @param {ReadonlyMat2} b The second matrix. * @returns {Boolean} True if the matrices are equal, false otherwise. */ function equals(a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)); } /** * Multiply each element of the matrix by a scalar. * * @param {mat2} out the receiving matrix * @param {ReadonlyMat2} a the matrix to scale * @param {Number} b amount to scale the matrix's elements by * @returns {mat2} out */ function multiplyScalar(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; out[3] = a[3] * b; return out; } /** * Adds two mat2's after multiplying each element of the second operand by a scalar value. * * @param {mat2} out the receiving vector * @param {ReadonlyMat2} a the first operand * @param {ReadonlyMat2} b the second operand * @param {Number} scale the amount to scale b's elements by before adding * @returns {mat2} out */ function multiplyScalarAndAdd(out, a, b, scale) { out[0] = a[0] + b[0] * scale; out[1] = a[1] + b[1] * scale; out[2] = a[2] + b[2] * scale; out[3] = a[3] + b[3] * scale; return out; } /** * Alias for {@link mat2.multiply} * @function */ var mul = exports.mul = multiply; /** * Alias for {@link mat2.subtract} * @function */ var sub = exports.sub = subtract; },{"./common.js":4}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.add = add; exports.clone = clone; exports.copy = copy; exports.create = create; exports.determinant = determinant; exports.equals = equals; exports.exactEquals = exactEquals; exports.frob = frob; exports.fromRotation = fromRotation; exports.fromScaling = fromScaling; exports.fromTranslation = fromTranslation; exports.fromValues = fromValues; exports.identity = identity; exports.invert = invert; exports.mul = void 0; exports.multiply = multiply; exports.multiplyScalar = multiplyScalar; exports.multiplyScalarAndAdd = multiplyScalarAndAdd; exports.rotate = rotate; exports.scale = scale; exports.set = set; exports.str = str; exports.sub = void 0; exports.subtract = subtract; exports.translate = translate; var glMatrix = _interopRequireWildcard(require("./common.js")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /** * 2x3 Matrix * @module mat2d * @description * A mat2d contains six elements defined as: * <pre> * [a, b, * c, d, * tx, ty] * </pre> * This is a short form for the 3x3 matrix: * <pre> * [a, b, 0, * c, d, 0, * tx, ty, 1] * </pre> * The last column is ignored so the array is shorter and operations are faster. */ /** * Creates a new identity mat2d * * @returns {mat2d} a new 2x3 matrix */ function create() { var out = new glMatrix.ARRAY_TYPE(6); if (glMatrix.ARRAY_TYPE != Float32Array) { out[1] = 0; out[2] = 0; out[4] = 0; out[5] = 0; } out[0] = 1; out[3] = 1; return out; } /** * Creates a new mat2d initialized with values from an existing matrix * * @param {ReadonlyMat2d} a matrix to clone * @returns {mat2d} a new 2x3 matrix */ function clone(a) { var out = new glMatrix.ARRAY_TYPE(6); out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; return out; } /** * Copy the values from one mat2d to another * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the source matrix * @returns {mat2d} out */ function copy(out, a) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[4] = a[4]; out[5] = a[5]; return out; } /** * Set a mat2d to the identity matrix * * @param {mat2d} out the receiving matrix * @returns {mat2d} out */ function identity(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = 0; out[5] = 0; return out; } /** * Create a new mat2d with the given values * * @param {Number} a Component A (index 0) * @param {Number} b Component B (index 1) * @param {Number} c Component C (index 2) * @param {Number} d Component D (index 3) * @param {Number} tx Component TX (index 4) * @param {Number} ty Component TY (index 5) * @returns {mat2d} A new mat2d */ function fromValues(a, b, c, d, tx, ty) { var out = new glMatrix.ARRAY_TYPE(6); out[0] = a; out[1] = b; out[2] = c; out[3] = d; out[4] = tx; out[5] = ty; return out; } /** * Set the components of a mat2d to the given values * * @param {mat2d} out the receiving matrix * @param {Number} a Component A (index 0) * @param {Number} b Component B (index 1) * @param {Number} c Component C (index 2) * @param {Number} d Component D (index 3) * @param {Number} tx Component TX (index 4) * @param {Number} ty Component TY (index 5) * @returns {mat2d} out */ function set(out, a, b, c, d, tx, ty) { out[0] = a; out[1] = b; out[2] = c; out[3] = d; out[4] = tx; out[5] = ty; return out; } /** * Inverts a mat2d * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the source matrix * @returns {mat2d | null} out, or null if source matrix is not invertible */ function invert(out, a) { var aa = a[0], ab = a[1], ac = a[2], ad = a[3]; var atx = a[4], aty = a[5]; var det = aa * ad - ab * ac; if (!det) { return null; } det = 1.0 / det; out[0] = ad * det; out[1] = -ab * det; out[2] = -ac * det; out[3] = aa * det; out[4] = (ac * aty - ad * atx) * det; out[5] = (ab * atx - aa * aty) * det; return out; } /** * Calculates the determinant of a mat2d * * @param {ReadonlyMat2d} a the source matrix * @returns {Number} determinant of a */ function determinant(a) { return a[0] * a[3] - a[1] * a[2]; } /** * Multiplies two mat2d's * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the first operand * @param {ReadonlyMat2d} b the second operand * @returns {mat2d} out */ function multiply(out, a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5]; var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; out[0] = a0 * b0 + a2 * b1; out[1] = a1 * b0 + a3 * b1; out[2] = a0 * b2 + a2 * b3; out[3] = a1 * b2 + a3 * b3; out[4] = a0 * b4 + a2 * b5 + a4; out[5] = a1 * b4 + a3 * b5 + a5; return out; } /** * Rotates a mat2d by the given angle * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the matrix to rotate * @param {Number} rad the angle to rotate the matrix by * @returns {mat2d} out */ function rotate(out, a, rad) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5]; var s = Math.sin(rad); var c = Math.cos(rad); out[0] = a0 * c + a2 * s; out[1] = a1 * c + a3 * s; out[2] = a0 * -s + a2 * c; out[3] = a1 * -s + a3 * c; out[4] = a4; out[5] = a5; return out; } /** * Scales the mat2d by the dimensions in the given vec2 * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the matrix to translate * @param {ReadonlyVec2} v the vec2 to scale the matrix by * @returns {mat2d} out **/ function scale(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5]; var v0 = v[0], v1 = v[1]; out[0] = a0 * v0; out[1] = a1 * v0; out[2] = a2 * v1; out[3] = a3 * v1; out[4] = a4; out[5] = a5; return out; } /** * Translates the mat2d by the dimensions in the given vec2 * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the matrix to translate * @param {ReadonlyVec2} v the vec2 to translate the matrix by * @returns {mat2d} out **/ function translate(out, a, v) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5]; var v0 = v[0], v1 = v[1]; out[0] = a0; out[1] = a1; out[2] = a2; out[3] = a3; out[4] = a0 * v0 + a2 * v1 + a4; out[5] = a1 * v0 + a3 * v1 + a5; return out; } /** * Creates a matrix from a given angle * This is equivalent to (but much faster than): * * mat2d.identity(dest); * mat2d.rotate(dest, dest, rad); * * @param {mat2d} out mat2d receiving operation result * @param {Number} rad the angle to rotate the matrix by * @returns {mat2d} out */ function fromRotation(out, rad) { var s = Math.sin(rad), c = Math.cos(rad); out[0] = c; out[1] = s; out[2] = -s; out[3] = c; out[4] = 0; out[5] = 0; return out; } /** * Creates a matrix from a vector scaling * This is equivalent to (but much faster than): * * mat2d.identity(dest); * mat2d.scale(dest, dest, vec); * * @param {mat2d} out mat2d receiving operation result * @param {ReadonlyVec2} v Scaling vector * @returns {mat2d} out */ function fromScaling(out, v) { out[0] = v[0]; out[1] = 0; out[2] = 0; out[3] = v[1]; out[4] = 0; out[5] = 0; return out; } /** * Creates a matrix from a vector translation * This is equivalent to (but much faster than): * * mat2d.identity(dest); * mat2d.translate(dest, dest, vec); * * @param {mat2d} out mat2d receiving operation result * @param {ReadonlyVec2} v Translation vector * @returns {mat2d} out */ function fromTranslation(out, v) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 1; out[4] = v[0]; out[5] = v[1]; return out; } /** * Returns a string representation of a mat2d * * @param {ReadonlyMat2d} a matrix to represent as a string * @returns {String} string representation of the matrix */ function str(a) { return "mat2d(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ")"; } /** * Returns Frobenius norm of a mat2d * * @param {ReadonlyMat2d} a the matrix to calculate Frobenius norm of * @returns {Number} Frobenius norm */ function frob(a) { return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3] + a[4] * a[4] + a[5] * a[5] + 1); } /** * Adds two mat2d's * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the first operand * @param {ReadonlyMat2d} b the second operand * @returns {mat2d} out */ function add(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; out[4] = a[4] + b[4]; out[5] = a[5] + b[5]; return out; } /** * Subtracts matrix b from matrix a * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the first operand * @param {ReadonlyMat2d} b the second operand * @returns {mat2d} out */ function subtract(out, a, b) { out[0] = a[0] - b[0]; out[1] = a[1] - b[1]; out[2] = a[2] - b[2]; out[3] = a[3] - b[3]; out[4] = a[4] - b[4]; out[5] = a[5] - b[5]; return out; } /** * Multiply each element of the matrix by a scalar. * * @param {mat2d} out the receiving matrix * @param {ReadonlyMat2d} a the matrix to scale * @param {Number} b amount to scale the matrix's elements by * @returns {mat2d} out */ function multiplyScalar(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; out[3] = a[3] * b; out[4] = a[4] * b; out[5] = a[5] * b; return out; } /** * Adds two mat2d's after multiplying each element of the second operand by a scalar value. * * @param {mat2d} out the receiving vector * @param {ReadonlyMat2d} a the first operand * @param {ReadonlyMat2d} b the second operand * @param {Number} scale the amount to scale b's elements by before adding * @returns {mat2d} out */ function multiplyScalarAndAdd(out, a, b, scale) { out[0] = a[0] + b[0] * scale; out[1] = a[1] + b[1] * scale; out[2] = a[2] + b[2] * scale; out[3] = a[3] + b[3] * scale; out[4] = a[4] + b[4] * scale; out[5] = a[5] + b[5] * scale; return out; } /** * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===) * * @param {ReadonlyMat2d} a The first matrix. * @param {ReadonlyMat2d} b The second matrix. * @returns {Boolean} True if the matrices are equal, false otherwise. */ function exactEquals(a, b) { return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5]; } /** * Returns whether or not the matrices have approximately the same elements in the same position. * * @param {ReadonlyMat2d} a The first matrix. * @param {ReadonlyMat2d} b The second matrix. * @returns {Boolean} True if the matrices are equal, false otherwise. */ function equals(a, b) { var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5]; var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSI