text: /*!
   *
   * Planck.js v0.3.22
   *
   * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
   * Copyright (c) 2006-2013 Erin Catto  http://www.gphysics.com
   *
   * This software is provided 'as-is', without any express or implied
   * warranty.  In no event will the authors be held liable for any damages
   * arising from the use of this software.
   *
   * Permission is granted to anyone to use this software for any purpose,
   * including commercial applications, and to alter it and redistribute it
   * freely, subject to the following restrictions:
   *
   * 1. The origin of this software must not be misrepresented; you must not
   * claim that you wrote the original software. If you use this software
   * in a product, an acknowledgment in the product documentation would be
   * appreciated but is not required.
   * 2. Altered source versions must be plainly marked as such, and must not be
   * misrepresented as being the original software.
   * 3. This notice may not be removed or altered from any source distribution.
   *
   */
  var planck = (function (modules) {
  	// webpackBootstrap
  	/******/ // The module cache
  	/******/ var installedModules = {}; // The require function
  	/******/
  	/******/ /******/ function __webpack_require__ (moduleId) {
  		/******/
  		/******/ // Check if module is in cache
  		/******/ if (installedModules[moduleId]) {
  			/******/ return installedModules[moduleId].exports;
  			/******/
  		} // Create a new module (and put it into the cache)
  		/******/ /******/ var module = (installedModules[moduleId] = {
  			/******/ i: moduleId,
  			/******/ l: false,
  			/******/ exports: {}
  			/******/
  		}); // Execute the module function
  		/******/
  		/******/ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // Flag the module as loaded
  		/******/
  		/******/ /******/ module.l = true; // Return the exports of the module
  		/******/
  		/******/ /******/ return module.exports;
  		/******/
  	} // expose the modules object (__webpack_modules__)
  	/******/
  	/******/
  	/******/ /******/ __webpack_require__.m = modules; // expose the module cache
  	/******/
  	/******/ /******/ __webpack_require__.c = installedModules; // define getter function for harmony exports
  	/******/
  	/******/ /******/ __webpack_require__.d = function (exports, name, getter) {
  		/******/ if (!__webpack_require__.o(exports, name)) {
  			/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
  			/******/
  		}
  		/******/
  	}; // define __esModule on exports
  	/******/
  	/******/ /******/ __webpack_require__.r = function (exports) {
  		/******/ if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  			/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  			/******/
  		}
  		/******/ Object.defineProperty(exports, '__esModule', { value: true });
  		/******/
  	}; // create a fake namespace object // mode & 1: value is a module id, require it // mode & 2: merge all properties of value into the ns // mode & 4: return value when already ns object // mode & 8|1: behave like require
  	/******/
  	/******/ /******/ /******/ /******/ /******/ /******/ __webpack_require__.t = function (value, mode) {
  		/******/ if (mode & 1) value = __webpack_require__(value);
  		/******/ if (mode & 8) return value;
  		/******/ if (mode & 4 && typeof value === 'object' && value && value.__esModule) return value;
  		/******/ var ns = Object.create(null);
  		/******/ __webpack_require__.r(ns);
  		/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  		/******/ if (mode & 2 && typeof value != 'string')
  			for (var key in value)
  				__webpack_require__.d(
  					ns,
  					key,
  					function (key) {
  						return value[key];
  					}.bind(null, key)
  				);
  		/******/ return ns;
  		/******/
  	}; // getDefaultExport function for compatibility with non-harmony modules
  	/******/
  	/******/ /******/ __webpack_require__.n = function (module) {
  		/******/ var getter =
              module && module.__esModule
              	? /******/ function getDefault () {
              		return module.default;
              	}
              	: /******/ function getModuleExports () {
              		return module;
              	};
  		/******/ __webpack_require__.d(getter, 'a', getter);
  		/******/ return getter;
  		/******/
  	}; // Object.prototype.hasOwnProperty.call
  	/******/
  	/******/ /******/ __webpack_require__.o = function (object, property) {
  		return Object.prototype.hasOwnProperty.call(object, property);
  	}; // __webpack_public_path__
  	/******/
  	/******/ /******/ __webpack_require__.p = ''; // Load entry module and return exports
  	/******/
  	/******/
  	/******/ /******/ return __webpack_require__((__webpack_require__.s = 39));
  	/******/
  })(
  	/************************************************************************/
  	/******/ [
  		/* 0 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Vec2;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  
  			function Vec2 (x, y) {
  				if (!(this instanceof Vec2)) {
  					return new Vec2(x, y);
  				}
  				if (typeof x === 'undefined') {
  					this.x = 0;
  					this.y = 0;
  				} else if (typeof x === 'object') {
  					this.x = x.x;
  					this.y = x.y;
  				} else {
  					this.x = x;
  					this.y = y;
  				}
  				_ASSERT && Vec2.assert(this);
  			}
  
  			Vec2.prototype._serialize = function () {
  				return {
  					x: this.x,
  					y: this.y
  				};
  			};
  
  			Vec2._deserialize = function (data) {
  				var obj = Object.create(Vec2.prototype);
  				obj.x = data.x;
  				obj.y = data.y;
  				return obj;
  			};
  
  			Vec2.zero = function () {
  				var obj = Object.create(Vec2.prototype);
  				obj.x = 0;
  				obj.y = 0;
  				return obj;
  			};
  
  			Vec2.neo = function (x, y) {
  				var obj = Object.create(Vec2.prototype);
  				obj.x = x;
  				obj.y = y;
  				return obj;
  			};
  
  			Vec2.clone = function (v) {
  				_ASSERT && Vec2.assert(v);
  				return Vec2.neo(v.x, v.y);
  			};
  
  			Vec2.prototype.toString = function () {
  				return JSON.stringify(this);
  			};
  
  			/**
               * Does this vector contain finite coordinates?
               */
  			Vec2.isValid = function (v) {
  				return v && Math.isFinite(v.x) && Math.isFinite(v.y);
  			};
  
  			Vec2.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!Vec2.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid Vec2!');
  				}
  			};
  
  			Vec2.prototype.clone = function () {
  				return Vec2.clone(this);
  			};
  
  			/**
               * Set this vector to all zeros.
               *
               * @returns this
               */
  			Vec2.prototype.setZero = function () {
  				this.x = 0.0;
  				this.y = 0.0;
  				return this;
  			};
  
  			/**
               * Set this vector to some specified coordinates.
               *
               * @returns this
               */
  			Vec2.prototype.set = function (x, y) {
  				if (typeof x === 'object') {
  					_ASSERT && Vec2.assert(x);
  					this.x = x.x;
  					this.y = x.y;
  				} else {
  					_ASSERT && Math.assert(x);
  					_ASSERT && Math.assert(y);
  					this.x = x;
  					this.y = y;
  				}
  				return this;
  			};
  
  			/**
               * @deprecated Use setCombine or setMul
               */
  			Vec2.prototype.wSet = function (a, v, b, w) {
  				if (typeof b !== 'undefined' || typeof w !== 'undefined') {
  					return this.setCombine(a, v, b, w);
  				} else {
  					return this.setMul(a, v);
  				}
  			};
  
  			/**
               * Set linear combination of v and w: `a * v + b * w`
               */
  			Vec2.prototype.setCombine = function (a, v, b, w) {
  				_ASSERT && Math.assert(a);
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Math.assert(b);
  				_ASSERT && Vec2.assert(w);
  				var x = a * v.x + b * w.x;
  				var y = a * v.y + b * w.y;
  
  				// `this` may be `w`
  				this.x = x;
  				this.y = y;
  				return this;
  			};
  
  			Vec2.prototype.setMul = function (a, v) {
  				_ASSERT && Math.assert(a);
  				_ASSERT && Vec2.assert(v);
  				var x = a * v.x;
  				var y = a * v.y;
  
  				this.x = x;
  				this.y = y;
  				return this;
  			};
  
  			/**
               * Add a vector to this vector.
               *
               * @returns this
               */
  			Vec2.prototype.add = function (w) {
  				_ASSERT && Vec2.assert(w);
  				this.x += w.x;
  				this.y += w.y;
  				return this;
  			};
  
  			/**
               * @deprecated Use addCombine or addMul
               */
  			Vec2.prototype.wAdd = function (a, v, b, w) {
  				if (typeof b !== 'undefined' || typeof w !== 'undefined') {
  					return this.addCombine(a, v, b, w);
  				} else {
  					return this.addMul(a, v);
  				}
  			};
  
  			/**
               * Add linear combination of v and w: `a * v + b * w`
               */
  			Vec2.prototype.addCombine = function (a, v, b, w) {
  				_ASSERT && Math.assert(a);
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Math.assert(b);
  				_ASSERT && Vec2.assert(w);
  
  				var x = a * v.x + b * w.x;
  				var y = a * v.y + b * w.y;
  
  				// `this` may be `w`
  				this.x += x;
  				this.y += y;
  				return this;
  			};
  
  			Vec2.prototype.addMul = function (a, v) {
  				_ASSERT && Math.assert(a);
  				_ASSERT && Vec2.assert(v);
  				var x = a * v.x;
  				var y = a * v.y;
  
  				this.x += x;
  				this.y += y;
  				return this;
  			};
  
  			/**
               * @deprecated Use subCombine or subMul
               */
  			Vec2.prototype.wSub = function (a, v, b, w) {
  				if (typeof b !== 'undefined' || typeof w !== 'undefined') {
  					return this.subCombine(a, v, b, w);
  				} else {
  					return this.subMul(a, v);
  				}
  			};
  
  			/**
               * Subtract linear combination of v and w: `a * v + b * w`
               */
  			Vec2.prototype.subCombine = function (a, v, b, w) {
  				_ASSERT && Math.assert(a);
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Math.assert(b);
  				_ASSERT && Vec2.assert(w);
  				var x = a * v.x + b * w.x;
  				var y = a * v.y + b * w.y;
  
  				// `this` may be `w`
  				this.x -= x;
  				this.y -= y;
  				return this;
  			};
  
  			Vec2.prototype.subMul = function (a, v) {
  				_ASSERT && Math.assert(a);
  				_ASSERT && Vec2.assert(v);
  				var x = a * v.x;
  				var y = a * v.y;
  
  				this.x -= x;
  				this.y -= y;
  				return this;
  			};
  
  			/**
               * Subtract a vector from this vector
               *
               * @returns this
               */
  			Vec2.prototype.sub = function (w) {
  				_ASSERT && Vec2.assert(w);
  				this.x -= w.x;
  				this.y -= w.y;
  				return this;
  			};
  
  			/**
               * Multiply this vector by a scalar.
               *
               * @returns this
               */
  			Vec2.prototype.mul = function (m) {
  				_ASSERT && Math.assert(m);
  				this.x *= m;
  				this.y *= m;
  				return this;
  			};
  
  			/**
               * Get the length of this vector (the norm).
               *
               * For performance, use this instead of lengthSquared (if possible).
               */
  			Vec2.prototype.length = function () {
  				return Vec2.lengthOf(this);
  			};
  
  			/**
               * Get the length squared.
               */
  			Vec2.prototype.lengthSquared = function () {
  				return Vec2.lengthSquared(this);
  			};
  
  			/**
               * Convert this vector into a unit vector.
               *
               * @returns old length
               */
  			Vec2.prototype.normalize = function () {
  				var length = this.length();
  				if (length < Math.EPSILON) {
  					return 0.0;
  				}
  				var invLength = 1.0 / length;
  				this.x *= invLength;
  				this.y *= invLength;
  				return length;
  			};
  
  			/**
               * Get the length of this vector (the norm).
               *
               * For performance, use this instead of lengthSquared (if possible).
               */
  			Vec2.lengthOf = function (v) {
  				_ASSERT && Vec2.assert(v);
  				return Math.sqrt(v.x * v.x + v.y * v.y);
  			};
  
  			/**
               * Get the length squared.
               */
  			Vec2.lengthSquared = function (v) {
  				_ASSERT && Vec2.assert(v);
  				return v.x * v.x + v.y * v.y;
  			};
  
  			Vec2.distance = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				var dx = v.x - w.x;
  				var dy = v.y - w.y;
  				return Math.sqrt(dx * dx + dy * dy);
  			};
  
  			Vec2.distanceSquared = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				var dx = v.x - w.x;
  				var dy = v.y - w.y;
  				return dx * dx + dy * dy;
  			};
  
  			Vec2.areEqual = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return v == w || (typeof w === 'object' && w !== null && v.x === w.x && v.y === w.y);
  			};
  
  			/**
               * Get the skew vector such that dot(skew_vec, other) == cross(vec, other)
               */
  			Vec2.skew = function (v) {
  				_ASSERT && Vec2.assert(v);
  				return Vec2.neo(-v.y, v.x);
  			};
  
  			/**
               * Perform the dot product on two vectors.
               */
  			Vec2.dot = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return v.x * w.x + v.y * w.y;
  			};
  
  			/**
               * Perform the cross product on two vectors. In 2D this produces a scalar.
               *
               * Perform the cross product on a vector and a scalar. In 2D this produces a
               * vector.
               */
  			Vec2.cross = function (v, w) {
  				if (typeof w === 'number') {
  					_ASSERT && Vec2.assert(v);
  					_ASSERT && Math.assert(w);
  					return Vec2.neo(w * v.y, -w * v.x);
  				} else if (typeof v === 'number') {
  					_ASSERT && Math.assert(v);
  					_ASSERT && Vec2.assert(w);
  					return Vec2.neo(-v * w.y, v * w.x);
  				} else {
  					_ASSERT && Vec2.assert(v);
  					_ASSERT && Vec2.assert(w);
  					return v.x * w.y - v.y * w.x;
  				}
  			};
  
  			/**
               * Returns `a + (v x w)`
               */
  			Vec2.addCross = function (a, v, w) {
  				if (typeof w === 'number') {
  					_ASSERT && Vec2.assert(v);
  					_ASSERT && Math.assert(w);
  					return Vec2.neo(w * v.y + a.x, -w * v.x + a.y);
  				} else if (typeof v === 'number') {
  					_ASSERT && Math.assert(v);
  					_ASSERT && Vec2.assert(w);
  					return Vec2.neo(-v * w.y + a.x, v * w.x + a.y);
  				}
  
  				_ASSERT && common.assert(false);
  			};
  
  			Vec2.add = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return Vec2.neo(v.x + w.x, v.y + w.y);
  			};
  
  			/**
               * @deprecated Use combine
               */
  			Vec2.wAdd = function (a, v, b, w) {
  				if (typeof b !== 'undefined' || typeof w !== 'undefined') {
  					return Vec2.combine(a, v, b, w);
  				} else {
  					return Vec2.mul(a, v);
  				}
  			};
  
  			Vec2.combine = function (a, v, b, w) {
  				return Vec2.zero().setCombine(a, v, b, w);
  			};
  
  			Vec2.sub = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return Vec2.neo(v.x - w.x, v.y - w.y);
  			};
  
  			Vec2.mul = function (a, b) {
  				if (typeof a === 'object') {
  					_ASSERT && Vec2.assert(a);
  					_ASSERT && Math.assert(b);
  					return Vec2.neo(a.x * b, a.y * b);
  				} else if (typeof b === 'object') {
  					_ASSERT && Math.assert(a);
  					_ASSERT && Vec2.assert(b);
  					return Vec2.neo(a * b.x, a * b.y);
  				}
  			};
  
  			Vec2.prototype.neg = function () {
  				this.x = -this.x;
  				this.y = -this.y;
  				return this;
  			};
  
  			Vec2.neg = function (v) {
  				_ASSERT && Vec2.assert(v);
  				return Vec2.neo(-v.x, -v.y);
  			};
  
  			Vec2.abs = function (v) {
  				_ASSERT && Vec2.assert(v);
  				return Vec2.neo(Math.abs(v.x), Math.abs(v.y));
  			};
  
  			Vec2.mid = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return Vec2.neo((v.x + w.x) * 0.5, (v.y + w.y) * 0.5);
  			};
  
  			Vec2.upper = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return Vec2.neo(Math.max(v.x, w.x), Math.max(v.y, w.y));
  			};
  
  			Vec2.lower = function (v, w) {
  				_ASSERT && Vec2.assert(v);
  				_ASSERT && Vec2.assert(w);
  				return Vec2.neo(Math.min(v.x, w.x), Math.min(v.y, w.y));
  			};
  
  			Vec2.prototype.clamp = function (max) {
  				var lengthSqr = this.x * this.x + this.y * this.y;
  				if (lengthSqr > max * max) {
  					var invLength = Math.invSqrt(lengthSqr);
  					this.x *= invLength * max;
  					this.y *= invLength * max;
  				}
  				return this;
  			};
  
  			Vec2.clamp = function (v, max) {
  				v = Vec2.neo(v.x, v.y);
  				v.clamp(max);
  				return v;
  			};
  
  			/**
               * @experimental
               */
  			Vec2.scaleFn = function (x, y) {
  				return function (v) {
  					return Vec2.neo(v.x * x, v.y * y);
  				};
  			};
  
  			/**
               * @experimental
               */
  			Vec2.translateFn = function (x, y) {
  				return function (v) {
  					return Vec2.neo(v.x + x, v.y + y);
  				};
  			};
  
  			/***/
  		},
  		/* 1 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var native = Math;
  			var math = (module.exports = create(native));
  
  			math.EPSILON = 1e-9; // TODO
  
  			/**
               * This function is used to ensure that a floating point number is not a NaN or
               * infinity.
               */
  			math.isFinite = function (x) {
  				return typeof x === 'number' && isFinite(x) && !isNaN(x);
  			};
  
  			math.assert = function (x) {
  				if (!_ASSERT) return;
  				if (!math.isFinite(x)) {
  					_DEBUG && common.debug(x);
  					throw new Error('Invalid Number!');
  				}
  			};
  
  			/**
               * TODO: This is a approximate yet fast inverse square-root.
               */
  			math.invSqrt = function (x) {
  				// TODO
  				return 1 / native.sqrt(x);
  			};
  
  			/**
               * Next Largest Power of 2 Given a binary integer value x, the next largest
               * power of 2 can be computed by a SWAR algorithm that recursively "folds" the
               * upper bits into the lower bits. This process yields a bit vector with the
               * same most significant 1 as x, but all 1's below it. Adding 1 to that value
               * yields the next largest power of 2. For a 32-bit value:
               */
  			math.nextPowerOfTwo = function (x) {
  				// TODO
  				x |= x >> 1;
  				x |= x >> 2;
  				x |= x >> 4;
  				x |= x >> 8;
  				x |= x >> 16;
  				return x + 1;
  			};
  
  			math.isPowerOfTwo = function (x) {
  				return x > 0 && (x & (x - 1)) == 0;
  			};
  
  			math.mod = function (num, min, max) {
  				if (typeof min === 'undefined') {
  					(max = 1), (min = 0);
  				} else if (typeof max === 'undefined') {
  					(max = min), (min = 0);
  				}
  				if (max > min) {
  					num = (num - min) % (max - min);
  					return num + (num < 0 ? max : min);
  				} else {
  					num = (num - max) % (min - max);
  					return num + (num <= 0 ? min : max);
  				}
  			};
  
  			math.clamp = function (num, min, max) {
  				if (num < min) {
  					return min;
  				} else if (num > max) {
  					return max;
  				} else {
  					return num;
  				}
  			};
  
  			math.random = function (min, max) {
  				if (typeof min === 'undefined') {
  					max = 1;
  					min = 0;
  				} else if (typeof max === 'undefined') {
  					max = min;
  					min = 0;
  				}
  				return min == max ? min : native.random() * (max - min) + min;
  			};
  
  			/***/
  		},
  		/* 2 */
  		/***/ function (module, exports, __webpack_require__) {
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			exports.debug = function () {
  				if (!_DEBUG) return;
  				console.log.apply(console, arguments);
  			};
  
  			exports.assert = function (statement, err, log) {
  				if (!_ASSERT) return;
  				if (statement) return;
  				log && console.log(log);
  				throw new Error(err);
  			};
  
  			/***/
  		},
  		/* 3 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Rot;
  
  			var common = __webpack_require__(2);
  			var Vec2 = __webpack_require__(0);
  			var Math = __webpack_require__(1);
  
  			// TODO merge with Transform
  
  			/**
               * Initialize from an angle in radians.
               */
  			function Rot (angle) {
  				if (!(this instanceof Rot)) {
  					return new Rot(angle);
  				}
  				if (typeof angle === 'number') {
  					this.setAngle(angle);
  				} else if (typeof angle === 'object') {
  					this.set(angle);
  				} else {
  					this.setIdentity();
  				}
  			}
  
  			Rot.neo = function (angle) {
  				var obj = Object.create(Rot.prototype);
  				obj.setAngle(angle);
  				return obj;
  			};
  
  			Rot.clone = function (rot) {
  				_ASSERT && Rot.assert(rot);
  				var obj = Object.create(Rot.prototype);
  				obj.s = rot.s;
  				obj.c = rot.c;
  				return obj;
  			};
  
  			Rot.identity = function () {
  				var obj = Object.create(Rot.prototype);
  				obj.s = 0.0;
  				obj.c = 1.0;
  				return obj;
  			};
  
  			Rot.isValid = function (o) {
  				return o && Math.isFinite(o.s) && Math.isFinite(o.c);
  			};
  
  			Rot.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!Rot.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid Rot!');
  				}
  			};
  
  			/**
               * Set to the identity rotation.
               */
  			Rot.prototype.setIdentity = function () {
  				this.s = 0.0;
  				this.c = 1.0;
  			};
  
  			Rot.prototype.set = function (angle) {
  				if (typeof angle === 'object') {
  					_ASSERT && Rot.assert(angle);
  					this.s = angle.s;
  					this.c = angle.c;
  				} else {
  					_ASSERT && Math.assert(angle);
  					// TODO_ERIN optimize
  					this.s = Math.sin(angle);
  					this.c = Math.cos(angle);
  				}
  			};
  
  			/**
               * Set using an angle in radians.
               */
  			Rot.prototype.setAngle = function (angle) {
  				_ASSERT && Math.assert(angle);
  				// TODO_ERIN optimize
  				this.s = Math.sin(angle);
  				this.c = Math.cos(angle);
  			};
  
  			/**
               * Get the angle in radians.
               */
  			Rot.prototype.getAngle = function () {
  				return Math.atan2(this.s, this.c);
  			};
  
  			/**
               * Get the x-axis.
               */
  			Rot.prototype.getXAxis = function () {
  				return Vec2.neo(this.c, this.s);
  			};
  
  			/**
               * Get the u-axis.
               */
  			Rot.prototype.getYAxis = function () {
  				return Vec2.neo(-this.s, this.c);
  			};
  
  			/**
               * Multiply two rotations: q * r
               *
               * @returns Rot
               *
               * Rotate a vector
               *
               * @returns Vec2
               */
  			Rot.mul = function (rot, m) {
  				_ASSERT && Rot.assert(rot);
  				if ('c' in m && 's' in m) {
  					_ASSERT && Rot.assert(m);
  					// [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
  					// [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
  					// s = qs * rc + qc * rs
  					// c = qc * rc - qs * rs
  					var qr = Rot.identity();
  					qr.s = rot.s * m.c + rot.c * m.s;
  					qr.c = rot.c * m.c - rot.s * m.s;
  					return qr;
  				} else if ('x' in m && 'y' in m) {
  					_ASSERT && Vec2.assert(m);
  					return Vec2.neo(rot.c * m.x - rot.s * m.y, rot.s * m.x + rot.c * m.y);
  				}
  			};
  
  			Rot.mulRot = function (rot, m) {
  				_ASSERT && Rot.assert(rot);
  				_ASSERT && Rot.assert(m);
  				// [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
  				// [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
  				// s = qs * rc + qc * rs
  				// c = qc * rc - qs * rs
  				var qr = Rot.identity();
  				qr.s = rot.s * m.c + rot.c * m.s;
  				qr.c = rot.c * m.c - rot.s * m.s;
  				return qr;
  			};
  
  			Rot.mulVec2 = function (rot, m) {
  				_ASSERT && Rot.assert(rot);
  				_ASSERT && Vec2.assert(m);
  				return Vec2.neo(rot.c * m.x - rot.s * m.y, rot.s * m.x + rot.c * m.y);
  			};
  
  			Rot.mulSub = function (rot, v, w) {
  				var x = rot.c * (v.x - w.x) - rot.s * (v.y - w.y);
  				var y = rot.s * (v.x - w.x) + rot.c * (v.y - w.y);
  				return Vec2.neo(x, y);
  			};
  
  			/**
               * Transpose multiply two rotations: qT * r
               *
               * @returns Rot
               *
               * Inverse rotate a vector
               *
               * @returns Vec2
               */
  			Rot.mulT = function (rot, m) {
  				if ('c' in m && 's' in m) {
  					_ASSERT && Rot.assert(m);
  					// [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
  					// [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
  					// s = qc * rs - qs * rc
  					// c = qc * rc + qs * rs
  					var qr = Rot.identity();
  					qr.s = rot.c * m.s - rot.s * m.c;
  					qr.c = rot.c * m.c + rot.s * m.s;
  					return qr;
  				} else if ('x' in m && 'y' in m) {
  					_ASSERT && Vec2.assert(m);
  					return Vec2.neo(rot.c * m.x + rot.s * m.y, -rot.s * m.x + rot.c * m.y);
  				}
  			};
  
  			Rot.mulTRot = function (rot, m) {
  				_ASSERT && Rot.assert(m);
  				// [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
  				// [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
  				// s = qc * rs - qs * rc
  				// c = qc * rc + qs * rs
  				var qr = Rot.identity();
  				qr.s = rot.c * m.s - rot.s * m.c;
  				qr.c = rot.c * m.c + rot.s * m.s;
  				return qr;
  			};
  
  			Rot.mulTVec2 = function (rot, m) {
  				_ASSERT && Vec2.assert(m);
  				return Vec2.neo(rot.c * m.x + rot.s * m.y, -rot.s * m.x + rot.c * m.y);
  			};
  
  			/***/
  		},
  		/* 4 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			// TODO merge with World options?
  
  			var Settings = exports;
  
  			/**
               * Tuning constants based on meters-kilograms-seconds (MKS) units.
               */
  
  			// Collision
  			/**
               * The maximum number of contact points between two convex shapes. Do not change
               * this value.
               */
  			Settings.maxManifoldPoints = 2;
  
  			/**
               * The maximum number of vertices on a convex polygon. You cannot increase this
               * too much because BlockAllocator has a maximum object size.
               */
  			Settings.maxPolygonVertices = 12;
  
  			/**
               * This is used to fatten AABBs in the dynamic tree. This allows proxies to move
               * by a small amount without triggering a tree adjustment. This is in meters.
               */
  			Settings.aabbExtension = 0.1;
  
  			/**
               * This is used to fatten AABBs in the dynamic tree. This is used to predict the
               * future position based on the current displacement. This is a dimensionless
               * multiplier.
               */
  			Settings.aabbMultiplier = 2.0;
  
  			/**
               * A small length used as a collision and constraint tolerance. Usually it is
               * chosen to be numerically significant, but visually insignificant.
               */
  			Settings.linearSlop = 0.005;
  			Settings.linearSlopSquared = Settings.linearSlop * Settings.linearSlop;
  
  			/**
               * A small angle used as a collision and constraint tolerance. Usually it is
               * chosen to be numerically significant, but visually insignificant.
               */
  			Settings.angularSlop = (2.0 / 180.0) * Math.PI;
  
  			/**
               * The radius of the polygon/edge shape skin. This should not be modified.
               * Making this smaller means polygons will have an insufficient buffer for
               * continuous collision. Making it larger may create artifacts for vertex
               * collision.
               */
  			Settings.polygonRadius = 2.0 * Settings.linearSlop;
  
  			/**
               * Maximum number of sub-steps per contact in continuous physics simulation.
               */
  			Settings.maxSubSteps = 8;
  
  			// Dynamics
  
  			/**
               * Maximum number of contacts to be handled to solve a TOI impact.
               */
  			Settings.maxTOIContacts = 32;
  
  			/**
               * Maximum iterations to solve a TOI.
               */
  			Settings.maxTOIIterations = 20;
  
  			/**
               * Maximum iterations to find Distance.
               */
  			Settings.maxDistnceIterations = 20;
  
  			/**
               * A velocity threshold for elastic collisions. Any collision with a relative
               * linear velocity below this threshold will be treated as inelastic.
               */
  			Settings.velocityThreshold = 1.0;
  
  			/**
               * The maximum linear position correction used when solving constraints. This
               * helps to prevent overshoot.
               */
  			Settings.maxLinearCorrection = 0.2;
  
  			/**
               * The maximum angular position correction used when solving constraints. This
               * helps to prevent overshoot.
               */
  			Settings.maxAngularCorrection = (8.0 / 180.0) * Math.PI;
  
  			/**
               * The maximum linear velocity of a body. This limit is very large and is used
               * to prevent numerical problems. You shouldn't need to adjust this.
               */
  			Settings.maxTranslation = 500.0;
  			Settings.maxTranslationSquared = Settings.maxTranslation * Settings.maxTranslation;
  
  			/**
               * The maximum angular velocity of a body. This limit is very large and is used
               * to prevent numerical problems. You shouldn't need to adjust this.
               */
  			Settings.maxRotation = 0.5 * Math.PI;
  			Settings.maxRotationSquared = Settings.maxRotation * Settings.maxRotation;
  
  			/**
               * This scale factor controls how fast overlap is resolved. Ideally this would
               * be 1 so that overlap is removed in one time step. However using values close
               * to 1 often lead to overshoot.
               */
  			Settings.baumgarte = 0.2;
  			Settings.toiBaugarte = 0.75;
  
  			// Sleep
  
  			/**
               * The time that a body must be still before it will go to sleep.
               */
  			Settings.timeToSleep = 0.5;
  
  			/**
               * A body cannot sleep if its linear velocity is above this tolerance.
               */
  			Settings.linearSleepTolerance = 0.01;
  
  			Settings.linearSleepToleranceSqr = Math.pow(Settings.linearSleepTolerance, 2);
  
  			/**
               * A body cannot sleep if its angular velocity is above this tolerance.
               */
  			Settings.angularSleepTolerance = (2.0 / 180.0) * Math.PI;
  
  			Settings.angularSleepToleranceSqr = Math.pow(Settings.angularSleepTolerance, 2);
  
  			/***/
  		},
  		/* 5 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Transform;
  
  			var common = __webpack_require__(2);
  			var Vec2 = __webpack_require__(0);
  			var Rot = __webpack_require__(3);
  
  			// TODO merge with Rot
  
  			/**
               * A transform contains translation and rotation. It is used to represent the
               * position and orientation of rigid frames. Initialize using a position vector
               * and a rotation.
               *
               * @prop {Vec2} position
               * @prop {Rot} rotation
               */
  			function Transform (position, rotation) {
  				if (!(this instanceof Transform)) {
  					return new Transform(position, rotation);
  				}
  				this.p = Vec2.zero();
  				this.q = Rot.identity();
  				if (typeof position !== 'undefined') {
  					this.p.set(position);
  				}
  				if (typeof rotation !== 'undefined') {
  					this.q.set(rotation);
  				}
  			}
  
  			Transform.clone = function (xf) {
  				var obj = Object.create(Transform.prototype);
  				obj.p = Vec2.clone(xf.p);
  				obj.q = Rot.clone(xf.q);
  				return obj;
  			};
  
  			Transform.neo = function (position, rotation) {
  				var obj = Object.create(Transform.prototype);
  				obj.p = Vec2.clone(position);
  				obj.q = Rot.clone(rotation);
  				return obj;
  			};
  
  			Transform.identity = function () {
  				var obj = Object.create(Transform.prototype);
  				obj.p = Vec2.zero();
  				obj.q = Rot.identity();
  				return obj;
  			};
  
  			/**
               * Set this to the identity transform.
               */
  			Transform.prototype.setIdentity = function () {
  				this.p.setZero();
  				this.q.setIdentity();
  			};
  
  			/**
               * Set this based on the position and angle.
               */
  			Transform.prototype.set = function (a, b) {
  				if (typeof b === 'undefined') {
  					this.p.set(a.p);
  					this.q.set(a.q);
  				} else {
  					this.p.set(a);
  					this.q.set(b);
  				}
  			};
  
  			Transform.isValid = function (o) {
  				return o && Vec2.isValid(o.p) && Rot.isValid(o.q);
  			};
  
  			Transform.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!Transform.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid Transform!');
  				}
  			};
  
  			/**
               * @param {Transform} a
               * @param {Vec2} b
               * @returns {Vec2}
               *
               * @param {Transform} a
               * @param {Transform} b
               * @returns {Transform}
               */
  			Transform.mul = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				if (Array.isArray(b)) {
  					var arr = [];
  					for (var i = 0; i < b.length; i++) {
  						arr[i] = Transform.mul(a, b[i]);
  					}
  					return arr;
  				} else if ('x' in b && 'y' in b) {
  					_ASSERT && Vec2.assert(b);
  					var x = a.q.c * b.x - a.q.s * b.y + a.p.x;
  					var y = a.q.s * b.x + a.q.c * b.y + a.p.y;
  					return Vec2.neo(x, y);
  				} else if ('p' in b && 'q' in b) {
  					_ASSERT && Transform.assert(b);
  					// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
  					// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
  					var xf = Transform.identity();
  					xf.q = Rot.mulRot(a.q, b.q);
  					xf.p = Vec2.add(Rot.mulVec2(a.q, b.p), a.p);
  					return xf;
  				}
  			};
  
  			/**
               * @deprecated Use mulFn instead.
               */
  			Transform.mulAll = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				var arr = [];
  				for (var i = 0; i < b.length; i++) {
  					arr[i] = Transform.mul(a, b[i]);
  				}
  				return arr;
  			};
  
  			/**
               * @experimental
               */
  			Transform.mulFn = function (a) {
  				_ASSERT && Transform.assert(a);
  				return function (b) {
  					return Transform.mul(a, b);
  				};
  			};
  
  			Transform.mulVec2 = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				_ASSERT && Vec2.assert(b);
  				var x = a.q.c * b.x - a.q.s * b.y + a.p.x;
  				var y = a.q.s * b.x + a.q.c * b.y + a.p.y;
  				return Vec2.neo(x, y);
  			};
  
  			Transform.mulXf = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				_ASSERT && Transform.assert(b);
  				// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
  				// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
  				var xf = Transform.identity();
  				xf.q = Rot.mulRot(a.q, b.q);
  				xf.p = Vec2.add(Rot.mulVec2(a.q, b.p), a.p);
  				return xf;
  			};
  
  			/**
               * @param {Transform} a
               * @param {Vec2} b
               * @returns {Vec2}
               *
               * @param {Transform} a
               * @param {Transform} b
               * @returns {Transform}
               */
  			Transform.mulT = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				if ('x' in b && 'y' in b) {
  					_ASSERT && Vec2.assert(b);
  					var px = b.x - a.p.x;
  					var py = b.y - a.p.y;
  					var x = a.q.c * px + a.q.s * py;
  					var y = -a.q.s * px + a.q.c * py;
  					return Vec2.neo(x, y);
  				} else if ('p' in b && 'q' in b) {
  					_ASSERT && Transform.assert(b);
  					// v2 = A.q' * (B.q * v1 + B.p - A.p)
  					// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
  					var xf = Transform.identity();
  					xf.q.set(Rot.mulTRot(a.q, b.q));
  					xf.p.set(Rot.mulTVec2(a.q, Vec2.sub(b.p, a.p)));
  					return xf;
  				}
  			};
  
  			Transform.mulTVec2 = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				_ASSERT && Vec2.assert(b);
  				var px = b.x - a.p.x;
  				var py = b.y - a.p.y;
  				var x = a.q.c * px + a.q.s * py;
  				var y = -a.q.s * px + a.q.c * py;
  				return Vec2.neo(x, y);
  			};
  
  			Transform.mulTXf = function (a, b) {
  				_ASSERT && Transform.assert(a);
  				_ASSERT && Transform.assert(b);
  				// v2 = A.q' * (B.q * v1 + B.p - A.p)
  				// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
  				var xf = Transform.identity();
  				xf.q.set(Rot.mulTRot(a.q, b.q));
  				xf.p.set(Rot.mulTVec2(a.q, Vec2.sub(b.p, a.p)));
  				return xf;
  			};
  
  			/***/
  		},
  		/* 6 */
  		/***/ function (module, exports) {
  			if (typeof Object.create == 'function') {
  				module.exports = function (proto, props) {
  					return Object.create.call(Object, proto, props);
  				};
  			} else {
  				module.exports = function (proto, props) {
  					if (props) throw Error('Second argument is not supported!');
  					if (typeof proto !== 'object' || proto === null) throw Error('Invalid prototype!');
  					noop.prototype = proto;
  					return new noop();
  				};
  				function noop () {}
  			}
  
  			/***/
  		},
  		/* 7 */
  		/***/ function (module, exports, __webpack_require__) {
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var propIsEnumerable = Object.prototype.propertyIsEnumerable;
  
  			module.exports = function (to, from) {
  				if (to === null || typeof to === 'undefined') {
  					to = {};
  				}
  
  				for (var key in from) {
  					if (from.hasOwnProperty(key) && typeof to[key] === 'undefined') {
  						to[key] = from[key];
  					}
  				}
  
  				if (typeof Object.getOwnPropertySymbols === 'function') {
  					var symbols = Object.getOwnPropertySymbols(from);
  					for (var i = 0; i < symbols.length; i++) {
  						var symbol = symbols[i];
  						if (from.propertyIsEnumerable(symbol) && typeof to[key] === 'undefined') {
  							to[symbol] = from[symbol];
  						}
  					}
  				}
  				return to;
  			};
  
  			/***/
  		},
  		/* 8 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Body;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  
  			var Vec2 = __webpack_require__(0);
  			var Rot = __webpack_require__(3);
  			var Math = __webpack_require__(1);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Fixture = __webpack_require__(32);
  			var Shape = __webpack_require__(16);
  
  			var staticBody = (Body.STATIC = 'static');
  			var kinematicBody = (Body.KINEMATIC = 'kinematic');
  			var dynamicBody = (Body.DYNAMIC = 'dynamic');
  
  			/**
               * @typedef {Object} BodyDef
               *
               * @prop type Body types are static, kinematic, or dynamic. Note: if a dynamic
               *       body would have zero mass, the mass is set to one.
               *
               * @prop position The world position of the body. Avoid creating bodies at the
               *       origin since this can lead to many overlapping shapes.
               *
               * @prop angle The world angle of the body in radians.
               *
               * @prop linearVelocity The linear velocity of the body's origin in world
               *       co-ordinates.
               *
               * @prop angularVelocity
               *
               * @prop linearDamping Linear damping is use to reduce the linear velocity. The
               *       damping parameter can be larger than 1.0 but the damping effect becomes
               *       sensitive to the time step when the damping parameter is large.
               *
               * @prop angularDamping Angular damping is use to reduce the angular velocity.
               *       The damping parameter can be larger than 1.0 but the damping effect
               *       becomes sensitive to the time step when the damping parameter is large.
               *
               * @prop fixedRotation Should this body be prevented from rotating? Useful for
               *       characters.
               *
               * @prop bullet Is this a fast moving body that should be prevented from
               *       tunneling through other moving bodies? Note that all bodies are
               *       prevented from tunneling through kinematic and static bodies. This
               *       setting is only considered on dynamic bodies. Warning: You should use
               *       this flag sparingly since it increases processing time.
               *
               * @prop active Does this body start out active?
               *
               * @prop awake Is this body initially awake or sleeping?
               *
               * @prop allowSleep Set this flag to false if this body should never fall
               *       asleep. Note that this increases CPU usage.
               */
  			var BodyDef = {
  				type: staticBody,
  				position: Vec2.zero(),
  				angle: 0.0,
  
  				linearVelocity: Vec2.zero(),
  				angularVelocity: 0.0,
  
  				linearDamping: 0.0,
  				angularDamping: 0.0,
  
  				fixedRotation: false,
  				bullet: false,
  				gravityScale: 1.0,
  
  				allowSleep: true,
  				awake: true,
  				active: true,
  
  				userData: null
  			};
  
  			/**
               * @class
               *
               * A rigid body composed of one or more fixtures.
               *
               * @param {World} world
               * @param {BodyDef} def
               */
  			function Body (world, def) {
  				def = options(def, BodyDef);
  
  				_ASSERT && common.assert(Vec2.isValid(def.position));
  				_ASSERT && common.assert(Vec2.isValid(def.linearVelocity));
  				_ASSERT && common.assert(Math.isFinite(def.angle));
  				_ASSERT && common.assert(Math.isFinite(def.angularVelocity));
  				_ASSERT && common.assert(Math.isFinite(def.angularDamping) && def.angularDamping >= 0.0);
  				_ASSERT && common.assert(Math.isFinite(def.linearDamping) && def.linearDamping >= 0.0);
  
  				this.m_world = world;
  
  				this.m_awakeFlag = def.awake;
  				this.m_autoSleepFlag = def.allowSleep;
  				this.m_bulletFlag = def.bullet;
  				this.m_fixedRotationFlag = def.fixedRotation;
  				this.m_activeFlag = def.active;
  
  				this.m_islandFlag = false;
  				this.m_toiFlag = false;
  
  				this.m_userData = def.userData;
  				this.m_type = def.type;
  
  				if (this.m_type == dynamicBody) {
  					this.m_mass = 1.0;
  					this.m_invMass = 1.0;
  				} else {
  					this.m_mass = 0.0;
  					this.m_invMass = 0.0;
  				}
  
  				// Rotational inertia about the center of mass.
  				this.m_I = 0.0;
  				this.m_invI = 0.0;
  
  				// the body origin transform
  				this.m_xf = Transform.identity();
  				this.m_xf.p = Vec2.clone(def.position);
  				this.m_xf.q.setAngle(def.angle);
  
  				// the swept motion for CCD
  				this.m_sweep = new Sweep();
  				this.m_sweep.setTransform(this.m_xf);
  
  				// position and velocity correction
  				this.c_velocity = new Velocity();
  				this.c_position = new Position();
  
  				this.m_force = Vec2.zero();
  				this.m_torque = 0.0;
  
  				this.m_linearVelocity = Vec2.clone(def.linearVelocity);
  				this.m_angularVelocity = def.angularVelocity;
  
  				this.m_linearDamping = def.linearDamping;
  				this.m_angularDamping = def.angularDamping;
  				this.m_gravityScale = def.gravityScale;
  
  				this.m_sleepTime = 0.0;
  
  				this.m_jointList = null;
  				this.m_contactList = null;
  				this.m_fixtureList = null;
  
  				this.m_prev = null;
  				this.m_next = null;
  
  				this.m_destroyed = false;
  			}
  
  			Body.prototype._serialize = function () {
  				var fixtures = [];
  				for (var f = this.m_fixtureList; f; f = f.m_next) {
  					fixtures.push(f);
  				}
  				return {
  					type: this.m_type,
  					position: this.m_xf.p,
  					angle: this.m_xf.q.getAngle(),
  					linearVelocity: this.m_linearVelocity,
  					angularVelocity: this.m_angularVelocity,
  					fixtures: fixtures
  				};
  			};
  
  			Body._deserialize = function (data, world, restore) {
  				var body = new Body(world, data);
  
  				data.fixtures.forEach(function (data) {
  					var fixture = restore(Fixture, data, body);
  					body._addFixture(fixture);
  				});
  
  				return body;
  			};
  
  			Body.prototype.isWorldLocked = function () {
  				return !!(this.m_world && this.m_world.isLocked());
  			};
  
  			Body.prototype.getWorld = function () {
  				return this.m_world;
  			};
  
  			Body.prototype.getNext = function () {
  				return this.m_next;
  			};
  
  			Body.prototype.setUserData = function (data) {
  				this.m_userData = data;
  			};
  
  			Body.prototype.getUserData = function () {
  				return this.m_userData;
  			};
  
  			Body.prototype.getFixtureList = function () {
  				return this.m_fixtureList;
  			};
  
  			Body.prototype.getJointList = function () {
  				return this.m_jointList;
  			};
  
  			/**
               * Warning: this list changes during the time step and you may miss some
               * collisions if you don't use ContactListener.
               */
  			Body.prototype.getContactList = function () {
  				return this.m_contactList;
  			};
  
  			Body.prototype.isStatic = function () {
  				return this.m_type == staticBody;
  			};
  
  			Body.prototype.isDynamic = function () {
  				return this.m_type == dynamicBody;
  			};
  
  			Body.prototype.isKinematic = function () {
  				return this.m_type == kinematicBody;
  			};
  
  			/**
               * This will alter the mass and velocity.
               */
  			Body.prototype.setStatic = function () {
  				this.setType(staticBody);
  				return this;
  			};
  
  			Body.prototype.setDynamic = function () {
  				this.setType(dynamicBody);
  				return this;
  			};
  
  			Body.prototype.setKinematic = function () {
  				this.setType(kinematicBody);
  				return this;
  			};
  
  			/**
               * @private
               */
  			Body.prototype.getType = function () {
  				return this.m_type;
  			};
  
  			/**
               *
               * @private
               */
  			Body.prototype.setType = function (type) {
  				_ASSERT && common.assert(type === staticBody || type === kinematicBody || type === dynamicBody);
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  
  				if (this.isWorldLocked() == true) {
  					return;
  				}
  
  				if (this.m_type == type) {
  					return;
  				}
  
  				this.m_type = type;
  
  				this.resetMassData();
  
  				if (this.m_type == staticBody) {
  					this.m_linearVelocity.setZero();
  					this.m_angularVelocity = 0.0;
  					this.m_sweep.forward();
  					this.synchronizeFixtures();
  				}
  
  				this.setAwake(true);
  
  				this.m_force.setZero();
  				this.m_torque = 0.0;
  
  				// Delete the attached contacts.
  				var ce = this.m_contactList;
  				while (ce) {
  					var ce0 = ce;
  					ce = ce.next;
  					this.m_world.destroyContact(ce0.contact);
  				}
  				this.m_contactList = null;
  
  				// Touch the proxies so that new contacts will be created (when appropriate)
  				var broadPhase = this.m_world.m_broadPhase;
  				for (var f = this.m_fixtureList; f; f = f.m_next) {
  					var proxyCount = f.m_proxyCount;
  					for (var i = 0; i < proxyCount; ++i) {
  						broadPhase.touchProxy(f.m_proxies[i].proxyId);
  					}
  				}
  			};
  
  			Body.prototype.isBullet = function () {
  				return this.m_bulletFlag;
  			};
  
  			/**
               * Should this body be treated like a bullet for continuous collision detection?
               */
  			Body.prototype.setBullet = function (flag) {
  				this.m_bulletFlag = !!flag;
  			};
  
  			Body.prototype.isSleepingAllowed = function () {
  				return this.m_autoSleepFlag;
  			};
  
  			Body.prototype.setSleepingAllowed = function (flag) {
  				this.m_autoSleepFlag = !!flag;
  				if (this.m_autoSleepFlag == false) {
  					this.setAwake(true);
  				}
  			};
  
  			Body.prototype.isAwake = function () {
  				return this.m_awakeFlag;
  			};
  
  			/**
               * Set the sleep state of the body. A sleeping body has very low CPU cost.
               *
               * @param flag Set to true to wake the body, false to put it to sleep.
               */
  			Body.prototype.setAwake = function (flag) {
  				if (flag) {
  					if (this.m_awakeFlag == false) {
  						this.m_awakeFlag = true;
  						this.m_sleepTime = 0.0;
  					}
  				} else {
  					this.m_awakeFlag = false;
  					this.m_sleepTime = 0.0;
  					this.m_linearVelocity.setZero();
  					this.m_angularVelocity = 0.0;
  					this.m_force.setZero();
  					this.m_torque = 0.0;
  				}
  			};
  
  			Body.prototype.isActive = function () {
  				return this.m_activeFlag;
  			};
  
  			/**
               * Set the active state of the body. An inactive body is not simulated and
               * cannot be collided with or woken up. If you pass a flag of true, all fixtures
               * will be added to the broad-phase. If you pass a flag of false, all fixtures
               * will be removed from the broad-phase and all contacts will be destroyed.
               * Fixtures and joints are otherwise unaffected.
               *
               * You may continue to create/destroy fixtures and joints on inactive bodies.
               * Fixtures on an inactive body are implicitly inactive and will not participate
               * in collisions, ray-casts, or queries. Joints connected to an inactive body
               * are implicitly inactive. An inactive body is still owned by a World object
               * and remains
               */
  			Body.prototype.setActive = function (flag) {
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  
  				if (flag == this.m_activeFlag) {
  					return;
  				}
  
  				this.m_activeFlag = !!flag;
  
  				if (this.m_activeFlag) {
  					// Create all proxies.
  					var broadPhase = this.m_world.m_broadPhase;
  					for (var f = this.m_fixtureList; f; f = f.m_next) {
  						f.createProxies(broadPhase, this.m_xf);
  					}
  					// Contacts are created the next time step.
  				} else {
  					// Destroy all proxies.
  					var broadPhase = this.m_world.m_broadPhase;
  					for (var f = this.m_fixtureList; f; f = f.m_next) {
  						f.destroyProxies(broadPhase);
  					}
  
  					// Destroy the attached contacts.
  					var ce = this.m_contactList;
  					while (ce) {
  						var ce0 = ce;
  						ce = ce.next;
  						this.m_world.destroyContact(ce0.contact);
  					}
  					this.m_contactList = null;
  				}
  			};
  
  			Body.prototype.isFixedRotation = function () {
  				return this.m_fixedRotationFlag;
  			};
  
  			/**
               * Set this body to have fixed rotation. This causes the mass to be reset.
               */
  			Body.prototype.setFixedRotation = function (flag) {
  				if (this.m_fixedRotationFlag == flag) {
  					return;
  				}
  
  				this.m_fixedRotationFlag = !!flag;
  
  				this.m_angularVelocity = 0.0;
  
  				this.resetMassData();
  			};
  
  			/**
               * Get the world transform for the body's origin.
               */
  			Body.prototype.getTransform = function () {
  				return this.m_xf;
  			};
  
  			/**
               * Set the position of the body's origin and rotation. Manipulating a body's
               * transform may cause non-physical behavior. Note: contacts are updated on the
               * next call to World.step.
               *
               * @param position The world position of the body's local origin.
               * @param angle The world rotation in radians.
               */
  			Body.prototype.setTransform = function (position, angle) {
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  				if (this.isWorldLocked() == true) {
  					return;
  				}
  
  				this.m_xf.set(position, angle);
  				this.m_sweep.setTransform(this.m_xf);
  
  				var broadPhase = this.m_world.m_broadPhase;
  				for (var f = this.m_fixtureList; f; f = f.m_next) {
  					f.synchronize(broadPhase, this.m_xf, this.m_xf);
  				}
  			};
  
  			Body.prototype.synchronizeTransform = function () {
  				this.m_sweep.getTransform(this.m_xf, 1);
  			};
  
  			/**
               * Update fixtures in broad-phase.
               */
  			Body.prototype.synchronizeFixtures = function () {
  				var xf = Transform.identity();
  
  				this.m_sweep.getTransform(xf, 0);
  
  				var broadPhase = this.m_world.m_broadPhase;
  				for (var f = this.m_fixtureList; f; f = f.m_next) {
  					f.synchronize(broadPhase, xf, this.m_xf);
  				}
  			};
  
  			/**
               * Used in TOI.
               */
  			Body.prototype.advance = function (alpha) {
  				// Advance to the new safe time. This doesn't sync the broad-phase.
  				this.m_sweep.advance(alpha);
  				this.m_sweep.c.set(this.m_sweep.c0);
  				this.m_sweep.a = this.m_sweep.a0;
  				this.m_sweep.getTransform(this.m_xf, 1);
  			};
  
  			/**
               * Get the world position for the body's origin.
               */
  			Body.prototype.getPosition = function () {
  				return this.m_xf.p;
  			};
  
  			Body.prototype.setPosition = function (p) {
  				this.setTransform(p, this.m_sweep.a);
  			};
  
  			/**
               * Get the current world rotation angle in radians.
               */
  			Body.prototype.getAngle = function () {
  				return this.m_sweep.a;
  			};
  
  			Body.prototype.setAngle = function (angle) {
  				this.setTransform(this.m_xf.p, angle);
  			};
  
  			/**
               * Get the world position of the center of mass.
               */
  			Body.prototype.getWorldCenter = function () {
  				return this.m_sweep.c;
  			};
  
  			/**
               * Get the local position of the center of mass.
               */
  			Body.prototype.getLocalCenter = function () {
  				return this.m_sweep.localCenter;
  			};
  
  			/**
               * Get the linear velocity of the center of mass.
               *
               * @return the linear velocity of the center of mass.
               */
  			Body.prototype.getLinearVelocity = function () {
  				return this.m_linearVelocity;
  			};
  
  			/**
               * Get the world linear velocity of a world point attached to this body.
               *
               * @param worldPoint A point in world coordinates.
               */
  			Body.prototype.getLinearVelocityFromWorldPoint = function (worldPoint) {
  				var localCenter = Vec2.sub(worldPoint, this.m_sweep.c);
  				return Vec2.add(this.m_linearVelocity, Vec2.cross(this.m_angularVelocity, localCenter));
  			};
  
  			/**
               * Get the world velocity of a local point.
               *
               * @param localPoint A point in local coordinates.
               */
  			Body.prototype.getLinearVelocityFromLocalPoint = function (localPoint) {
  				return this.getLinearVelocityFromWorldPoint(this.getWorldPoint(localPoint));
  			};
  
  			/**
               * Set the linear velocity of the center of mass.
               *
               * @param v The new linear velocity of the center of mass.
               */
  			Body.prototype.setLinearVelocity = function (v) {
  				if (this.m_type == staticBody) {
  					return;
  				}
  				if (Vec2.dot(v, v) > 0.0) {
  					this.setAwake(true);
  				}
  				this.m_linearVelocity.set(v);
  			};
  
  			/**
               * Get the angular velocity.
               *
               * @returns the angular velocity in radians/second.
               */
  			Body.prototype.getAngularVelocity = function () {
  				return this.m_angularVelocity;
  			};
  
  			/**
               * Set the angular velocity.
               *
               * @param omega The new angular velocity in radians/second.
               */
  			Body.prototype.setAngularVelocity = function (w) {
  				if (this.m_type == staticBody) {
  					return;
  				}
  				if (w * w > 0.0) {
  					this.setAwake(true);
  				}
  				this.m_angularVelocity = w;
  			};
  
  			Body.prototype.getLinearDamping = function () {
  				return this.m_linearDamping;
  			};
  
  			Body.prototype.setLinearDamping = function (linearDamping) {
  				this.m_linearDamping = linearDamping;
  			};
  
  			Body.prototype.getAngularDamping = function () {
  				return this.m_angularDamping;
  			};
  
  			Body.prototype.setAngularDamping = function (angularDamping) {
  				this.m_angularDamping = angularDamping;
  			};
  
  			Body.prototype.getGravityScale = function () {
  				return this.m_gravityScale;
  			};
  
  			/**
               * Scale the gravity applied to this body.
               */
  			Body.prototype.setGravityScale = function (scale) {
  				this.m_gravityScale = scale;
  			};
  
  			/**
               * Get the total mass of the body.
               *
               * @returns The mass, usually in kilograms (kg).
               */
  			Body.prototype.getMass = function () {
  				return this.m_mass;
  			};
  
  			/**
               * Get the rotational inertia of the body about the local origin.
               *
               * @return the rotational inertia, usually in kg-m^2.
               */
  			Body.prototype.getInertia = function () {
  				return this.m_I + this.m_mass * Vec2.dot(this.m_sweep.localCenter, this.m_sweep.localCenter);
  			};
  
  			/**
               * @typedef {Object} MassData This holds the mass data computed for a shape.
               *
               * @prop mass The mass of the shape, usually in kilograms.
               * @prop center The position of the shape's centroid relative to the shape's
               *       origin.
               * @prop I The rotational inertia of the shape about the local origin.
               */
  			function MassData () {
  				this.mass = 0;
  				this.center = Vec2.zero();
  				this.I = 0;
  			}
  
  			/**
               * Copy the mass data of the body to data.
               */
  			Body.prototype.getMassData = function (data) {
  				data.mass = this.m_mass;
  				data.I = this.getInertia();
  				data.center.set(this.m_sweep.localCenter);
  			};
  
  			/**
               * This resets the mass properties to the sum of the mass properties of the
               * fixtures. This normally does not need to be called unless you called
               * SetMassData to override the mass and you later want to reset the mass.
               */
  			Body.prototype.resetMassData = function () {
  				// Compute mass data from shapes. Each shape has its own density.
  				this.m_mass = 0.0;
  				this.m_invMass = 0.0;
  				this.m_I = 0.0;
  				this.m_invI = 0.0;
  				this.m_sweep.localCenter.setZero();
  
  				// Static and kinematic bodies have zero mass.
  				if (this.isStatic() || this.isKinematic()) {
  					this.m_sweep.c0.set(this.m_xf.p);
  					this.m_sweep.c.set(this.m_xf.p);
  					this.m_sweep.a0 = this.m_sweep.a;
  					return;
  				}
  
  				_ASSERT && common.assert(this.isDynamic());
  
  				// Accumulate mass over all fixtures.
  				var localCenter = Vec2.zero();
  				for (var f = this.m_fixtureList; f; f = f.m_next) {
  					if (f.m_density == 0.0) {
  						continue;
  					}
  
  					var massData = new MassData();
  					f.getMassData(massData);
  					this.m_mass += massData.mass;
  					localCenter.addMul(massData.mass, massData.center);
  					this.m_I += massData.I;
  				}
  
  				// Compute center of mass.
  				if (this.m_mass > 0.0) {
  					this.m_invMass = 1.0 / this.m_mass;
  					localCenter.mul(this.m_invMass);
  				} else {
  					// Force all dynamic bodies to have a positive mass.
  					this.m_mass = 1.0;
  					this.m_invMass = 1.0;
  				}
  
  				if (this.m_I > 0.0 && this.m_fixedRotationFlag == false) {
  					// Center the inertia about the center of mass.
  					this.m_I -= this.m_mass * Vec2.dot(localCenter, localCenter);
  					_ASSERT && common.assert(this.m_I > 0.0);
  					this.m_invI = 1.0 / this.m_I;
  				} else {
  					this.m_I = 0.0;
  					this.m_invI = 0.0;
  				}
  
  				// Move center of mass.
  				var oldCenter = Vec2.clone(this.m_sweep.c);
  				this.m_sweep.setLocalCenter(localCenter, this.m_xf);
  
  				// Update center of mass velocity.
  				this.m_linearVelocity.add(Vec2.cross(this.m_angularVelocity, Vec2.sub(this.m_sweep.c, oldCenter)));
  			};
  
  			/**
               * Set the mass properties to override the mass properties of the fixtures. Note
               * that this changes the center of mass position. Note that creating or
               * destroying fixtures can also alter the mass. This function has no effect if
               * the body isn't dynamic.
               *
               * @param massData The mass properties.
               */
  			Body.prototype.setMassData = function (massData) {
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  				if (this.isWorldLocked() == true) {
  					return;
  				}
  
  				if (this.m_type != dynamicBody) {
  					return;
  				}
  
  				this.m_invMass = 0.0;
  				this.m_I = 0.0;
  				this.m_invI = 0.0;
  
  				this.m_mass = massData.mass;
  				if (this.m_mass <= 0.0) {
  					this.m_mass = 1.0;
  				}
  
  				this.m_invMass = 1.0 / this.m_mass;
  
  				if (massData.I > 0.0 && this.m_fixedRotationFlag == false) {
  					this.m_I = massData.I - this.m_mass * Vec2.dot(massData.center, massData.center);
  					_ASSERT && common.assert(this.m_I > 0.0);
  					this.m_invI = 1.0 / this.m_I;
  				}
  
  				// Move center of mass.
  				var oldCenter = Vec2.clone(this.m_sweep.c);
  				this.m_sweep.setLocalCenter(massData.center, this.m_xf);
  
  				// Update center of mass velocity.
  				this.m_linearVelocity.add(Vec2.cross(this.m_angularVelocity, Vec2.sub(this.m_sweep.c, oldCenter)));
  			};
  
  			/**
               * Apply a force at a world point. If the force is not applied at the center of
               * mass, it will generate a torque and affect the angular velocity. This wakes
               * up the body.
               *
               * @param force The world force vector, usually in Newtons (N).
               * @param point The world position of the point of application.
               * @param wake Also wake up the body
               */
  			Body.prototype.applyForce = function (force, point, wake) {
  				if (this.m_type != dynamicBody) {
  					return;
  				}
  				if (wake && this.m_awakeFlag == false) {
  					this.setAwake(true);
  				}
  				// Don't accumulate a force if the body is sleeping.
  				if (this.m_awakeFlag) {
  					this.m_force.add(force);
  					this.m_torque += Vec2.cross(Vec2.sub(point, this.m_sweep.c), force);
  				}
  			};
  
  			/**
               * Apply a force to the center of mass. This wakes up the body.
               *
               * @param force The world force vector, usually in Newtons (N).
               * @param wake Also wake up the body
               */
  			Body.prototype.applyForceToCenter = function (force, wake) {
  				if (this.m_type != dynamicBody) {
  					return;
  				}
  				if (wake && this.m_awakeFlag == false) {
  					this.setAwake(true);
  				}
  				// Don't accumulate a force if the body is sleeping
  				if (this.m_awakeFlag) {
  					this.m_force.add(force);
  				}
  			};
  
  			/**
               * Apply a torque. This affects the angular velocity without affecting the
               * linear velocity of the center of mass. This wakes up the body.
               *
               * @param torque About the z-axis (out of the screen), usually in N-m.
               * @param wake Also wake up the body
               */
  			Body.prototype.applyTorque = function (torque, wake) {
  				if (this.m_type != dynamicBody) {
  					return;
  				}
  				if (wake && this.m_awakeFlag == false) {
  					this.setAwake(true);
  				}
  				// Don't accumulate a force if the body is sleeping
  				if (this.m_awakeFlag) {
  					this.m_torque += torque;
  				}
  			};
  
  			/**
               * Apply an impulse at a point. This immediately modifies the velocity. It also
               * modifies the angular velocity if the point of application is not at the
               * center of mass. This wakes up the body.
               *
               * @param impulse The world impulse vector, usually in N-seconds or kg-m/s.
               * @param point The world position of the point of application.
               * @param wake Also wake up the body
               */
  			Body.prototype.applyLinearImpulse = function (impulse, point, wake) {
  				if (this.m_type != dynamicBody) {
  					return;
  				}
  				if (wake && this.m_awakeFlag == false) {
  					this.setAwake(true);
  				}
  
  				// Don't accumulate velocity if the body is sleeping
  				if (this.m_awakeFlag) {
  					this.m_linearVelocity.addMul(this.m_invMass, impulse);
  					this.m_angularVelocity += this.m_invI * Vec2.cross(Vec2.sub(point, this.m_sweep.c), impulse);
  				}
  			};
  
  			/**
               * Apply an angular impulse.
               *
               * @param impulse The angular impulse in units of kg*m*m/s
               * @param wake Also wake up the body
               */
  			Body.prototype.applyAngularImpulse = function (impulse, wake) {
  				if (this.m_type != dynamicBody) {
  					return;
  				}
  
  				if (wake && this.m_awakeFlag == false) {
  					this.setAwake(true);
  				}
  				// Don't accumulate velocity if the body is sleeping
  				if (this.m_awakeFlag) {
  					this.m_angularVelocity += this.m_invI * impulse;
  				}
  			};
  
  			/**
               * This is used to prevent connected bodies (by joints) from colliding,
               * depending on the joint's collideConnected flag.
               */
  			Body.prototype.shouldCollide = function (that) {
  				// At least one body should be dynamic.
  				if (this.m_type != dynamicBody && that.m_type != dynamicBody) {
  					return false;
  				}
  				// Does a joint prevent collision?
  				for (var jn = this.m_jointList; jn; jn = jn.next) {
  					if (jn.other == that) {
  						if (jn.joint.m_collideConnected == false) {
  							return false;
  						}
  					}
  				}
  				return true;
  			};
  
  			/**
               * @internal Used for deserialize.
               */
  			Body.prototype._addFixture = function (fixture) {
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  
  				if (this.isWorldLocked() == true) {
  					return null;
  				}
  
  				if (this.m_activeFlag) {
  					var broadPhase = this.m_world.m_broadPhase;
  					fixture.createProxies(broadPhase, this.m_xf);
  				}
  
  				fixture.m_next = this.m_fixtureList;
  				this.m_fixtureList = fixture;
  
  				// Adjust mass properties if needed.
  				if (fixture.m_density > 0.0) {
  					this.resetMassData();
  				}
  
  				// Let the world know we have a new fixture. This will cause new contacts
  				// to be created at the beginning of the next time step.
  				this.m_world.m_newFixture = true;
  
  				return fixture;
  			};
  
  			/**
   * Creates a fixture and attach it to this body.
   *
   * If the density is non-zero, this function automatically updates the mass of
   * the body.
   *
   * Contacts are not created until the next time step.
   *
   * Warning: This function is locked during callbacks.
  
   * @param {Shape|FixtureDef} shape Shape or fixture definition.
   * @param {FixtureDef|number} fixdef Fixture definition or just density.
   */
  			Body.prototype.createFixture = function (shape, fixdef) {
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  
  				if (this.isWorldLocked() == true) {
  					return null;
  				}
  
  				var fixture = new Fixture(this, shape, fixdef);
  				this._addFixture(fixture);
  				return fixture;
  			};
  
  			/**
               * Destroy a fixture. This removes the fixture from the broad-phase and destroys
               * all contacts associated with this fixture. This will automatically adjust the
               * mass of the body if the body is dynamic and the fixture has positive density.
               * All fixtures attached to a body are implicitly destroyed when the body is
               * destroyed.
               *
               * Warning: This function is locked during callbacks.
               *
               * @param fixture The fixture to be removed.
               */
  			Body.prototype.destroyFixture = function (fixture) {
  				_ASSERT && common.assert(this.isWorldLocked() == false);
  
  				if (this.isWorldLocked() == true) {
  					return;
  				}
  
  				_ASSERT && common.assert(fixture.m_body == this);
  
  				// Remove the fixture from this body's singly linked list.
  				var found = false;
  				if (this.m_fixtureList === fixture) {
  					this.m_fixtureList = fixture.m_next;
  					found = true;
  				} else {
  					var node = this.m_fixtureList;
  					while (node != null) {
  						if (node.m_next === fixture) {
  							node.m_next = fixture.m_next;
  							found = true;
  							break;
  						}
  						node = node.m_next;
  					}
  				}
  
  				// You tried to remove a shape that is not attached to this body.
  				_ASSERT && common.assert(found);
  
  				// Destroy any contacts associated with the fixture.
  				var edge = this.m_contactList;
  				while (edge) {
  					var c = edge.contact;
  					edge = edge.next;
  
  					var fixtureA = c.getFixtureA();
  					var fixtureB = c.getFixtureB();
  
  					if (fixture == fixtureA || fixture == fixtureB) {
  						// This destroys the contact and removes it from
  						// this body's contact list.
  						this.m_world.destroyContact(c);
  					}
  				}
  
  				if (this.m_activeFlag) {
  					var broadPhase = this.m_world.m_broadPhase;
  					fixture.destroyProxies(broadPhase);
  				}
  
  				fixture.m_body = null;
  				fixture.m_next = null;
  
  				this.m_world.publish('remove-fixture', fixture);
  
  				// Reset the mass data.
  				this.resetMassData();
  			};
  
  			/**
               * Get the corresponding world point of a local point.
               */
  			Body.prototype.getWorldPoint = function (localPoint) {
  				return Transform.mulVec2(this.m_xf, localPoint);
  			};
  
  			/**
               * Get the corresponding world vector of a local vector.
               */
  			Body.prototype.getWorldVector = function (localVector) {
  				return Rot.mulVec2(this.m_xf.q, localVector);
  			};
  
  			/**
               * Gets the corresponding local point of a world point.
               */
  			Body.prototype.getLocalPoint = function (worldPoint) {
  				return Transform.mulTVec2(this.m_xf, worldPoint);
  			};
  
  			/**
               *
               * Gets the corresponding local vector of a world vector.
               */
  			Body.prototype.getLocalVector = function (worldVector) {
  				return Rot.mulTVec2(this.m_xf.q, worldVector);
  			};
  
  			/***/
  		},
  		/* 9 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Sweep;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Rot = __webpack_require__(3);
  			var Transform = __webpack_require__(5);
  
  			/**
               * This describes the motion of a body/shape for TOI computation. Shapes are
               * defined with respect to the body origin, which may not coincide with the
               * center of mass. However, to support dynamics we must interpolate the center
               * of mass position.
               *
               * @prop {Vec2} localCenter Local center of mass position
               * @prop {Vec2} c World center position
               * @prop {float} a World angle
               * @prop {float} alpha0 Fraction of the current time step in the range [0,1], c0
               *       and a0 are c and a at alpha0.
               */
  			function Sweep (c, a) {
  				_ASSERT && common.assert(typeof c === 'undefined');
  				_ASSERT && common.assert(typeof a === 'undefined');
  				this.localCenter = Vec2.zero();
  				this.c = Vec2.zero();
  				this.a = 0;
  				this.alpha0 = 0;
  				this.c0 = Vec2.zero();
  				this.a0 = 0;
  			}
  
  			Sweep.prototype.setTransform = function (xf) {
  				var c = Transform.mulVec2(xf, this.localCenter);
  				this.c.set(c);
  				this.c0.set(c);
  
  				this.a = xf.q.getAngle();
  				this.a0 = xf.q.getAngle();
  			};
  
  			Sweep.prototype.setLocalCenter = function (localCenter, xf) {
  				this.localCenter.set(localCenter);
  
  				var c = Transform.mulVec2(xf, this.localCenter);
  				this.c.set(c);
  				this.c0.set(c);
  			};
  
  			/**
               * Get the interpolated transform at a specific time.
               *
               * @param xf
               * @param beta A factor in [0,1], where 0 indicates alpha0
               */
  			Sweep.prototype.getTransform = function (xf, beta) {
  				beta = typeof beta === 'undefined' ? 0 : beta;
  				xf.q.setAngle((1.0 - beta) * this.a0 + beta * this.a);
  				xf.p.setCombine(1.0 - beta, this.c0, beta, this.c);
  
  				// shift to origin
  				xf.p.sub(Rot.mulVec2(xf.q, this.localCenter));
  			};
  
  			/**
               * Advance the sweep forward, yielding a new initial state.
               *
               * @param {float} alpha The new initial time
               */
  			Sweep.prototype.advance = function (alpha) {
  				_ASSERT && common.assert(this.alpha0 < 1.0);
  				var beta = (alpha - this.alpha0) / (1.0 - this.alpha0);
  				this.c0.setCombine(beta, this.c, 1 - beta, this.c0);
  				this.a0 = beta * this.a + (1 - beta) * this.a0;
  				this.alpha0 = alpha;
  			};
  
  			Sweep.prototype.forward = function () {
  				this.a0 = this.a;
  				this.c0.set(this.c);
  			};
  
  			/**
               * normalize the angles in radians to be between -pi and pi.
               */
  			Sweep.prototype.normalize = function () {
  				var a0 = Math.mod(this.a0, -Math.PI, +Math.PI);
  				this.a -= this.a0 - a0;
  				this.a0 = a0;
  			};
  
  			Sweep.prototype.clone = function () {
  				var clone = new Sweep();
  				clone.localCenter.set(this.localCenter);
  				clone.alpha0 = this.alpha0;
  				clone.a0 = this.a0;
  				clone.a = this.a;
  				clone.c0.set(this.c0);
  				clone.c.set(this.c);
  				return clone;
  			};
  
  			Sweep.prototype.set = function (that) {
  				this.localCenter.set(that.localCenter);
  				this.alpha0 = that.alpha0;
  				this.a0 = that.a0;
  				this.a = that.a;
  				this.c0.set(that.c0);
  				this.c.set(that.c);
  			};
  
  			/***/
  		},
  		/* 10 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Mat22;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  
  			/**
               * A 2-by-2 matrix. Stored in column-major order.
               */
  			function Mat22 (a, b, c, d) {
  				if (typeof a === 'object' && a !== null) {
  					this.ex = Vec2.clone(a);
  					this.ey = Vec2.clone(b);
  				} else if (typeof a === 'number') {
  					this.ex = Vec2.neo(a, c);
  					this.ey = Vec2.neo(b, d);
  				} else {
  					this.ex = Vec2.zero();
  					this.ey = Vec2.zero();
  				}
  			}
  
  			Mat22.prototype.toString = function () {
  				return JSON.stringify(this);
  			};
  
  			Mat22.isValid = function (o) {
  				return o && Vec2.isValid(o.ex) && Vec2.isValid(o.ey);
  			};
  
  			Mat22.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!Mat22.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid Mat22!');
  				}
  			};
  
  			Mat22.prototype.set = function (a, b, c, d) {
  				if (typeof a === 'number' && typeof b === 'number' && typeof c === 'number' && typeof d === 'number') {
  					this.ex.set(a, c);
  					this.ey.set(b, d);
  				} else if (typeof a === 'object' && typeof b === 'object') {
  					this.ex.set(a);
  					this.ey.set(b);
  				} else if (typeof a === 'object') {
  					_ASSERT && Mat22.assert(a);
  					this.ex.set(a.ex);
  					this.ey.set(a.ey);
  				} else {
  					_ASSERT && common.assert(false);
  				}
  			};
  
  			Mat22.prototype.setIdentity = function () {
  				this.ex.x = 1.0;
  				this.ey.x = 0.0;
  				this.ex.y = 0.0;
  				this.ey.y = 1.0;
  			};
  
  			Mat22.prototype.setZero = function () {
  				this.ex.x = 0.0;
  				this.ey.x = 0.0;
  				this.ex.y = 0.0;
  				this.ey.y = 0.0;
  			};
  
  			Mat22.prototype.getInverse = function () {
  				var a = this.ex.x;
  				var b = this.ey.x;
  				var c = this.ex.y;
  				var d = this.ey.y;
  				var det = a * d - b * c;
  				if (det != 0.0) {
  					det = 1.0 / det;
  				}
  				var imx = new Mat22();
  				imx.ex.x = det * d;
  				imx.ey.x = -det * b;
  				imx.ex.y = -det * c;
  				imx.ey.y = det * a;
  				return imx;
  			};
  
  			/**
               * Solve A * x = b, where b is a column vector. This is more efficient than
               * computing the inverse in one-shot cases.
               */
  			Mat22.prototype.solve = function (v) {
  				_ASSERT && Vec2.assert(v);
  				var a = this.ex.x;
  				var b = this.ey.x;
  				var c = this.ex.y;
  				var d = this.ey.y;
  				var det = a * d - b * c;
  				if (det != 0.0) {
  					det = 1.0 / det;
  				}
  				var w = Vec2.zero();
  				w.x = det * (d * v.x - b * v.y);
  				w.y = det * (a * v.y - c * v.x);
  				return w;
  			};
  
  			/**
               * Multiply a matrix times a vector. If a rotation matrix is provided, then this
               * transforms the vector from one frame to another.
               */
  			Mat22.mul = function (mx, v) {
  				if (v && 'x' in v && 'y' in v) {
  					_ASSERT && Vec2.assert(v);
  					var x = mx.ex.x * v.x + mx.ey.x * v.y;
  					var y = mx.ex.y * v.x + mx.ey.y * v.y;
  					return Vec2.neo(x, y);
  				} else if (v && 'ex' in v && 'ey' in v) {
  					// Mat22
  					_ASSERT && Mat22.assert(v);
  					// return new Mat22(Vec2.mul(mx, v.ex), Vec2.mul(mx, v.ey));
  					var a = mx.ex.x * v.ex.x + mx.ey.x * v.ex.y;
  					var b = mx.ex.x * v.ey.x + mx.ey.x * v.ey.y;
  					var c = mx.ex.y * v.ex.x + mx.ey.y * v.ex.y;
  					var d = mx.ex.y * v.ey.x + mx.ey.y * v.ey.y;
  					return new Mat22(a, b, c, d);
  				}
  
  				_ASSERT && common.assert(false);
  			};
  
  			Mat22.mulVec2 = function (mx, v) {
  				_ASSERT && Vec2.assert(v);
  				var x = mx.ex.x * v.x + mx.ey.x * v.y;
  				var y = mx.ex.y * v.x + mx.ey.y * v.y;
  				return Vec2.neo(x, y);
  			};
  
  			Mat22.mulMat22 = function (mx, v) {
  				_ASSERT && Mat22.assert(v);
  				// return new Mat22(Vec2.mul(mx, v.ex), Vec2.mul(mx, v.ey));
  				var a = mx.ex.x * v.ex.x + mx.ey.x * v.ex.y;
  				var b = mx.ex.x * v.ey.x + mx.ey.x * v.ey.y;
  				var c = mx.ex.y * v.ex.x + mx.ey.y * v.ex.y;
  				var d = mx.ex.y * v.ey.x + mx.ey.y * v.ey.y;
  				return new Mat22(a, b, c, d);
  				_ASSERT && common.assert(false);
  			};
  
  			/**
               * Multiply a matrix transpose times a vector. If a rotation matrix is provided,
               * then this transforms the vector from one frame to another (inverse
               * transform).
               */
  			Mat22.mulT = function (mx, v) {
  				if (v && 'x' in v && 'y' in v) {
  					// Vec2
  					_ASSERT && Vec2.assert(v);
  					return Vec2.neo(Vec2.dot(v, mx.ex), Vec2.dot(v, mx.ey));
  				} else if (v && 'ex' in v && 'ey' in v) {
  					// Mat22
  					_ASSERT && Mat22.assert(v);
  					var c1 = Vec2.neo(Vec2.dot(mx.ex, v.ex), Vec2.dot(mx.ey, v.ex));
  					var c2 = Vec2.neo(Vec2.dot(mx.ex, v.ey), Vec2.dot(mx.ey, v.ey));
  					return new Mat22(c1, c2);
  				}
  
  				_ASSERT && common.assert(false);
  			};
  
  			Mat22.mulTVec2 = function (mx, v) {
  				_ASSERT && Mat22.assert(mx);
  				_ASSERT && Vec2.assert(v);
  				return Vec2.neo(Vec2.dot(v, mx.ex), Vec2.dot(v, mx.ey));
  			};
  
  			Mat22.mulTMat22 = function (mx, v) {
  				_ASSERT && Mat22.assert(mx);
  				_ASSERT && Mat22.assert(v);
  				var c1 = Vec2.neo(Vec2.dot(mx.ex, v.ex), Vec2.dot(mx.ey, v.ex));
  				var c2 = Vec2.neo(Vec2.dot(mx.ex, v.ey), Vec2.dot(mx.ey, v.ey));
  				return new Mat22(c1, c2);
  			};
  
  			Mat22.abs = function (mx) {
  				_ASSERT && Mat22.assert(mx);
  				return new Mat22(Vec2.abs(mx.ex), Vec2.abs(mx.ey));
  			};
  
  			Mat22.add = function (mx1, mx2) {
  				_ASSERT && Mat22.assert(mx1);
  				_ASSERT && Mat22.assert(mx2);
  				return new Mat22(Vec2.add(mx1.ex, mx2.ex), Vec2.add(mx1.ey, mx2.ey));
  			};
  
  			/***/
  		},
  		/* 11 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Vec3;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  
  			function Vec3 (x, y, z) {
  				if (!(this instanceof Vec3)) {
  					return new Vec3(x, y, z);
  				}
  				if (typeof x === 'undefined') {
  					(this.x = 0), (this.y = 0), (this.z = 0);
  				} else if (typeof x === 'object') {
  					(this.x = x.x), (this.y = x.y), (this.z = x.z);
  				} else {
  					(this.x = x), (this.y = y), (this.z = z);
  				}
  				_ASSERT && Vec3.assert(this);
  			}
  
  			Vec3.prototype._serialize = function () {
  				return {
  					x: this.x,
  					y: this.y,
  					z: this.z
  				};
  			};
  
  			Vec3._deserialize = function (data) {
  				var obj = Object.create(Vec3.prototype);
  				obj.x = data.x;
  				obj.y = data.y;
  				obj.z = data.z;
  				return obj;
  			};
  
  			Vec3.neo = function (x, y, z) {
  				var obj = Object.create(Vec3.prototype);
  				obj.x = x;
  				obj.y = y;
  				obj.z = z;
  				return obj;
  			};
  
  			Vec3.clone = function (v) {
  				_ASSERT && Vec3.assert(v);
  				return Vec3.neo(v.x, v.y, v.z);
  			};
  
  			Vec3.prototype.toString = function () {
  				return JSON.stringify(this);
  			};
  
  			/**
               * Does this vector contain finite coordinates?
               */
  			Vec3.isValid = function (v) {
  				return v && Math.isFinite(v.x) && Math.isFinite(v.y) && Math.isFinite(v.z);
  			};
  
  			Vec3.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!Vec3.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid Vec3!');
  				}
  			};
  
  			Vec3.prototype.setZero = function () {
  				this.x = 0.0;
  				this.y = 0.0;
  				this.z = 0.0;
  				return this;
  			};
  
  			Vec3.prototype.set = function (x, y, z) {
  				this.x = x;
  				this.y = y;
  				this.z = z;
  				return this;
  			};
  
  			Vec3.prototype.add = function (w) {
  				this.x += w.x;
  				this.y += w.y;
  				this.z += w.z;
  				return this;
  			};
  
  			Vec3.prototype.sub = function (w) {
  				this.x -= w.x;
  				this.y -= w.y;
  				this.z -= w.z;
  				return this;
  			};
  
  			Vec3.prototype.mul = function (m) {
  				this.x *= m;
  				this.y *= m;
  				this.z *= m;
  				return this;
  			};
  
  			Vec3.areEqual = function (v, w) {
  				_ASSERT && Vec3.assert(v);
  				_ASSERT && Vec3.assert(w);
  				return v == w || (typeof v === 'object' && v !== null && typeof w === 'object' && w !== null && v.x === w.x && v.y === w.y && v.z === w.z);
  			};
  
  			/**
               * Perform the dot product on two vectors.
               */
  			Vec3.dot = function (v, w) {
  				return v.x * w.x + v.y * w.y + v.z * w.z;
  			};
  
  			/**
               * Perform the cross product on two vectors. In 2D this produces a scalar.
               */
  			Vec3.cross = function (v, w) {
  				return new Vec3(v.y * w.z - v.z * w.y, v.z * w.x - v.x * w.z, v.x * w.y - v.y * w.x);
  			};
  
  			Vec3.add = function (v, w) {
  				return new Vec3(v.x + w.x, v.y + w.y, v.z + w.z);
  			};
  
  			Vec3.sub = function (v, w) {
  				return new Vec3(v.x - w.x, v.y - w.y, v.z - w.z);
  			};
  
  			Vec3.mul = function (v, m) {
  				return new Vec3(m * v.x, m * v.y, m * v.z);
  			};
  
  			Vec3.prototype.neg = function () {
  				this.x = -this.x;
  				this.y = -this.y;
  				this.z = -this.z;
  				return this;
  			};
  
  			Vec3.neg = function (v) {
  				return new Vec3(-v.x, -v.y, -v.z);
  			};
  
  			/***/
  		},
  		/* 12 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Joint;
  
  			var common = __webpack_require__(2);
  
  			/**
               * A joint edge is used to connect bodies and joints together in a joint graph
               * where each body is a node and each joint is an edge. A joint edge belongs to
               * a doubly linked list maintained in each attached body. Each joint has two
               * joint nodes, one for each attached body.
               *
               * @prop {Body} other provides quick access to the other body attached.
               * @prop {Joint} joint the joint
               * @prop {JointEdge} prev the previous joint edge in the body's joint list
               * @prop {JointEdge} next the next joint edge in the body's joint list
               */
  			function JointEdge () {
  				this.other = null;
  				this.joint = null;
  				this.prev = null;
  				this.next = null;
  			}
  
  			/**
               * @typedef {Object} JointDef
               *
               * Joint definitions are used to construct joints.
               *
               * @prop userData Use this to attach application specific data to your joints.
               *       void userData;
               * @prop {boolean} collideConnected Set this flag to true if the attached bodies
               *       should collide.
               *
               * @prop {Body} bodyA The first attached body.
               * @prop {Body} bodyB The second attached body.
               */
  
  			var DEFAULTS = {
  				userData: null,
  				collideConnected: false
  			};
  
  			/**
               * The base joint class. Joints are used to constraint two bodies together in
               * various fashions. Some joints also feature limits and motors.
               *
               * @param {JointDef} def
               */
  			function Joint (def, bodyA, bodyB) {
  				bodyA = def.bodyA || bodyA;
  				bodyB = def.bodyB || bodyB;
  
  				_ASSERT && common.assert(bodyA);
  				_ASSERT && common.assert(bodyB);
  				_ASSERT && common.assert(bodyA != bodyB);
  
  				this.m_type = 'unknown-joint';
  
  				this.m_bodyA = bodyA;
  				this.m_bodyB = bodyB;
  
  				this.m_index = 0;
  				this.m_collideConnected = !!def.collideConnected;
  
  				this.m_prev = null;
  				this.m_next = null;
  
  				this.m_edgeA = new JointEdge();
  				this.m_edgeB = new JointEdge();
  
  				this.m_islandFlag = false;
  				this.m_userData = def.userData;
  			}
  
  			Joint.TYPES = {};
  
  			Joint._deserialize = function (data, context, restore) {
  				var clazz = Joint.TYPES[data.type];
  				return clazz && restore(clazz, data);
  			};
  
  			/**
               * Short-cut function to determine if either body is inactive.
               *
               * @returns {boolean}
               */
  			Joint.prototype.isActive = function () {
  				return this.m_bodyA.isActive() && this.m_bodyB.isActive();
  			};
  
  			/**
               * Get the type of the concrete joint.
               *
               * @returns JointType
               */
  			Joint.prototype.getType = function () {
  				return this.m_type;
  			};
  
  			/**
               * Get the first body attached to this joint.
               *
               * @returns Body
               */
  			Joint.prototype.getBodyA = function () {
  				return this.m_bodyA;
  			};
  
  			/**
               * Get the second body attached to this joint.
               *
               * @returns Body
               */
  			Joint.prototype.getBodyB = function () {
  				return this.m_bodyB;
  			};
  
  			/**
               * Get the next joint the world joint list.
               *
               * @returns Joint
               */
  			Joint.prototype.getNext = function () {
  				return this.m_next;
  			};
  
  			Joint.prototype.getUserData = function () {
  				return this.m_userData;
  			};
  
  			Joint.prototype.setUserData = function (data) {
  				this.m_userData = data;
  			};
  
  			/**
               * Get collide connected. Note: modifying the collide connect flag won't work
               * correctly because the flag is only checked when fixture AABBs begin to
               * overlap.
               *
               * @returns {boolean}
               */
  			Joint.prototype.getCollideConnected = function () {
  				return this.m_collideConnected;
  			};
  
  			/**
               * Get the anchor point on bodyA in world coordinates.
               *
               * @return {Vec2}
               */
  			Joint.prototype.getAnchorA = function () {};
  
  			/**
               * Get the anchor point on bodyB in world coordinates.
               *
               * @return {Vec2}
               */
  			Joint.prototype.getAnchorB = function () {};
  
  			/**
               * Get the reaction force on bodyB at the joint anchor in Newtons.
               *
               * @param {float} inv_dt
               * @return {Vec2}
               */
  			Joint.prototype.getReactionForce = function (inv_dt) {};
  
  			/**
               * Get the reaction torque on bodyB in N*m.
               *
               * @param {float} inv_dt
               * @return {float}
               */
  			Joint.prototype.getReactionTorque = function (inv_dt) {};
  
  			/**
               * Shift the origin for any points stored in world coordinates.
               *
               * @param {Vec2} newOrigin
               */
  			Joint.prototype.shiftOrigin = function (newOrigin) {};
  
  			/**
               */
  			Joint.prototype.initVelocityConstraints = function (step) {};
  
  			/**
               */
  			Joint.prototype.solveVelocityConstraints = function (step) {};
  
  			/**
               * This returns true if the position errors are within tolerance.
               */
  			Joint.prototype.solvePositionConstraints = function (step) {};
  
  			/***/
  		},
  		/* 13 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Velocity;
  
  			var Vec2 = __webpack_require__(0);
  
  			/**
               * @prop {Vec2} v linear
               * @prop {float} w angular
               */
  			function Velocity () {
  				this.v = Vec2.zero();
  				this.w = 0;
  			}
  
  			/***/
  		},
  		/* 14 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Position;
  
  			var Vec2 = __webpack_require__(0);
  			var Rot = __webpack_require__(3);
  
  			/**
               * @prop {Vec2} c location
               * @prop {float} a angle
               */
  			function Position () {
  				this.c = Vec2.zero();
  				this.a = 0;
  			}
  
  			Position.prototype.getTransform = function (xf, p) {
  				xf.q.set(this.a);
  				xf.p.set(Vec2.sub(this.c, Rot.mulVec2(xf.q, p)));
  				return xf;
  			};
  
  			/***/
  		},
  		/* 15 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Mat33;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  
  			/**
               * A 3-by-3 matrix. Stored in column-major order.
               */
  			function Mat33 (a, b, c) {
  				if (typeof a === 'object' && a !== null) {
  					this.ex = Vec3.clone(a);
  					this.ey = Vec3.clone(b);
  					this.ez = Vec3.clone(c);
  				} else {
  					this.ex = Vec3();
  					this.ey = Vec3();
  					this.ez = Vec3();
  				}
  			}
  
  			Mat33.prototype.toString = function () {
  				return JSON.stringify(this);
  			};
  
  			Mat33.isValid = function (o) {
  				return o && Vec3.isValid(o.ex) && Vec3.isValid(o.ey) && Vec3.isValid(o.ez);
  			};
  
  			Mat33.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!Mat33.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid Mat33!');
  				}
  			};
  
  			/**
               * Set this matrix to all zeros.
               */
  			Mat33.prototype.setZero = function () {
  				this.ex.setZero();
  				this.ey.setZero();
  				this.ez.setZero();
  				return this;
  			};
  
  			/**
               * Solve A * x = b, where b is a column vector. This is more efficient than
               * computing the inverse in one-shot cases.
               *
               * @param {Vec3} v
               * @returns {Vec3}
               */
  			Mat33.prototype.solve33 = function (v) {
  				var det = Vec3.dot(this.ex, Vec3.cross(this.ey, this.ez));
  				if (det != 0.0) {
  					det = 1.0 / det;
  				}
  				var r = new Vec3();
  				r.x = det * Vec3.dot(v, Vec3.cross(this.ey, this.ez));
  				r.y = det * Vec3.dot(this.ex, Vec3.cross(v, this.ez));
  				r.z = det * Vec3.dot(this.ex, Vec3.cross(this.ey, v));
  				return r;
  			};
  
  			/**
               * Solve A * x = b, where b is a column vector. This is more efficient than
               * computing the inverse in one-shot cases. Solve only the upper 2-by-2 matrix
               * equation.
               *
               * @param {Vec2} v
               *
               * @returns {Vec2}
               */
  			Mat33.prototype.solve22 = function (v) {
  				var a11 = this.ex.x;
  				var a12 = this.ey.x;
  				var a21 = this.ex.y;
  				var a22 = this.ey.y;
  				var det = a11 * a22 - a12 * a21;
  				if (det != 0.0) {
  					det = 1.0 / det;
  				}
  				var r = Vec2.zero();
  				r.x = det * (a22 * v.x - a12 * v.y);
  				r.y = det * (a11 * v.y - a21 * v.x);
  				return r;
  			};
  
  			/**
               * Get the inverse of this matrix as a 2-by-2. Returns the zero matrix if
               * singular.
               *
               * @param {Mat33} M
               */
  			Mat33.prototype.getInverse22 = function (M) {
  				var a = this.ex.x;
  				var b = this.ey.x;
  				var c = this.ex.y;
  				var d = this.ey.y;
  				var det = a * d - b * c;
  				if (det != 0.0) {
  					det = 1.0 / det;
  				}
  				M.ex.x = det * d;
  				M.ey.x = -det * b;
  				M.ex.z = 0.0;
  				M.ex.y = -det * c;
  				M.ey.y = det * a;
  				M.ey.z = 0.0;
  				M.ez.x = 0.0;
  				M.ez.y = 0.0;
  				M.ez.z = 0.0;
  			};
  
  			/**
               * Get the symmetric inverse of this matrix as a 3-by-3. Returns the zero matrix
               * if singular.
               *
               * @param {Mat33} M
               */
  			Mat33.prototype.getSymInverse33 = function (M) {
  				var det = Vec3.dot(this.ex, Vec3.cross(this.ey, this.ez));
  				if (det != 0.0) {
  					det = 1.0 / det;
  				}
  				var a11 = this.ex.x;
  				var a12 = this.ey.x;
  				var a13 = this.ez.x;
  				var a22 = this.ey.y;
  				var a23 = this.ez.y;
  				var a33 = this.ez.z;
  
  				M.ex.x = det * (a22 * a33 - a23 * a23);
  				M.ex.y = det * (a13 * a23 - a12 * a33);
  				M.ex.z = det * (a12 * a23 - a13 * a22);
  
  				M.ey.x = M.ex.y;
  				M.ey.y = det * (a11 * a33 - a13 * a13);
  				M.ey.z = det * (a13 * a12 - a11 * a23);
  
  				M.ez.x = M.ex.z;
  				M.ez.y = M.ey.z;
  				M.ez.z = det * (a11 * a22 - a12 * a12);
  			};
  
  			/**
               * Multiply a matrix times a vector.
               *
               * @param {Mat33} a
               * @param {Vec3|Vec2} b
               *
               * @returns {Vec3|Vec2}
               */
  			Mat33.mul = function (a, b) {
  				_ASSERT && Mat33.assert(a);
  				if (b && 'z' in b && 'y' in b && 'x' in b) {
  					_ASSERT && Vec3.assert(b);
  					var x = a.ex.x * b.x + a.ey.x * b.y + a.ez.x * b.z;
  					var y = a.ex.y * b.x + a.ey.y * b.y + a.ez.y * b.z;
  					var z = a.ex.z * b.x + a.ey.z * b.y + a.ez.z * b.z;
  					return new Vec3(x, y, z);
  				} else if (b && 'y' in b && 'x' in b) {
  					_ASSERT && Vec2.assert(b);
  					var x = a.ex.x * b.x + a.ey.x * b.y;
  					var y = a.ex.y * b.x + a.ey.y * b.y;
  					return Vec2.neo(x, y);
  				}
  
  				_ASSERT && common.assert(false);
  			};
  
  			Mat33.mulVec3 = function (a, b) {
  				_ASSERT && Mat33.assert(a);
  				_ASSERT && Vec3.assert(b);
  				var x = a.ex.x * b.x + a.ey.x * b.y + a.ez.x * b.z;
  				var y = a.ex.y * b.x + a.ey.y * b.y + a.ez.y * b.z;
  				var z = a.ex.z * b.x + a.ey.z * b.y + a.ez.z * b.z;
  				return new Vec3(x, y, z);
  			};
  
  			Mat33.mulVec2 = function (a, b) {
  				_ASSERT && Mat33.assert(a);
  				_ASSERT && Vec2.assert(b);
  				var x = a.ex.x * b.x + a.ey.x * b.y;
  				var y = a.ex.y * b.x + a.ey.y * b.y;
  				return Vec2.neo(x, y);
  			};
  
  			Mat33.add = function (a, b) {
  				_ASSERT && Mat33.assert(a);
  				_ASSERT && Mat33.assert(b);
  				return new Mat33(Vec3.add(a.ex, b.ex), Vec3.add(a.ey, b.ey), Vec3.add(a.ez, b.ez));
  			};
  
  			/***/
  		},
  		/* 16 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Shape;
  
  			var Math = __webpack_require__(1);
  
  			/**
               * A shape is used for collision detection. You can create a shape however you
               * like. Shapes used for simulation in World are created automatically when a
               * Fixture is created. Shapes may encapsulate one or more child shapes.
               */
  			function Shape () {
  				this.m_type;
  				this.m_radius;
  			}
  
  			Shape.prototype._reset = function () {};
  
  			Shape.prototype._serialize = function () {
  				return {};
  			};
  
  			Shape.TYPES = {};
  
  			Shape._deserialize = function (data, context, restore) {
  				var clazz = Shape.TYPES[data.type];
  				return clazz && restore(clazz, data);
  			};
  
  			Shape.isValid = function (shape) {
  				return !!shape;
  			};
  
  			Shape.prototype.getRadius = function () {
  				return this.m_radius;
  			};
  
  			/**
               * Get the type of this shape. You can use this to down cast to the concrete
               * shape.
               *
               * @return the shape type.
               */
  			Shape.prototype.getType = function () {
  				return this.m_type;
  			};
  
  			/**
               * @deprecated Shapes should be treated as immutable.
               *
               * clone the concrete shape.
               */
  			Shape.prototype._clone = function () {};
  
  			/**
               * // Get the number of child primitives.
               */
  			Shape.prototype.getChildCount = function () {};
  
  			/**
               * Test a point for containment in this shape. This only works for convex
               * shapes.
               *
               * @param {Transform} xf The shape world transform.
               * @param p A point in world coordinates.
               */
  			Shape.prototype.testPoint = function (xf, p) {};
  
  			/**
               * Cast a ray against a child shape.
               *
               * @param {RayCastOutput} output The ray-cast results.
               * @param {RayCastInput} input The ray-cast input parameters.
               * @param {Transform} transform The transform to be applied to the shape.
               * @param childIndex The child shape index
               */
  			Shape.prototype.rayCast = function (output, input, transform, childIndex) {};
  
  			/**
               * Given a transform, compute the associated axis aligned bounding box for a
               * child shape.
               *
               * @param {AABB} aabb Returns the axis aligned box.
               * @param {Transform} xf The world transform of the shape.
               * @param childIndex The child shape
               */
  			Shape.prototype.computeAABB = function (aabb, xf, childIndex) {};
  
  			/**
               * Compute the mass properties of this shape using its dimensions and density.
               * The inertia tensor is computed about the local origin.
               *
               * @param {MassData} massData Returns the mass data for this shape.
               * @param density The density in kilograms per meter squared.
               */
  			Shape.prototype.computeMass = function (massData, density) {};
  
  			/**
               * @param {DistanceProxy} proxy
               */
  			Shape.prototype.computeDistanceProxy = function (proxy) {};
  
  			/***/
  		},
  		/* 17 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var Settings = __webpack_require__(4);
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  
  			module.exports = AABB;
  
  			function AABB (lower, upper) {
  				if (!(this instanceof AABB)) {
  					return new AABB(lower, upper);
  				}
  
  				this.lowerBound = Vec2.zero();
  				this.upperBound = Vec2.zero();
  
  				if (typeof lower === 'object') {
  					this.lowerBound.set(lower);
  				}
  				if (typeof upper === 'object') {
  					this.upperBound.set(upper);
  				} else if (typeof lower === 'object') {
  					this.upperBound.set(lower);
  				}
  			}
  
  			/**
               * Verify that the bounds are sorted.
               */
  			AABB.prototype.isValid = function () {
  				return AABB.isValid(this);
  			};
  
  			AABB.isValid = function (aabb) {
  				var d = Vec2.sub(aabb.upperBound, aabb.lowerBound);
  				var valid = d.x >= 0.0 && d.y >= 0.0 && Vec2.isValid(aabb.lowerBound) && Vec2.isValid(aabb.upperBound);
  				return valid;
  			};
  
  			AABB.assert = function (o) {
  				if (!_ASSERT) return;
  				if (!AABB.isValid(o)) {
  					_DEBUG && common.debug(o);
  					throw new Error('Invalid AABB!');
  				}
  			};
  
  			/**
               * Get the center of the AABB.
               */
  			AABB.prototype.getCenter = function () {
  				return Vec2.neo((this.lowerBound.x + this.upperBound.x) * 0.5, (this.lowerBound.y + this.upperBound.y) * 0.5);
  			};
  
  			/**
               * Get the extents of the AABB (half-widths).
               */
  			AABB.prototype.getExtents = function () {
  				return Vec2.neo((this.upperBound.x - this.lowerBound.x) * 0.5, (this.upperBound.y - this.lowerBound.y) * 0.5);
  			};
  
  			/**
               * Get the perimeter length.
               */
  			AABB.prototype.getPerimeter = function () {
  				return 2.0 * (this.upperBound.x - this.lowerBound.x + this.upperBound.y - this.lowerBound.y);
  			};
  
  			/**
               * Combine one or two AABB into this one.
               */
  			AABB.prototype.combine = function (a, b) {
  				b = b || this;
  
  				var lowerA = a.lowerBound;
  				var upperA = a.upperBound;
  				var lowerB = b.lowerBound;
  				var upperB = b.upperBound;
  
  				var lowerX = Math.min(lowerA.x, lowerB.x);
  				var lowerY = Math.min(lowerA.y, lowerB.y);
  				var upperX = Math.max(upperB.x, upperA.x);
  				var upperY = Math.max(upperB.y, upperA.y);
  
  				this.lowerBound.set(lowerX, lowerY);
  				this.upperBound.set(upperX, upperY);
  			};
  
  			AABB.prototype.combinePoints = function (a, b) {
  				this.lowerBound.set(Math.min(a.x, b.x), Math.min(a.y, b.y));
  				this.upperBound.set(Math.max(a.x, b.x), Math.max(a.y, b.y));
  			};
  
  			AABB.prototype.set = function (aabb) {
  				this.lowerBound.set(aabb.lowerBound.x, aabb.lowerBound.y);
  				this.upperBound.set(aabb.upperBound.x, aabb.upperBound.y);
  			};
  
  			AABB.prototype.contains = function (aabb) {
  				var result = true;
  				result = result && this.lowerBound.x <= aabb.lowerBound.x;
  				result = result && this.lowerBound.y <= aabb.lowerBound.y;
  				result = result && aabb.upperBound.x <= this.upperBound.x;
  				result = result && aabb.upperBound.y <= this.upperBound.y;
  				return result;
  			};
  
  			AABB.prototype.extend = function (value) {
  				AABB.extend(this, value);
  				return this;
  			};
  
  			AABB.extend = function (aabb, value) {
  				aabb.lowerBound.x -= value;
  				aabb.lowerBound.y -= value;
  				aabb.upperBound.x += value;
  				aabb.upperBound.y += value;
  			};
  
  			AABB.testOverlap = function (a, b) {
  				var d1x = b.lowerBound.x - a.upperBound.x;
  				var d2x = a.lowerBound.x - b.upperBound.x;
  
  				var d1y = b.lowerBound.y - a.upperBound.y;
  				var d2y = a.lowerBound.y - b.upperBound.y;
  
  				if (d1x > 0 || d1y > 0 || d2x > 0 || d2y > 0) {
  					return false;
  				}
  				return true;
  			};
  
  			AABB.areEqual = function (a, b) {
  				return Vec2.areEqual(a.lowerBound, b.lowerBound) && Vec2.areEqual(a.upperBound, b.upperBound);
  			};
  
  			AABB.diff = function (a, b) {
  				var wD = Math.max(0, Math.min(a.upperBound.x, b.upperBound.x) - Math.max(b.lowerBound.x, a.lowerBound.x));
  				var hD = Math.max(0, Math.min(a.upperBound.y, b.upperBound.y) - Math.max(b.lowerBound.y, a.lowerBound.y));
  
  				var wA = a.upperBound.x - a.lowerBound.x;
  				var hA = a.upperBound.y - a.lowerBound.y;
  
  				var wB = b.upperBound.x - b.lowerBound.x;
  				var hB = b.upperBound.y - b.lowerBound.y;
  
  				return wA * hA + wB * hB - wD * hD;
  			};
  
  			/**
               * @typedef RayCastInput
               *
               * Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
               *
               * @prop {Vec2} p1
               * @prop {Vec2} p2
               * @prop {number} maxFraction
               */
  
  			/**
               * @typedef RayCastInput
               *
               * Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and
               * p2 come from RayCastInput.
               *
               * @prop {Vec2} normal
               * @prop {number} fraction
               */
  
  			/**
               * @param {RayCastOutput} output
               * @param {RayCastInput} input
               * @returns {boolean}
               */
  			AABB.prototype.rayCast = function (output, input) {
  				// From Real-time Collision Detection, p179.
  
  				var tmin = -Infinity;
  				var tmax = Infinity;
  
  				var p = input.p1;
  				var d = Vec2.sub(input.p2, input.p1);
  				var absD = Vec2.abs(d);
  
  				var normal = Vec2.zero();
  
  				for (var f = 'x'; f !== null; f = f === 'x' ? 'y' : null) {
  					if (absD.x < Math.EPSILON) {
  						// Parallel.
  						if (p[f] < this.lowerBound[f] || this.upperBound[f] < p[f]) {
  							return false;
  						}
  					} else {
  						var inv_d = 1.0 / d[f];
  						var t1 = (this.lowerBound[f] - p[f]) * inv_d;
  						var t2 = (this.upperBound[f] - p[f]) * inv_d;
  
  						// Sign of the normal vector.
  						var s = -1.0;
  
  						if (t1 > t2) {
  							var temp = t1;
  							(t1 = t2), (t2 = temp);
  							s = 1.0;
  						}
  
  						// Push the min up
  						if (t1 > tmin) {
  							normal.setZero();
  							normal[f] = s;
  							tmin = t1;
  						}
  
  						// Pull the max down
  						tmax = Math.min(tmax, t2);
  
  						if (tmin > tmax) {
  							return false;
  						}
  					}
  				}
  
  				// Does the ray start inside the box?
  				// Does the ray intersect beyond the max fraction?
  				if (tmin < 0.0 || input.maxFraction < tmin) {
  					return false;
  				}
  
  				// Intersection.
  				output.fraction = tmin;
  				output.normal = normal;
  				return true;
  			};
  
  			AABB.prototype.toString = function () {
  				return JSON.stringify(this);
  			};
  
  			/***/
  		},
  		/* 18 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var DEBUG_SOLVER = false;
  
  			var common = __webpack_require__(2);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Transform = __webpack_require__(5);
  			var Mat22 = __webpack_require__(10);
  			var Rot = __webpack_require__(3);
  
  			var Settings = __webpack_require__(4);
  			var Manifold = __webpack_require__(19);
  			var Distance = __webpack_require__(22);
  
  			module.exports = Contact;
  
  			/**
               * A contact edge is used to connect bodies and contacts together in a contact
               * graph where each body is a node and each contact is an edge. A contact edge
               * belongs to a doubly linked list maintained in each attached body. Each
               * contact has two contact nodes, one for each attached body.
               *
               * @prop {Contact} contact The contact
               * @prop {ContactEdge} prev The previous contact edge in the body's contact list
               * @prop {ContactEdge} next The next contact edge in the body's contact list
               * @prop {Body} other Provides quick access to the other body attached.
               */
  			function ContactEdge (contact) {
  				this.contact = contact;
  				this.prev;
  				this.next;
  				this.other;
  			}
  
  			/**
               * @function Contact~evaluate
               *
               * @param manifold
               * @param xfA
               * @param fixtureA
               * @param indexA
               * @param xfB
               * @param fixtureB
               * @param indexB
               */
  
  			/**
               * The class manages contact between two shapes. A contact exists for each
               * overlapping AABB in the broad-phase (except if filtered). Therefore a contact
               * object may exist that has no contact points.
               *
               * @param {Fixture} fA
               * @param {int} indexA
               * @param {Fixture} fB
               * @param {int} indexB
               * @param {Contact~evaluate} evaluateFcn
               */
  			function Contact (fA, indexA, fB, indexB, evaluateFcn) {
  				// Nodes for connecting bodies.
  				this.m_nodeA = new ContactEdge(this);
  				this.m_nodeB = new ContactEdge(this);
  
  				this.m_fixtureA = fA;
  				this.m_fixtureB = fB;
  
  				this.m_indexA = indexA;
  				this.m_indexB = indexB;
  
  				this.m_evaluateFcn = evaluateFcn;
  
  				this.m_manifold = new Manifold();
  
  				this.m_prev = null;
  				this.m_next = null;
  
  				this.m_toi = 1.0;
  				this.m_toiCount = 0;
  				// This contact has a valid TOI in m_toi
  				this.m_toiFlag = false;
  
  				this.m_friction = mixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction);
  				this.m_restitution = mixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution);
  
  				this.m_tangentSpeed = 0.0;
  
  				// This contact can be disabled (by user)
  				this.m_enabledFlag = true;
  
  				// Used when crawling contact graph when forming islands.
  				this.m_islandFlag = false;
  
  				// Set when the shapes are touching.
  				this.m_touchingFlag = false;
  
  				// This contact needs filtering because a fixture filter was changed.
  				this.m_filterFlag = false;
  
  				// This bullet contact had a TOI event
  				this.m_bulletHitFlag = false;
  
  				this.v_points = []; // VelocityConstraintPoint[maxManifoldPoints]
  				this.v_normal = Vec2.zero();
  				this.v_normalMass = new Mat22();
  				this.v_K = new Mat22();
  				this.v_pointCount;
  
  				this.v_tangentSpeed;
  				this.v_friction;
  				this.v_restitution;
  
  				this.v_invMassA;
  				this.v_invMassB;
  				this.v_invIA;
  				this.v_invIB;
  
  				this.p_localPoints = []; // Vec2[maxManifoldPoints];
  				this.p_localNormal = Vec2.zero();
  				this.p_localPoint = Vec2.zero();
  				this.p_localCenterA = Vec2.zero();
  				this.p_localCenterB = Vec2.zero();
  				this.p_type; // Manifold.Type
  				this.p_radiusA;
  				this.p_radiusB;
  				this.p_pointCount;
  
  				this.p_invMassA;
  				this.p_invMassB;
  				this.p_invIA;
  				this.p_invIB;
  			}
  
  			Contact.prototype.initConstraint = function (step) {
  				var fixtureA = this.m_fixtureA;
  				var fixtureB = this.m_fixtureB;
  
  				var shapeA = fixtureA.getShape();
  				var shapeB = fixtureB.getShape();
  
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				var manifold = this.getManifold();
  
  				var pointCount = manifold.pointCount;
  				_ASSERT && common.assert(pointCount > 0);
  
  				this.v_invMassA = bodyA.m_invMass;
  				this.v_invMassB = bodyB.m_invMass;
  				this.v_invIA = bodyA.m_invI;
  				this.v_invIB = bodyB.m_invI;
  
  				this.v_friction = this.m_friction;
  				this.v_restitution = this.m_restitution;
  				this.v_tangentSpeed = this.m_tangentSpeed;
  
  				this.v_pointCount = pointCount;
  
  				this.v_K.setZero();
  				this.v_normalMass.setZero();
  
  				this.p_invMassA = bodyA.m_invMass;
  				this.p_invMassB = bodyB.m_invMass;
  				this.p_invIA = bodyA.m_invI;
  				this.p_invIB = bodyB.m_invI;
  				this.p_localCenterA = Vec2.clone(bodyA.m_sweep.localCenter);
  				this.p_localCenterB = Vec2.clone(bodyB.m_sweep.localCenter);
  
  				this.p_radiusA = shapeA.m_radius;
  				this.p_radiusB = shapeB.m_radius;
  
  				this.p_type = manifold.type;
  				this.p_localNormal = Vec2.clone(manifold.localNormal);
  				this.p_localPoint = Vec2.clone(manifold.localPoint);
  				this.p_pointCount = pointCount;
  
  				for (var j = 0; j < pointCount; ++j) {
  					var cp = manifold.points[j]; // ManifoldPoint
  					var vcp = (this.v_points[j] = new VelocityConstraintPoint());
  
  					if (step.warmStarting) {
  						vcp.normalImpulse = step.dtRatio * cp.normalImpulse;
  						vcp.tangentImpulse = step.dtRatio * cp.tangentImpulse;
  					} else {
  						vcp.normalImpulse = 0.0;
  						vcp.tangentImpulse = 0.0;
  					}
  
  					vcp.rA.setZero();
  					vcp.rB.setZero();
  					vcp.normalMass = 0.0;
  					vcp.tangentMass = 0.0;
  					vcp.velocityBias = 0.0;
  
  					this.p_localPoints[j] = Vec2.clone(cp.localPoint);
  				}
  			};
  
  			/**
               * Get the contact manifold. Do not modify the manifold unless you understand
               * the internals of the library.
               */
  			Contact.prototype.getManifold = function () {
  				return this.m_manifold;
  			};
  
  			/**
               * Get the world manifold.
               *
               * @param {WorldManifold} [worldManifold]
               */
  			Contact.prototype.getWorldManifold = function (worldManifold) {
  				var bodyA = this.m_fixtureA.getBody();
  				var bodyB = this.m_fixtureB.getBody();
  				var shapeA = this.m_fixtureA.getShape();
  				var shapeB = this.m_fixtureB.getShape();
  
  				return this.m_manifold.getWorldManifold(worldManifold, bodyA.getTransform(), shapeA.m_radius, bodyB.getTransform(), shapeB.m_radius);
  			};
  
  			/**
               * Enable/disable this contact. This can be used inside the pre-solve contact
               * listener. The contact is only disabled for the current time step (or sub-step
               * in continuous collisions).
               */
  			Contact.prototype.setEnabled = function (flag) {
  				this.m_enabledFlag = !!flag;
  			};
  
  			/**
               * Has this contact been disabled?
               */
  			Contact.prototype.isEnabled = function () {
  				return this.m_enabledFlag;
  			};
  
  			/**
               * Is this contact touching?
               */
  			Contact.prototype.isTouching = function () {
  				return this.m_touchingFlag;
  			};
  
  			/**
               * Get the next contact in the world's contact list.
               */
  			Contact.prototype.getNext = function () {
  				return this.m_next;
  			};
  
  			/**
               * Get fixture A in this contact.
               */
  			Contact.prototype.getFixtureA = function () {
  				return this.m_fixtureA;
  			};
  
  			/**
               * Get fixture B in this contact.
               */
  			Contact.prototype.getFixtureB = function () {
  				return this.m_fixtureB;
  			};
  
  			/**
               * Get the child primitive index for fixture A.
               */
  			Contact.prototype.getChildIndexA = function () {
  				return this.m_indexA;
  			};
  
  			/**
               * Get the child primitive index for fixture B.
               */
  			Contact.prototype.getChildIndexB = function () {
  				return this.m_indexB;
  			};
  
  			/**
               * Flag this contact for filtering. Filtering will occur the next time step.
               */
  			Contact.prototype.flagForFiltering = function () {
  				this.m_filterFlag = true;
  			};
  
  			/**
               * Override the default friction mixture. You can call this in
               * ContactListener.preSolve. This value persists until set or reset.
               */
  			Contact.prototype.setFriction = function (friction) {
  				this.m_friction = friction;
  			};
  
  			/**
               * Get the friction.
               */
  			Contact.prototype.getFriction = function () {
  				return this.m_friction;
  			};
  
  			/**
               * Reset the friction mixture to the default value.
               */
  			Contact.prototype.resetFriction = function () {
  				this.m_friction = mixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction);
  			};
  
  			/**
               * Override the default restitution mixture. You can call this in
               * ContactListener.preSolve. The value persists until you set or reset.
               */
  			Contact.prototype.setRestitution = function (restitution) {
  				this.m_restitution = restitution;
  			};
  
  			/**
               * Get the restitution.
               */
  			Contact.prototype.getRestitution = function () {
  				return this.m_restitution;
  			};
  
  			/**
               * Reset the restitution to the default value.
               */
  			Contact.prototype.resetRestitution = function () {
  				this.m_restitution = mixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution);
  			};
  
  			/**
               * Set the desired tangent speed for a conveyor belt behavior. In meters per
               * second.
               */
  			Contact.prototype.setTangentSpeed = function (speed) {
  				this.m_tangentSpeed = speed;
  			};
  
  			/**
               * Get the desired tangent speed. In meters per second.
               */
  			Contact.prototype.getTangentSpeed = function () {
  				return this.m_tangentSpeed;
  			};
  
  			/**
               * Called by Update method, and implemented by subclasses.
               */
  			Contact.prototype.evaluate = function (manifold, xfA, xfB) {
  				this.m_evaluateFcn(manifold, xfA, this.m_fixtureA, this.m_indexA, xfB, this.m_fixtureB, this.m_indexB);
  			};
  
  			/**
               * Updates the contact manifold and touching status.
               *
               * Note: do not assume the fixture AABBs are overlapping or are valid.
               *
               * @param {function} listener.beginContact
               * @param {function} listener.endContact
               * @param {function} listener.preSolve
               */
  			Contact.prototype.update = function (listener) {
  				// Re-enable this contact.
  				this.m_enabledFlag = true;
  
  				var touching = false;
  				var wasTouching = this.m_touchingFlag;
  
  				var sensorA = this.m_fixtureA.isSensor();
  				var sensorB = this.m_fixtureB.isSensor();
  				var sensor = sensorA || sensorB;
  
  				var bodyA = this.m_fixtureA.getBody();
  				var bodyB = this.m_fixtureB.getBody();
  				var xfA = bodyA.getTransform();
  				var xfB = bodyB.getTransform();
  
  				// Is this contact a sensor?
  				if (sensor) {
  					var shapeA = this.m_fixtureA.getShape();
  					var shapeB = this.m_fixtureB.getShape();
  					touching = Distance.testOverlap(shapeA, this.m_indexA, shapeB, this.m_indexB, xfA, xfB);
  
  					// Sensors don't generate manifolds.
  					this.m_manifold.pointCount = 0;
  				} else {
  					// TODO reuse manifold
  					var oldManifold = this.m_manifold;
  					this.m_manifold = new Manifold();
  
  					this.evaluate(this.m_manifold, xfA, xfB);
  					touching = this.m_manifold.pointCount > 0;
  
  					// Match old contact ids to new contact ids and copy the
  					// stored impulses to warm start the solver.
  					for (var i = 0; i < this.m_manifold.pointCount; ++i) {
  						var nmp = this.m_manifold.points[i];
  						nmp.normalImpulse = 0.0;
  						nmp.tangentImpulse = 0.0;
  
  						for (var j = 0; j < oldManifold.pointCount; ++j) {
  							var omp = oldManifold.points[j];
  							if (omp.id.key == nmp.id.key) {
  								// ContactID.key
  								nmp.normalImpulse = omp.normalImpulse;
  								nmp.tangentImpulse = omp.tangentImpulse;
  								break;
  							}
  						}
  					}
  
  					if (touching != wasTouching) {
  						bodyA.setAwake(true);
  						bodyB.setAwake(true);
  					}
  				}
  
  				this.m_touchingFlag = touching;
  
  				if (wasTouching == false && touching == true && listener) {
  					listener.beginContact(this);
  				}
  
  				if (wasTouching == true && touching == false && listener) {
  					listener.endContact(this);
  				}
  
  				if (sensor == false && touching && listener) {
  					listener.preSolve(this, oldManifold);
  				}
  			};
  
  			Contact.prototype.solvePositionConstraint = function (step) {
  				return this._solvePositionConstraint(step, false);
  			};
  
  			Contact.prototype.solvePositionConstraintTOI = function (step, toiA, toiB) {
  				return this._solvePositionConstraint(step, true, toiA, toiB);
  			};
  
  			Contact.prototype._solvePositionConstraint = function (step, toi, toiA, toiB) {
  				var fixtureA = this.m_fixtureA;
  				var fixtureB = this.m_fixtureB;
  
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				var velocityA = bodyA.c_velocity;
  				var velocityB = bodyB.c_velocity;
  				var positionA = bodyA.c_position;
  				var positionB = bodyB.c_position;
  
  				var localCenterA = Vec2.clone(this.p_localCenterA);
  				var localCenterB = Vec2.clone(this.p_localCenterB);
  
  				var mA = 0.0;
  				var iA = 0.0;
  				if (!toi || bodyA == toiA || bodyA == toiB) {
  					mA = this.p_invMassA;
  					iA = this.p_invIA;
  				}
  
  				var mB = 0.0;
  				var iB = 0.0;
  				if (!toi || bodyB == toiA || bodyB == toiB) {
  					mB = this.p_invMassB;
  					iB = this.p_invIB;
  				}
  
  				var cA = Vec2.clone(positionA.c);
  				var aA = positionA.a;
  
  				var cB = Vec2.clone(positionB.c);
  				var aB = positionB.a;
  
  				var minSeparation = 0.0;
  
  				// Solve normal constraints
  				for (var j = 0; j < this.p_pointCount; ++j) {
  					var xfA = Transform.identity();
  					var xfB = Transform.identity();
  					xfA.q.set(aA);
  					xfB.q.set(aB);
  					xfA.p = Vec2.sub(cA, Rot.mulVec2(xfA.q, localCenterA));
  					xfB.p = Vec2.sub(cB, Rot.mulVec2(xfB.q, localCenterB));
  
  					// PositionSolverManifold
  					var normal, point, separation;
  					switch (this.p_type) {
  						case Manifold.e_circles:
  							var pointA = Transform.mulVec2(xfA, this.p_localPoint);
  							var pointB = Transform.mulVec2(xfB, this.p_localPoints[0]);
  							normal = Vec2.sub(pointB, pointA);
  							normal.normalize();
  							point = Vec2.combine(0.5, pointA, 0.5, pointB);
  							separation = Vec2.dot(Vec2.sub(pointB, pointA), normal) - this.p_radiusA - this.p_radiusB;
  							break;
  
  						case Manifold.e_faceA:
  							normal = Rot.mulVec2(xfA.q, this.p_localNormal);
  							var planePoint = Transform.mulVec2(xfA, this.p_localPoint);
  							var clipPoint = Transform.mulVec2(xfB, this.p_localPoints[j]);
  							separation = Vec2.dot(Vec2.sub(clipPoint, planePoint), normal) - this.p_radiusA - this.p_radiusB;
  							point = clipPoint;
  							break;
  
  						case Manifold.e_faceB:
  							normal = Rot.mulVec2(xfB.q, this.p_localNormal);
  							var planePoint = Transform.mulVec2(xfB, this.p_localPoint);
  							var clipPoint = Transform.mulVec2(xfA, this.p_localPoints[j]);
  							separation = Vec2.dot(Vec2.sub(clipPoint, planePoint), normal) - this.p_radiusA - this.p_radiusB;
  							point = clipPoint;
  
  							// Ensure normal points from A to B
  							normal.mul(-1);
  							break;
  					}
  
  					var rA = Vec2.sub(point, cA);
  					var rB = Vec2.sub(point, cB);
  
  					// Track max constraint error.
  					minSeparation = Math.min(minSeparation, separation);
  
  					var baumgarte = toi ? Settings.toiBaugarte : Settings.baumgarte;
  					var linearSlop = Settings.linearSlop;
  					var maxLinearCorrection = Settings.maxLinearCorrection;
  
  					// Prevent large corrections and allow slop.
  					var C = Math.clamp(baumgarte * (separation + linearSlop), -maxLinearCorrection, 0.0);
  
  					// Compute the effective mass.
  					var rnA = Vec2.cross(rA, normal);
  					var rnB = Vec2.cross(rB, normal);
  					var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
  
  					// Compute normal impulse
  					var impulse = K > 0.0 ? -C / K : 0.0;
  
  					var P = Vec2.mul(impulse, normal);
  
  					cA.subMul(mA, P);
  					aA -= iA * Vec2.cross(rA, P);
  
  					cB.addMul(mB, P);
  					aB += iB * Vec2.cross(rB, P);
  				}
  
  				positionA.c.set(cA);
  				positionA.a = aA;
  
  				positionB.c.set(cB);
  				positionB.a = aB;
  
  				return minSeparation;
  			};
  
  			// TODO merge with ManifoldPoint
  			function VelocityConstraintPoint () {
  				this.rA = Vec2.zero();
  				this.rB = Vec2.zero();
  				this.normalImpulse = 0;
  				this.tangentImpulse = 0;
  				this.normalMass = 0;
  				this.tangentMass = 0;
  				this.velocityBias = 0;
  			}
  
  			Contact.prototype.initVelocityConstraint = function (step) {
  				var fixtureA = this.m_fixtureA;
  				var fixtureB = this.m_fixtureB;
  
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				var velocityA = bodyA.c_velocity;
  				var velocityB = bodyB.c_velocity;
  
  				var positionA = bodyA.c_position;
  				var positionB = bodyB.c_position;
  
  				var radiusA = this.p_radiusA;
  				var radiusB = this.p_radiusB;
  				var manifold = this.getManifold();
  
  				var mA = this.v_invMassA;
  				var mB = this.v_invMassB;
  				var iA = this.v_invIA;
  				var iB = this.v_invIB;
  				var localCenterA = Vec2.clone(this.p_localCenterA);
  				var localCenterB = Vec2.clone(this.p_localCenterB);
  
  				var cA = Vec2.clone(positionA.c);
  				var aA = positionA.a;
  				var vA = Vec2.clone(velocityA.v);
  				var wA = velocityA.w;
  
  				var cB = Vec2.clone(positionB.c);
  				var aB = positionB.a;
  				var vB = Vec2.clone(velocityB.v);
  				var wB = velocityB.w;
  
  				_ASSERT && common.assert(manifold.pointCount > 0);
  
  				var xfA = Transform.identity();
  				var xfB = Transform.identity();
  				xfA.q.set(aA);
  				xfB.q.set(aB);
  				xfA.p.setCombine(1, cA, -1, Rot.mulVec2(xfA.q, localCenterA));
  				xfB.p.setCombine(1, cB, -1, Rot.mulVec2(xfB.q, localCenterB));
  
  				var worldManifold = manifold.getWorldManifold(null, xfA, radiusA, xfB, radiusB);
  
  				this.v_normal.set(worldManifold.normal);
  
  				for (var j = 0; j < this.v_pointCount; ++j) {
  					var vcp = this.v_points[j]; // VelocityConstraintPoint
  
  					vcp.rA.set(Vec2.sub(worldManifold.points[j], cA));
  					vcp.rB.set(Vec2.sub(worldManifold.points[j], cB));
  
  					var rnA = Vec2.cross(vcp.rA, this.v_normal);
  					var rnB = Vec2.cross(vcp.rB, this.v_normal);
  
  					var kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
  
  					vcp.normalMass = kNormal > 0.0 ? 1.0 / kNormal : 0.0;
  
  					var tangent = Vec2.cross(this.v_normal, 1.0);
  
  					var rtA = Vec2.cross(vcp.rA, tangent);
  					var rtB = Vec2.cross(vcp.rB, tangent);
  
  					var kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB;
  
  					vcp.tangentMass = kTangent > 0.0 ? 1.0 / kTangent : 0.0;
  
  					// Setup a velocity bias for restitution.
  					vcp.velocityBias = 0.0;
  					var vRel = Vec2.dot(this.v_normal, vB) + Vec2.dot(this.v_normal, Vec2.cross(wB, vcp.rB)) - Vec2.dot(this.v_normal, vA) - Vec2.dot(this.v_normal, Vec2.cross(wA, vcp.rA));
  					if (vRel < -Settings.velocityThreshold) {
  						vcp.velocityBias = -this.v_restitution * vRel;
  					}
  				}
  
  				// If we have two points, then prepare the block solver.
  				if (this.v_pointCount == 2 && step.blockSolve) {
  					var vcp1 = this.v_points[0]; // VelocityConstraintPoint
  					var vcp2 = this.v_points[1]; // VelocityConstraintPoint
  
  					var rn1A = Vec2.cross(vcp1.rA, this.v_normal);
  					var rn1B = Vec2.cross(vcp1.rB, this.v_normal);
  					var rn2A = Vec2.cross(vcp2.rA, this.v_normal);
  					var rn2B = Vec2.cross(vcp2.rB, this.v_normal);
  
  					var k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B;
  					var k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B;
  					var k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B;
  
  					// Ensure a reasonable condition number.
  					var k_maxConditionNumber = 1000.0;
  					if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) {
  						// K is safe to invert.
  						this.v_K.ex.set(k11, k12);
  						this.v_K.ey.set(k12, k22);
  						this.v_normalMass.set(this.v_K.getInverse());
  					} else {
  						// The constraints are redundant, just use one.
  						// TODO_ERIN use deepest?
  						this.v_pointCount = 1;
  					}
  				}
  
  				positionA.c.set(cA);
  				positionA.a = aA;
  				velocityA.v.set(vA);
  				velocityA.w = wA;
  
  				positionB.c.set(cB);
  				positionB.a = aB;
  				velocityB.v.set(vB);
  				velocityB.w = wB;
  			};
  
  			Contact.prototype.warmStartConstraint = function (step) {
  				var fixtureA = this.m_fixtureA;
  				var fixtureB = this.m_fixtureB;
  
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				var velocityA = bodyA.c_velocity;
  				var velocityB = bodyB.c_velocity;
  				var positionA = bodyA.c_position;
  				var positionB = bodyB.c_position;
  
  				var mA = this.v_invMassA;
  				var iA = this.v_invIA;
  				var mB = this.v_invMassB;
  				var iB = this.v_invIB;
  
  				var vA = Vec2.clone(velocityA.v);
  				var wA = velocityA.w;
  				var vB = Vec2.clone(velocityB.v);
  				var wB = velocityB.w;
  
  				var normal = this.v_normal;
  				var tangent = Vec2.cross(normal, 1.0);
  
  				for (var j = 0; j < this.v_pointCount; ++j) {
  					var vcp = this.v_points[j]; // VelocityConstraintPoint
  
  					var P = Vec2.combine(vcp.normalImpulse, normal, vcp.tangentImpulse, tangent);
  					wA -= iA * Vec2.cross(vcp.rA, P);
  					vA.subMul(mA, P);
  					wB += iB * Vec2.cross(vcp.rB, P);
  					vB.addMul(mB, P);
  				}
  
  				velocityA.v.set(vA);
  				velocityA.w = wA;
  				velocityB.v.set(vB);
  				velocityB.w = wB;
  			};
  
  			Contact.prototype.storeConstraintImpulses = function (step) {
  				var manifold = this.m_manifold;
  				for (var j = 0; j < this.v_pointCount; ++j) {
  					manifold.points[j].normalImpulse = this.v_points[j].normalImpulse;
  					manifold.points[j].tangentImpulse = this.v_points[j].tangentImpulse;
  				}
  			};
  
  			Contact.prototype.solveVelocityConstraint = function (step) {
  				var bodyA = this.m_fixtureA.m_body;
  				var bodyB = this.m_fixtureB.m_body;
  
  				var velocityA = bodyA.c_velocity;
  				var positionA = bodyA.c_position;
  
  				var velocityB = bodyB.c_velocity;
  				var positionB = bodyB.c_position;
  
  				var mA = this.v_invMassA;
  				var iA = this.v_invIA;
  				var mB = this.v_invMassB;
  				var iB = this.v_invIB;
  
  				var vA = Vec2.clone(velocityA.v);
  				var wA = velocityA.w;
  				var vB = Vec2.clone(velocityB.v);
  				var wB = velocityB.w;
  
  				var normal = this.v_normal;
  				var tangent = Vec2.cross(normal, 1.0);
  				var friction = this.v_friction;
  
  				_ASSERT && common.assert(this.v_pointCount == 1 || this.v_pointCount == 2);
  
  				// Solve tangent constraints first because non-penetration is more important
  				// than friction.
  				for (var j = 0; j < this.v_pointCount; ++j) {
  					var vcp = this.v_points[j]; // VelocityConstraintPoint
  
  					// Relative velocity at contact
  					var dv = Vec2.zero();
  					dv.addCombine(1, vB, 1, Vec2.cross(wB, vcp.rB));
  					dv.subCombine(1, vA, 1, Vec2.cross(wA, vcp.rA));
  
  					// Compute tangent force
  					var vt = Vec2.dot(dv, tangent) - this.v_tangentSpeed;
  					var lambda = vcp.tangentMass * -vt;
  
  					// Clamp the accumulated force
  					var maxFriction = friction * vcp.normalImpulse;
  					var newImpulse = Math.clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction);
  					lambda = newImpulse - vcp.tangentImpulse;
  					vcp.tangentImpulse = newImpulse;
  
  					// Apply contact impulse
  					var P = Vec2.mul(lambda, tangent);
  
  					vA.subMul(mA, P);
  					wA -= iA * Vec2.cross(vcp.rA, P);
  
  					vB.addMul(mB, P);
  					wB += iB * Vec2.cross(vcp.rB, P);
  				}
  
  				// Solve normal constraints
  				if (this.v_pointCount == 1 || step.blockSolve == false) {
  					for (var i = 0; i < this.v_pointCount; ++i) {
  						var vcp = this.v_points[i]; // VelocityConstraintPoint
  
  						// Relative velocity at contact
  						var dv = Vec2.zero();
  						dv.addCombine(1, vB, 1, Vec2.cross(wB, vcp.rB));
  						dv.subCombine(1, vA, 1, Vec2.cross(wA, vcp.rA));
  
  						// Compute normal impulse
  						var vn = Vec2.dot(dv, normal);
  						var lambda = -vcp.normalMass * (vn - vcp.velocityBias);
  
  						// Clamp the accumulated impulse
  						var newImpulse = Math.max(vcp.normalImpulse + lambda, 0.0);
  						lambda = newImpulse - vcp.normalImpulse;
  						vcp.normalImpulse = newImpulse;
  
  						// Apply contact impulse
  						var P = Vec2.mul(lambda, normal);
  
  						vA.subMul(mA, P);
  						wA -= iA * Vec2.cross(vcp.rA, P);
  
  						vB.addMul(mB, P);
  						wB += iB * Vec2.cross(vcp.rB, P);
  					}
  				} else {
  					// Block solver developed in collaboration with Dirk Gregorius (back in
  					// 01/07 on Box2D_Lite).
  					// Build the mini LCP for this contact patch
  					//
  					// vn = A * x + b, vn >= 0, , vn >= 0, x >= 0 and vn_i * x_i = 0 with i =
  					// 1..2
  					//
  					// A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n )
  					// b = vn0 - velocityBias
  					//
  					// The system is solved using the "Total enumeration method" (s. Murty).
  					// The complementary constraint vn_i * x_i
  					// implies that we must have in any solution either vn_i = 0 or x_i = 0.
  					// So for the 2D contact problem the cases
  					// vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and
  					// vn1 = 0 need to be tested. The first valid
  					// solution that satisfies the problem is chosen.
  					//
  					// In order to account of the accumulated impulse 'a' (because of the
  					// iterative nature of the solver which only requires
  					// that the accumulated impulse is clamped and not the incremental
  					// impulse) we change the impulse variable (x_i).
  					//
  					// Substitute:
  					//
  					// x = a + d
  					//
  					// a := old total impulse
  					// x := new total impulse
  					// d := incremental impulse
  					//
  					// For the current iteration we extend the formula for the incremental
  					// impulse
  					// to compute the new total impulse:
  					//
  					// vn = A * d + b
  					// = A * (x - a) + b
  					// = A * x + b - A * a
  					// = A * x + b'
  					// b' = b - A * a;
  
  					var vcp1 = this.v_points[0]; // VelocityConstraintPoint
  					var vcp2 = this.v_points[1]; // VelocityConstraintPoint
  
  					var a = Vec2.neo(vcp1.normalImpulse, vcp2.normalImpulse);
  					_ASSERT && common.assert(a.x >= 0.0 && a.y >= 0.0);
  
  					// Relative velocity at contact
  					var dv1 = Vec2.zero().add(vB).add(Vec2.cross(wB, vcp1.rB)).sub(vA).sub(Vec2.cross(wA, vcp1.rA));
  					var dv2 = Vec2.zero().add(vB).add(Vec2.cross(wB, vcp2.rB)).sub(vA).sub(Vec2.cross(wA, vcp2.rA));
  
  					// Compute normal velocity
  					var vn1 = Vec2.dot(dv1, normal);
  					var vn2 = Vec2.dot(dv2, normal);
  
  					var b = Vec2.neo(vn1 - vcp1.velocityBias, vn2 - vcp2.velocityBias);
  
  					// Compute b'
  					b.sub(Mat22.mulVec2(this.v_K, a));
  
  					var k_errorTol = 1e-3;
  					// NOT_USED(k_errorTol);
  
  					for (;;) {
  						//
  						// Case 1: vn = 0
  						//
  						// 0 = A * x + b'
  						//
  						// Solve for x:
  						//
  						// x = - inv(A) * b'
  						//
  						var x = Mat22.mulVec2(this.v_normalMass, b).neg();
  
  						if (x.x >= 0.0 && x.y >= 0.0) {
  							// Get the incremental impulse
  							var d = Vec2.sub(x, a);
  
  							// Apply incremental impulse
  							var P1 = Vec2.mul(d.x, normal);
  							var P2 = Vec2.mul(d.y, normal);
  
  							vA.subCombine(mA, P1, mA, P2);
  							wA -= iA * (Vec2.cross(vcp1.rA, P1) + Vec2.cross(vcp2.rA, P2));
  
  							vB.addCombine(mB, P1, mB, P2);
  							wB += iB * (Vec2.cross(vcp1.rB, P1) + Vec2.cross(vcp2.rB, P2));
  
  							// Accumulate
  							vcp1.normalImpulse = x.x;
  							vcp2.normalImpulse = x.y;
  
  							if (DEBUG_SOLVER) {
  								// Postconditions
  								dv1 = vB + Vec2.cross(wB, vcp1.rB) - vA - Vec2.cross(wA, vcp1.rA);
  								dv2 = vB + Vec2.cross(wB, vcp2.rB) - vA - Vec2.cross(wA, vcp2.rA);
  
  								// Compute normal velocity
  								vn1 = Dot(dv1, normal);
  								vn2 = Dot(dv2, normal);
  
  								_ASSERT && common.assert(Abs(vn1 - vcp1.velocityBias) < k_errorTol);
  								_ASSERT && common.assert(Abs(vn2 - vcp2.velocityBias) < k_errorTol);
  							}
  							break;
  						}
  
  						//
  						// Case 2: vn1 = 0 and x2 = 0
  						//
  						// 0 = a11 * x1 + a12 * 0 + b1'
  						// vn2 = a21 * x1 + a22 * 0 + b2'
  						//
  						x.x = -vcp1.normalMass * b.x;
  						x.y = 0.0;
  						vn1 = 0.0;
  						vn2 = this.v_K.ex.y * x.x + b.y;
  
  						if (x.x >= 0.0 && vn2 >= 0.0) {
  							// Get the incremental impulse
  							var d = Vec2.sub(x, a);
  
  							// Apply incremental impulse
  							var P1 = Vec2.mul(d.x, normal);
  							var P2 = Vec2.mul(d.y, normal);
  							vA.subCombine(mA, P1, mA, P2);
  							wA -= iA * (Vec2.cross(vcp1.rA, P1) + Vec2.cross(vcp2.rA, P2));
  
  							vB.addCombine(mB, P1, mB, P2);
  							wB += iB * (Vec2.cross(vcp1.rB, P1) + Vec2.cross(vcp2.rB, P2));
  
  							// Accumulate
  							vcp1.normalImpulse = x.x;
  							vcp2.normalImpulse = x.y;
  
  							if (DEBUG_SOLVER) {
  								// Postconditions
  								var dv1B = Vec2.add(vB, Vec2.cross(wB, vcp1.rB));
  								var dv1A = Vec2.add(vA, Vec2.cross(wA, vcp1.rA));
  								var dv1 = Vec2.sub(dv1B, dv1A);
  
  								// Compute normal velocity
  								vn1 = Vec2.dot(dv1, normal);
  
  								_ASSERT && common.assert(Math.abs(vn1 - vcp1.velocityBias) < k_errorTol);
  							}
  							break;
  						}
  
  						//
  						// Case 3: vn2 = 0 and x1 = 0
  						//
  						// vn1 = a11 * 0 + a12 * x2 + b1'
  						// 0 = a21 * 0 + a22 * x2 + b2'
  						//
  						x.x = 0.0;
  						x.y = -vcp2.normalMass * b.y;
  						vn1 = this.v_K.ey.x * x.y + b.x;
  						vn2 = 0.0;
  
  						if (x.y >= 0.0 && vn1 >= 0.0) {
  							// Resubstitute for the incremental impulse
  							var d = Vec2.sub(x, a);
  
  							// Apply incremental impulse
  							var P1 = Vec2.mul(d.x, normal);
  							var P2 = Vec2.mul(d.y, normal);
  							vA.subCombine(mA, P1, mA, P2);
  							wA -= iA * (Vec2.cross(vcp1.rA, P1) + Vec2.cross(vcp2.rA, P2));
  
  							vB.addCombine(mB, P1, mB, P2);
  							wB += iB * (Vec2.cross(vcp1.rB, P1) + Vec2.cross(vcp2.rB, P2));
  
  							// Accumulate
  							vcp1.normalImpulse = x.x;
  							vcp2.normalImpulse = x.y;
  
  							if (DEBUG_SOLVER) {
  								// Postconditions
  								var dv2B = Vec2.add(vB, Vec2.cross(wB, vcp2.rB));
  								var dv2A = Vec2.add(vA, Vec2.cross(wA, vcp2.rA));
  								var dv1 = Vec2.sub(dv2B, dv2A);
  
  								// Compute normal velocity
  								vn2 = Vec2.dot(dv2, normal);
  
  								_ASSERT && common.assert(Math.abs(vn2 - vcp2.velocityBias) < k_errorTol);
  							}
  							break;
  						}
  
  						//
  						// Case 4: x1 = 0 and x2 = 0
  						//
  						// vn1 = b1
  						// vn2 = b2;
  						//
  						x.x = 0.0;
  						x.y = 0.0;
  						vn1 = b.x;
  						vn2 = b.y;
  
  						if (vn1 >= 0.0 && vn2 >= 0.0) {
  							// Resubstitute for the incremental impulse
  							var d = Vec2.sub(x, a);
  
  							// Apply incremental impulse
  							var P1 = Vec2.mul(d.x, normal);
  							var P2 = Vec2.mul(d.y, normal);
  							vA.subCombine(mA, P1, mA, P2);
  							wA -= iA * (Vec2.cross(vcp1.rA, P1) + Vec2.cross(vcp2.rA, P2));
  
  							vB.addCombine(mB, P1, mB, P2);
  							wB += iB * (Vec2.cross(vcp1.rB, P1) + Vec2.cross(vcp2.rB, P2));
  
  							// Accumulate
  							vcp1.normalImpulse = x.x;
  							vcp2.normalImpulse = x.y;
  
  							break;
  						}
  
  						// No solution, give up. This is hit sometimes, but it doesn't seem to
  						// matter.
  						break;
  					}
  				}
  
  				velocityA.v.set(vA);
  				velocityA.w = wA;
  
  				velocityB.v.set(vB);
  				velocityB.w = wB;
  			};
  
  			/**
               * Friction mixing law. The idea is to allow either fixture to drive the
               * restitution to zero. For example, anything slides on ice.
               */
  			function mixFriction (friction1, friction2) {
  				return Math.sqrt(friction1 * friction2);
  			}
  
  			/**
               * Restitution mixing law. The idea is allow for anything to bounce off an
               * inelastic surface. For example, a superball bounces on anything.
               */
  			function mixRestitution (restitution1, restitution2) {
  				return restitution1 > restitution2 ? restitution1 : restitution2;
  			}
  
  			var s_registers = [];
  
  			/**
               * @param fn function(fixtureA, indexA, fixtureB, indexB) Contact
               */
  			Contact.addType = function (type1, type2, callback) {
  				s_registers[type1] = s_registers[type1] || {};
  				s_registers[type1][type2] = callback;
  			};
  
  			Contact.create = function (fixtureA, indexA, fixtureB, indexB) {
  				var typeA = fixtureA.getType(); // Shape.Type
  				var typeB = fixtureB.getType(); // Shape.Type
  
  				// TODO: pool contacts
  				var contact, evaluateFcn;
  				if ((evaluateFcn = s_registers[typeA] && s_registers[typeA][typeB])) {
  					contact = new Contact(fixtureA, indexA, fixtureB, indexB, evaluateFcn);
  				} else if ((evaluateFcn = s_registers[typeB] && s_registers[typeB][typeA])) {
  					contact = new Contact(fixtureB, indexB, fixtureA, indexA, evaluateFcn);
  				} else {
  					return null;
  				}
  
  				// Contact creation may swap fixtures.
  				fixtureA = contact.getFixtureA();
  				fixtureB = contact.getFixtureB();
  				indexA = contact.getChildIndexA();
  				indexB = contact.getChildIndexB();
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				// Connect to body A
  				contact.m_nodeA.contact = contact;
  				contact.m_nodeA.other = bodyB;
  
  				contact.m_nodeA.prev = null;
  				contact.m_nodeA.next = bodyA.m_contactList;
  				if (bodyA.m_contactList != null) {
  					bodyA.m_contactList.prev = contact.m_nodeA;
  				}
  				bodyA.m_contactList = contact.m_nodeA;
  
  				// Connect to body B
  				contact.m_nodeB.contact = contact;
  				contact.m_nodeB.other = bodyA;
  
  				contact.m_nodeB.prev = null;
  				contact.m_nodeB.next = bodyB.m_contactList;
  				if (bodyB.m_contactList != null) {
  					bodyB.m_contactList.prev = contact.m_nodeB;
  				}
  				bodyB.m_contactList = contact.m_nodeB;
  
  				// Wake up the bodies
  				if (fixtureA.isSensor() == false && fixtureB.isSensor() == false) {
  					bodyA.setAwake(true);
  					bodyB.setAwake(true);
  				}
  
  				return contact;
  			};
  
  			Contact.destroy = function (contact, listener) {
  				var fixtureA = contact.m_fixtureA;
  				var fixtureB = contact.m_fixtureB;
  
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				if (contact.isTouching()) {
  					listener.endContact(contact);
  				}
  
  				// Remove from body 1
  				if (contact.m_nodeA.prev) {
  					contact.m_nodeA.prev.next = contact.m_nodeA.next;
  				}
  
  				if (contact.m_nodeA.next) {
  					contact.m_nodeA.next.prev = contact.m_nodeA.prev;
  				}
  
  				if (contact.m_nodeA == bodyA.m_contactList) {
  					bodyA.m_contactList = contact.m_nodeA.next;
  				}
  
  				// Remove from body 2
  				if (contact.m_nodeB.prev) {
  					contact.m_nodeB.prev.next = contact.m_nodeB.next;
  				}
  
  				if (contact.m_nodeB.next) {
  					contact.m_nodeB.next.prev = contact.m_nodeB.prev;
  				}
  
  				if (contact.m_nodeB == bodyB.m_contactList) {
  					bodyB.m_contactList = contact.m_nodeB.next;
  				}
  
  				if (contact.m_manifold.pointCount > 0 && fixtureA.isSensor() == false && fixtureB.isSensor() == false) {
  					bodyA.setAwake(true);
  					bodyB.setAwake(true);
  				}
  
  				var typeA = fixtureA.getType(); // Shape.Type
  				var typeB = fixtureB.getType(); // Shape.Type
  
  				var destroyFcn = s_registers[typeA][typeB].destroyFcn;
  				if (typeof destroyFcn === 'function') {
  					destroyFcn(contact);
  				}
  			};
  
  			/***/
  		},
  		/* 19 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  
  			var Vec2 = __webpack_require__(0);
  			var Transform = __webpack_require__(5);
  			var Math = __webpack_require__(1);
  			var Rot = __webpack_require__(3);
  
  			module.exports = Manifold;
  			module.exports.clipSegmentToLine = clipSegmentToLine;
  			module.exports.clipVertex = ClipVertex;
  			module.exports.getPointStates = getPointStates;
  			module.exports.PointState = PointState;
  
  			// Manifold Type
  			Manifold.e_circles = 0;
  			Manifold.e_faceA = 1;
  			Manifold.e_faceB = 2;
  
  			// ContactFeature Type
  			Manifold.e_vertex = 0;
  			Manifold.e_face = 1;
  
  			/**
               * A manifold for two touching convex shapes. Manifolds are created in `evaluate`
               * method of Contact subclasses.
               *
               * Supported manifold types are e_faceA or e_faceB for clip point versus plane
               * with radius and e_circles point versus point with radius.
               *
               * We store contacts in this way so that position correction can account for
               * movement, which is critical for continuous physics. All contact scenarios
               * must be expressed in one of these types. This structure is stored across time
               * steps, so we keep it small.
               *
               * @prop type e_circle, e_faceA, e_faceB
               * @prop localPoint Usage depends on manifold type:<br>
               *       e_circles: the local center of circleA <br>
               *       e_faceA: the center of faceA <br>
               *       e_faceB: the center of faceB
               * @prop localNormal Usage depends on manifold type:<br>
               *       e_circles: not used <br>
               *       e_faceA: the normal on polygonA <br>
               *       e_faceB: the normal on polygonB
               * @prop points The points of contact {ManifoldPoint[]}
               * @prop pointCount The number of manifold points
               */
  			function Manifold () {
  				this.type;
  				this.localNormal = Vec2.zero();
  				this.localPoint = Vec2.zero();
  				this.points = [new ManifoldPoint(), new ManifoldPoint()];
  				this.pointCount = 0;
  			}
  
  			/**
               * A manifold point is a contact point belonging to a contact manifold. It holds
               * details related to the geometry and dynamics of the contact points.
               *
               * This structure is stored across time steps, so we keep it small.
               *
               * Note: impulses are used for internal caching and may not provide reliable
               * contact forces, especially for high speed collisions.
               *
               * @prop {Vec2} localPoint Usage depends on manifold type:<br>
               *       e_circles: the local center of circleB<br>
               *       e_faceA: the local center of cirlceB or the clip point of polygonB<br>
               *       e_faceB: the clip point of polygonA.
               * @prop normalImpulse The non-penetration impulse
               * @prop tangentImpulse The friction impulse
               * @prop {ContactID} id Uniquely identifies a contact point between two shapes
               *       to facilatate warm starting
               */
  			function ManifoldPoint () {
  				this.localPoint = Vec2.zero();
  				this.normalImpulse = 0;
  				this.tangentImpulse = 0;
  				this.id = new ContactID();
  			}
  
  			/**
               * Contact ids to facilitate warm starting.
               *
               * @prop {ContactFeature} cf
               * @prop key Used to quickly compare contact ids.
               *
               */
  			function ContactID () {
  				this.cf = new ContactFeature();
  			}
  
  			Object.defineProperty(ContactID.prototype, 'key', {
  				get: function () {
  					return this.cf.indexA + this.cf.indexB * 4 + this.cf.typeA * 16 + this.cf.typeB * 64;
  				},
  				enumerable: true,
  				configurable: true
  			});
  
  			ContactID.prototype.set = function (o) {
  				// this.key = o.key;
  				this.cf.set(o.cf);
  			};
  
  			/**
               * The features that intersect to form the contact point.
               *
               * @prop indexA Feature index on shapeA
               * @prop indexB Feature index on shapeB
               * @prop typeA The feature type on shapeA
               * @prop typeB The feature type on shapeB
               */
  			function ContactFeature () {
  				this.indexA;
  				this.indexB;
  				this.typeA;
  				this.typeB;
  			}
  
  			ContactFeature.prototype.set = function (o) {
  				this.indexA = o.indexA;
  				this.indexB = o.indexB;
  				this.typeA = o.typeA;
  				this.typeB = o.typeB;
  			};
  
  			/**
               * This is used to compute the current state of a contact manifold.
               *
               * @prop normal World vector pointing from A to B
               * @prop points World contact point (point of intersection)
               * @prop separations A negative value indicates overlap, in meters
               */
  			function WorldManifold () {
  				this.normal;
  				this.points = []; // [maxManifoldPoints]
  				this.separations = []; // float[maxManifoldPoints]
  			}
  
  			/**
               * Evaluate the manifold with supplied transforms. This assumes modest motion
               * from the original state. This does not change the point count, impulses, etc.
               * The radii must come from the shapes that generated the manifold.
               *
               * @param {WorldManifold} [wm]
               */
  			Manifold.prototype.getWorldManifold = function (wm, xfA, radiusA, xfB, radiusB) {
  				if (this.pointCount == 0) {
  					return;
  				}
  
  				wm = wm || new WorldManifold();
  
  				var normal = wm.normal;
  				var points = wm.points;
  				var separations = wm.separations;
  
  				// TODO: improve
  				switch (this.type) {
  					case Manifold.e_circles:
  						normal = Vec2.neo(1.0, 0.0);
  						var pointA = Transform.mulVec2(xfA, this.localPoint);
  						var pointB = Transform.mulVec2(xfB, this.points[0].localPoint);
  						var dist = Vec2.sub(pointB, pointA);
  						if (Vec2.lengthSquared(dist) > Math.EPSILON * Math.EPSILON) {
  							normal.set(dist);
  							normal.normalize();
  						}
  						var cA = pointA.clone().addMul(radiusA, normal);
  						var cB = pointB.clone().addMul(-radiusB, normal);
  						points[0] = Vec2.mid(cA, cB);
  						separations[0] = Vec2.dot(Vec2.sub(cB, cA), normal);
  						points.length = 1;
  						separations.length = 1;
  						break;
  
  					case Manifold.e_faceA:
  						normal = Rot.mulVec2(xfA.q, this.localNormal);
  						var planePoint = Transform.mulVec2(xfA, this.localPoint);
  
  						for (var i = 0; i < this.pointCount; ++i) {
  							var clipPoint = Transform.mulVec2(xfB, this.points[i].localPoint);
  							var cA = Vec2.clone(clipPoint).addMul(radiusA - Vec2.dot(Vec2.sub(clipPoint, planePoint), normal), normal);
  							var cB = Vec2.clone(clipPoint).subMul(radiusB, normal);
  							points[i] = Vec2.mid(cA, cB);
  							separations[i] = Vec2.dot(Vec2.sub(cB, cA), normal);
  						}
  						points.length = this.pointCount;
  						separations.length = this.pointCount;
  						break;
  
  					case Manifold.e_faceB:
  						normal = Rot.mulVec2(xfB.q, this.localNormal);
  						var planePoint = Transform.mulVec2(xfB, this.localPoint);
  
  						for (var i = 0; i < this.pointCount; ++i) {
  							var clipPoint = Transform.mulVec2(xfA, this.points[i].localPoint);
  							var cB = Vec2.combine(1, clipPoint, radiusB - Vec2.dot(Vec2.sub(clipPoint, planePoint), normal), normal);
  							var cA = Vec2.combine(1, clipPoint, -radiusA, normal);
  							points[i] = Vec2.mid(cA, cB);
  							separations[i] = Vec2.dot(Vec2.sub(cA, cB), normal);
  						}
  						points.length = this.pointCount;
  						separations.length = this.pointCount;
  						// Ensure normal points from A to B.
  						normal.mul(-1);
  						break;
  				}
  
  				wm.normal = normal;
  				wm.points = points;
  				wm.separations = separations;
  				return wm;
  			};
  
  			/**
               * This is used for determining the state of contact points.
               *
               * @prop {0} nullState Point does not exist
               * @prop {1} addState Point was added in the update
               * @prop {2} persistState Point persisted across the update
               * @prop {3} removeState Point was removed in the update
               */
  			var PointState = {
  				// TODO: use constants
  				nullState: 0,
  				addState: 1,
  				persistState: 2,
  				removeState: 3
  			};
  
  			/**
               * Compute the point states given two manifolds. The states pertain to the
               * transition from manifold1 to manifold2. So state1 is either persist or remove
               * while state2 is either add or persist.
               *
               * @param {PointState[Settings.maxManifoldPoints]} state1
               * @param {PointState[Settings.maxManifoldPoints]} state2
               */
  			function getPointStates (state1, state2, manifold1, manifold2) {
  				// for (var i = 0; i < Settings.maxManifoldPoints; ++i) {
  				// state1[i] = PointState.nullState;
  				// state2[i] = PointState.nullState;
  				// }
  
  				// Detect persists and removes.
  				for (var i = 0; i < manifold1.pointCount; ++i) {
  					var id = manifold1.points[i].id; // ContactID
  
  					state1[i] = PointState.removeState;
  
  					for (var j = 0; j < manifold2.pointCount; ++j) {
  						if (manifold2.points[j].id.key == id.key) {
  							state1[i] = PointState.persistState;
  							break;
  						}
  					}
  				}
  
  				// Detect persists and adds.
  				for (var i = 0; i < manifold2.pointCount; ++i) {
  					var id = manifold2.points[i].id; // ContactID
  
  					state2[i] = PointState.addState;
  
  					for (var j = 0; j < manifold1.pointCount; ++j) {
  						if (manifold1.points[j].id.key == id.key) {
  							state2[i] = PointState.persistState;
  							break;
  						}
  					}
  				}
  			}
  
  			/**
               * Used for computing contact manifolds.
               *
               * @prop {Vec2} v
               * @prop {ContactID} id
               */
  			function ClipVertex () {
  				this.v = Vec2.zero();
  				this.id = new ContactID();
  			}
  
  			ClipVertex.prototype.set = function (o) {
  				this.v.set(o.v);
  				this.id.set(o.id);
  			};
  
  			/**
               * Clipping for contact manifolds. Sutherland-Hodgman clipping.
               *
               * @param {ClipVertex[2]} vOut
               * @param {ClipVertex[2]} vIn
               */
  			function clipSegmentToLine (vOut, vIn, normal, offset, vertexIndexA) {
  				// Start with no output points
  				var numOut = 0;
  
  				// Calculate the distance of end points to the line
  				var distance0 = Vec2.dot(normal, vIn[0].v) - offset;
  				var distance1 = Vec2.dot(normal, vIn[1].v) - offset;
  
  				// If the points are behind the plane
  				if (distance0 <= 0.0) vOut[numOut++].set(vIn[0]);
  				if (distance1 <= 0.0) vOut[numOut++].set(vIn[1]);
  
  				// If the points are on different sides of the plane
  				if (distance0 * distance1 < 0.0) {
  					// Find intersection point of edge and plane
  					var interp = distance0 / (distance0 - distance1);
  					vOut[numOut].v.setCombine(1 - interp, vIn[0].v, interp, vIn[1].v);
  
  					// VertexA is hitting edgeB.
  					vOut[numOut].id.cf.indexA = vertexIndexA;
  					vOut[numOut].id.cf.indexB = vIn[0].id.cf.indexB;
  					vOut[numOut].id.cf.typeA = Manifold.e_vertex;
  					vOut[numOut].id.cf.typeB = Manifold.e_face;
  					++numOut;
  				}
  
  				return numOut;
  			}
  
  			/***/
  		}, /* 21 */,
  		/* 20 */ /***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = PolygonShape;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var options = __webpack_require__(7);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Rot = __webpack_require__(3);
  			var Vec2 = __webpack_require__(0);
  			var AABB = __webpack_require__(17);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  
  			PolygonShape._super = Shape;
  			PolygonShape.prototype = create(PolygonShape._super.prototype);
  
  			PolygonShape.TYPE = 'polygon';
  			Shape.TYPES[PolygonShape.TYPE] = PolygonShape;
  
  			/**
               * A convex polygon. It is assumed that the interior of the polygon is to the
               * left of each edge. Polygons have a maximum number of vertices equal to
               * Settings.maxPolygonVertices. In most cases you should not need many vertices
               * for a convex polygon. extends Shape
               */
  			function PolygonShape (vertices) {
  				if (!(this instanceof PolygonShape)) {
  					return new PolygonShape(vertices);
  				}
  
  				PolygonShape._super.call(this);
  
  				this.m_type = PolygonShape.TYPE;
  				this.m_radius = Settings.polygonRadius;
  				this.m_centroid = Vec2.zero();
  				this.m_vertices = []; // Vec2[Settings.maxPolygonVertices]
  				this.m_normals = []; // Vec2[Settings.maxPolygonVertices]
  				this.m_count = 0;
  
  				if (vertices && vertices.length) {
  					this._set(vertices);
  				}
  			}
  
  			PolygonShape.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  
  					vertices: this.m_vertices
  				};
  			};
  
  			PolygonShape._deserialize = function (data, fixture, restore) {
  				var vertices = data.vertices && data.vertices.map(v => Vec2._deserialize(v));
  				var shape = new PolygonShape(vertices);
  				return shape;
  			};
  
  			PolygonShape.prototype.getVertex = function (index) {
  				_ASSERT && common.assert(index >= 0 && index < this.m_count);
  				return this.m_vertices[index];
  			};
  
  			/**
               * @deprecated
               */
  			PolygonShape.prototype._clone = function () {
  				var clone = new PolygonShape();
  				clone.m_type = this.m_type;
  				clone.m_radius = this.m_radius;
  				clone.m_count = this.m_count;
  				clone.m_centroid.set(this.m_centroid);
  				for (var i = 0; i < this.m_count; i++) {
  					clone.m_vertices.push(this.m_vertices[i].clone());
  				}
  				for (var i = 0; i < this.m_normals.length; i++) {
  					clone.m_normals.push(this.m_normals[i].clone());
  				}
  				return clone;
  			};
  
  			PolygonShape.prototype.getChildCount = function () {
  				return 1;
  			};
  
  			function ComputeCentroid (vs, count) {
  				_ASSERT && common.assert(count >= 3);
  
  				var c = Vec2.zero();
  				var area = 0.0;
  
  				// pRef is the reference point for forming triangles.
  				// It's location doesn't change the result (except for rounding error).
  				var pRef = Vec2.zero();
  				if (false) {
  					var i;
  				}
  
  				var inv3 = 1.0 / 3.0;
  
  				for (var i = 0; i < count; ++i) {
  					// Triangle vertices.
  					var p1 = pRef;
  					var p2 = vs[i];
  					var p3 = i + 1 < count ? vs[i + 1] : vs[0];
  
  					var e1 = Vec2.sub(p2, p1);
  					var e2 = Vec2.sub(p3, p1);
  
  					var D = Vec2.cross(e1, e2);
  
  					var triangleArea = 0.5 * D;
  					area += triangleArea;
  
  					// Area weighted centroid
  					c.addMul(triangleArea * inv3, p1);
  					c.addMul(triangleArea * inv3, p2);
  					c.addMul(triangleArea * inv3, p3);
  				}
  
  				// Centroid
  				_ASSERT && common.assert(area > Math.EPSILON);
  				c.mul(1.0 / area);
  				return c;
  			}
  
  			PolygonShape.prototype._reset = function () {
  				this._set(this.m_vertices);
  			};
  
  			/**
               * @private
               *
               * Create a convex hull from the given array of local points. The count must be
               * in the range [3, Settings.maxPolygonVertices].
               *
               * Warning: the points may be re-ordered, even if they form a convex polygon
               * Warning: collinear points are handled but not removed. Collinear points may
               * lead to poor stacking behavior.
               */
  			PolygonShape.prototype._set = function (vertices) {
  				_ASSERT && common.assert(vertices.length >= 3 && vertices.length <= Settings.maxPolygonVertices);
  				if (vertices.length < 3) {
  					this._setAsBox(1.0, 1.0);
  					return;
  				}
  
  				var n = Math.min(vertices.length, Settings.maxPolygonVertices);
  
  				// Perform welding and copy vertices into local buffer.
  				var ps = []; // [Settings.maxPolygonVertices];
  				for (var i = 0; i < n; ++i) {
  					var v = vertices[i];
  
  					var unique = true;
  					for (var j = 0; j < ps.length; ++j) {
  						if (Vec2.distanceSquared(v, ps[j]) < 0.25 * Settings.linearSlopSquared) {
  							unique = false;
  							break;
  						}
  					}
  
  					if (unique) {
  						ps.push(v);
  					}
  				}
  
  				n = ps.length;
  				if (n < 3) {
  					// Polygon is degenerate.
  					_ASSERT && common.assert(false);
  					this._setAsBox(1.0, 1.0);
  					return;
  				}
  
  				// Create the convex hull using the Gift wrapping algorithm
  				// http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
  
  				// Find the right most point on the hull (in case of multiple points bottom most is used)
  				var i0 = 0;
  				var x0 = ps[0].x;
  				for (var i = 1; i < n; ++i) {
  					var x = ps[i].x;
  					if (x > x0 || (x === x0 && ps[i].y < ps[i0].y)) {
  						i0 = i;
  						x0 = x;
  					}
  				}
  
  				var hull = []; // [Settings.maxPolygonVertices];
  				var m = 0;
  				var ih = i0;
  
  				for (;;) {
  					hull[m] = ih;
  
  					var ie = 0;
  					for (var j = 1; j < n; ++j) {
  						if (ie === ih) {
  							ie = j;
  							continue;
  						}
  
  						var r = Vec2.sub(ps[ie], ps[hull[m]]);
  						var v = Vec2.sub(ps[j], ps[hull[m]]);
  						var c = Vec2.cross(r, v);
  						// c < 0 means counter-clockwise wrapping, c > 0 means clockwise wrapping
  						if (c < 0.0) {
  							ie = j;
  						}
  
  						// Collinearity check
  						if (c === 0.0 && v.lengthSquared() > r.lengthSquared()) {
  							ie = j;
  						}
  					}
  
  					++m;
  					ih = ie;
  
  					if (ie === i0) {
  						break;
  					}
  				}
  
  				if (m < 3) {
  					// Polygon is degenerate.
  					_ASSERT && common.assert(false);
  					this._setAsBox(1.0, 1.0);
  					return;
  				}
  
  				this.m_count = m;
  
  				// Copy vertices.
  				this.m_vertices = [];
  				for (var i = 0; i < m; ++i) {
  					this.m_vertices[i] = ps[hull[i]];
  				}
  
  				// Compute normals. Ensure the edges have non-zero length.
  				for (var i = 0; i < m; ++i) {
  					var i1 = i;
  					var i2 = i + 1 < m ? i + 1 : 0;
  					var edge = Vec2.sub(this.m_vertices[i2], this.m_vertices[i1]);
  					_ASSERT && common.assert(edge.lengthSquared() > Math.EPSILON * Math.EPSILON);
  					this.m_normals[i] = Vec2.cross(edge, 1.0);
  					this.m_normals[i].normalize();
  				}
  
  				// Compute the polygon centroid.
  				this.m_centroid = ComputeCentroid(this.m_vertices, m);
  			};
  
  			/**
               * @private
               */
  			PolygonShape.prototype._setAsBox = function (hx, hy, center, angle) {
  				// start with right-bottom, counter-clockwise, as in Gift wrapping algorithm in PolygonShape._set()
  				this.m_vertices[0] = Vec2.neo(hx, -hy);
  				this.m_vertices[1] = Vec2.neo(hx, hy);
  				this.m_vertices[2] = Vec2.neo(-hx, hy);
  				this.m_vertices[3] = Vec2.neo(-hx, -hy);
  
  				this.m_normals[0] = Vec2.neo(1.0, 0.0);
  				this.m_normals[1] = Vec2.neo(0.0, 1.0);
  				this.m_normals[2] = Vec2.neo(-1.0, 0.0);
  				this.m_normals[3] = Vec2.neo(0.0, -1.0);
  
  				this.m_count = 4;
  
  				if (Vec2.isValid(center)) {
  					angle = angle || 0;
  
  					this.m_centroid.set(center);
  
  					var xf = Transform.identity();
  					xf.p.set(center);
  					xf.q.set(angle);
  
  					// Transform vertices and normals.
  					for (var i = 0; i < this.m_count; ++i) {
  						this.m_vertices[i] = Transform.mulVec2(xf, this.m_vertices[i]);
  						this.m_normals[i] = Rot.mulVec2(xf.q, this.m_normals[i]);
  					}
  				}
  			};
  
  			PolygonShape.prototype.testPoint = function (xf, p) {
  				var pLocal = Rot.mulTVec2(xf.q, Vec2.sub(p, xf.p));
  
  				for (var i = 0; i < this.m_count; ++i) {
  					var dot = Vec2.dot(this.m_normals[i], Vec2.sub(pLocal, this.m_vertices[i]));
  					if (dot > 0.0) {
  						return false;
  					}
  				}
  
  				return true;
  			};
  
  			PolygonShape.prototype.rayCast = function (output, input, xf, childIndex) {
  				// Put the ray into the polygon's frame of reference.
  				var p1 = Rot.mulTVec2(xf.q, Vec2.sub(input.p1, xf.p));
  				var p2 = Rot.mulTVec2(xf.q, Vec2.sub(input.p2, xf.p));
  				var d = Vec2.sub(p2, p1);
  
  				var lower = 0.0;
  				var upper = input.maxFraction;
  
  				var index = -1;
  
  				for (var i = 0; i < this.m_count; ++i) {
  					// p = p1 + a * d
  					// dot(normal, p - v) = 0
  					// dot(normal, p1 - v) + a * dot(normal, d) = 0
  					var numerator = Vec2.dot(this.m_normals[i], Vec2.sub(this.m_vertices[i], p1));
  					var denominator = Vec2.dot(this.m_normals[i], d);
  
  					if (denominator == 0.0) {
  						if (numerator < 0.0) {
  							return false;
  						}
  					} else {
  						// Note: we want this predicate without division:
  						// lower < numerator / denominator, where denominator < 0
  						// Since denominator < 0, we have to flip the inequality:
  						// lower < numerator / denominator <==> denominator * lower > numerator.
  						if (denominator < 0.0 && numerator < lower * denominator) {
  							// Increase lower.
  							// The segment enters this half-space.
  							lower = numerator / denominator;
  							index = i;
  						} else if (denominator > 0.0 && numerator < upper * denominator) {
  							// Decrease upper.
  							// The segment exits this half-space.
  							upper = numerator / denominator;
  						}
  					}
  
  					// The use of epsilon here causes the assert on lower to trip
  					// in some cases. Apparently the use of epsilon was to make edge
  					// shapes work, but now those are handled separately.
  					// if (upper < lower - Math.EPSILON)
  					if (upper < lower) {
  						return false;
  					}
  				}
  
  				_ASSERT && common.assert(lower >= 0.0 && lower <= input.maxFraction);
  
  				if (index >= 0) {
  					output.fraction = lower;
  					output.normal = Rot.mulVec2(xf.q, this.m_normals[index]);
  					return true;
  				}
  
  				return false;
  			};
  
  			PolygonShape.prototype.computeAABB = function (aabb, xf, childIndex) {
  				var minX = Infinity;
  				var minY = Infinity;
  				var maxX = -Infinity;
  				var maxY = -Infinity;
  				for (var i = 0; i < this.m_count; ++i) {
  					var v = Transform.mulVec2(xf, this.m_vertices[i]);
  					minX = Math.min(minX, v.x);
  					maxX = Math.max(maxX, v.x);
  					minY = Math.min(minY, v.y);
  					maxY = Math.max(maxY, v.y);
  				}
  
  				aabb.lowerBound.set(minX, minY);
  				aabb.upperBound.set(maxX, maxY);
  				aabb.extend(this.m_radius);
  			};
  
  			PolygonShape.prototype.computeMass = function (massData, density) {
  				// Polygon mass, centroid, and inertia.
  				// Let rho be the polygon density in mass per unit area.
  				// Then:
  				// mass = rho * int(dA)
  				// centroid.x = (1/mass) * rho * int(x * dA)
  				// centroid.y = (1/mass) * rho * int(y * dA)
  				// I = rho * int((x*x + y*y) * dA)
  				//
  				// We can compute these integrals by summing all the integrals
  				// for each triangle of the polygon. To evaluate the integral
  				// for a single triangle, we make a change of variables to
  				// the (u,v) coordinates of the triangle:
  				// x = x0 + e1x * u + e2x * v
  				// y = y0 + e1y * u + e2y * v
  				// where 0 <= u && 0 <= v && u + v <= 1.
  				//
  				// We integrate u from [0,1-v] and then v from [0,1].
  				// We also need to use the Jacobian of the transformation:
  				// D = cross(e1, e2)
  				//
  				// Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
  				//
  				// The rest of the derivation is handled by computer algebra.
  
  				_ASSERT && common.assert(this.m_count >= 3);
  
  				var center = Vec2.zero();
  				var area = 0.0;
  				var I = 0.0;
  
  				// s is the reference point for forming triangles.
  				// It's location doesn't change the result (except for rounding error).
  				var s = Vec2.zero();
  
  				// This code would put the reference point inside the polygon.
  				for (var i = 0; i < this.m_count; ++i) {
  					s.add(this.m_vertices[i]);
  				}
  				s.mul(1.0 / this.m_count);
  
  				var k_inv3 = 1.0 / 3.0;
  
  				for (var i = 0; i < this.m_count; ++i) {
  					// Triangle vertices.
  					var e1 = Vec2.sub(this.m_vertices[i], s);
  					var e2 = i + 1 < this.m_count ? Vec2.sub(this.m_vertices[i + 1], s) : Vec2.sub(this.m_vertices[0], s);
  
  					var D = Vec2.cross(e1, e2);
  
  					var triangleArea = 0.5 * D;
  					area += triangleArea;
  
  					// Area weighted centroid
  					center.addCombine(triangleArea * k_inv3, e1, triangleArea * k_inv3, e2);
  
  					var ex1 = e1.x;
  					var ey1 = e1.y;
  					var ex2 = e2.x;
  					var ey2 = e2.y;
  
  					var intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
  					var inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;
  
  					I += 0.25 * k_inv3 * D * (intx2 + inty2);
  				}
  
  				// Total mass
  				massData.mass = density * area;
  
  				// Center of mass
  				_ASSERT && common.assert(area > Math.EPSILON);
  				center.mul(1.0 / area);
  				massData.center.setCombine(1, center, 1, s);
  
  				// Inertia tensor relative to the local origin (point s).
  				massData.I = density * I;
  
  				// Shift to center of mass then to original body origin.
  				massData.I += massData.mass * (Vec2.dot(massData.center, massData.center) - Vec2.dot(center, center));
  			};
  
  			// Validate convexity. This is a very time consuming operation.
  			// @returns true if valid
  			PolygonShape.prototype.validate = function () {
  				for (var i = 0; i < this.m_count; ++i) {
  					var i1 = i;
  					var i2 = i < this.m_count - 1 ? i1 + 1 : 0;
  					var p = this.m_vertices[i1];
  					var e = Vec2.sub(this.m_vertices[i2], p);
  
  					for (var j = 0; j < this.m_count; ++j) {
  						if (j == i1 || j == i2) {
  							continue;
  						}
  
  						var v = Vec2.sub(this.m_vertices[j], p);
  						var c = Vec2.cross(e, v);
  						if (c < 0.0) {
  							return false;
  						}
  					}
  				}
  
  				return true;
  			};
  
  			PolygonShape.prototype.computeDistanceProxy = function (proxy) {
  				proxy.m_vertices = this.m_vertices;
  				proxy.m_count = this.m_count;
  				proxy.m_radius = this.m_radius;
  			};
  
  			/***/
  		},
  		/* 22 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Distance;
  
  			module.exports.Input = DistanceInput;
  			module.exports.Output = DistanceOutput;
  			module.exports.Proxy = DistanceProxy;
  			module.exports.Cache = SimplexCache;
  
  			var Settings = __webpack_require__(4);
  			var common = __webpack_require__(2);
  
  			var stats = __webpack_require__(27);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			/**
               * GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates.
               */
  
  			stats.gjkCalls = 0;
  			stats.gjkIters = 0;
  			stats.gjkMaxIters = 0;
  
  			/**
               * Input for Distance. You have to option to use the shape radii in the
               * computation. Even
               */
  			function DistanceInput () {
  				this.proxyA = new DistanceProxy();
  				this.proxyB = new DistanceProxy();
  				this.transformA = null;
  				this.transformB = null;
  				this.useRadii = false;
  			}
  
  			/**
               * Output for Distance.
               *
               * @prop {Vec2} pointA closest point on shapeA
               * @prop {Vec2} pointB closest point on shapeB
               * @prop distance
               * @prop iterations number of GJK iterations used
               */
  			function DistanceOutput () {
  				this.pointA = Vec2.zero();
  				this.pointB = Vec2.zero();
  				this.distance;
  				this.iterations;
  			}
  
  			/**
               * Used to warm start Distance. Set count to zero on first call.
               *
               * @prop {number} metric length or area
               * @prop {array} indexA vertices on shape A
               * @prop {array} indexB vertices on shape B
               * @prop {number} count
               */
  			function SimplexCache () {
  				this.metric = 0;
  				this.indexA = [];
  				this.indexB = [];
  				this.count = 0;
  			}
  
  			/**
               * Compute the closest points between two shapes. Supports any combination of:
               * CircleShape, PolygonShape, EdgeShape. The simplex cache is input/output. On
               * the first call set SimplexCache.count to zero.
               *
               * @param {DistanceOutput} output
               * @param {SimplexCache} cache
               * @param {DistanceInput} input
               */
  			function Distance (output, cache, input) {
  				++stats.gjkCalls;
  
  				var proxyA = input.proxyA;
  				var proxyB = input.proxyB;
  				var xfA = input.transformA;
  				var xfB = input.transformB;
  
  				// Initialize the simplex.
  				var simplex = new Simplex();
  				simplex.readCache(cache, proxyA, xfA, proxyB, xfB);
  
  				// Get simplex vertices as an array.
  				var vertices = simplex.m_v; // SimplexVertex
  				var k_maxIters = Settings.maxDistnceIterations;
  
  				// These store the vertices of the last simplex so that we
  				// can check for duplicates and prevent cycling.
  				var saveA = [];
  				var saveB = []; // int[3]
  				var saveCount = 0;
  
  				var distanceSqr1 = Infinity;
  				var distanceSqr2 = Infinity;
  
  				// Main iteration loop.
  				var iter = 0;
  				while (iter < k_maxIters) {
  					// Copy simplex so we can identify duplicates.
  					saveCount = simplex.m_count;
  					for (var i = 0; i < saveCount; ++i) {
  						saveA[i] = vertices[i].indexA;
  						saveB[i] = vertices[i].indexB;
  					}
  
  					simplex.solve();
  
  					// If we have 3 points, then the origin is in the corresponding triangle.
  					if (simplex.m_count == 3) {
  						break;
  					}
  
  					// Compute closest point.
  					var p = simplex.getClosestPoint();
  					distanceSqr2 = p.lengthSquared();
  
  					// Ensure progress
  					if (distanceSqr2 >= distanceSqr1) {
  						// break;
  					}
  					distanceSqr1 = distanceSqr2;
  
  					// Get search direction.
  					var d = simplex.getSearchDirection();
  
  					// Ensure the search direction is numerically fit.
  					if (d.lengthSquared() < Math.EPSILON * Math.EPSILON) {
  						// The origin is probably contained by a line segment
  						// or triangle. Thus the shapes are overlapped.
  
  						// We can't return zero here even though there may be overlap.
  						// In case the simplex is a point, segment, or triangle it is difficult
  						// to determine if the origin is contained in the CSO or very close to it.
  						break;
  					}
  
  					// Compute a tentative new simplex vertex using support points.
  					var vertex = vertices[simplex.m_count]; // SimplexVertex
  
  					vertex.indexA = proxyA.getSupport(Rot.mulTVec2(xfA.q, Vec2.neg(d)));
  					vertex.wA = Transform.mulVec2(xfA, proxyA.getVertex(vertex.indexA));
  
  					vertex.indexB = proxyB.getSupport(Rot.mulTVec2(xfB.q, d));
  					vertex.wB = Transform.mulVec2(xfB, proxyB.getVertex(vertex.indexB));
  
  					vertex.w = Vec2.sub(vertex.wB, vertex.wA);
  
  					// Iteration count is equated to the number of support point calls.
  					++iter;
  					++stats.gjkIters;
  
  					// Check for duplicate support points. This is the main termination
  					// criteria.
  					var duplicate = false;
  					for (var i = 0; i < saveCount; ++i) {
  						if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) {
  							duplicate = true;
  							break;
  						}
  					}
  
  					// If we found a duplicate support point we must exit to avoid cycling.
  					if (duplicate) {
  						break;
  					}
  
  					// New vertex is ok and needed.
  					++simplex.m_count;
  				}
  
  				stats.gjkMaxIters = Math.max(stats.gjkMaxIters, iter);
  
  				// Prepare output.
  				simplex.getWitnessPoints(output.pointA, output.pointB);
  				output.distance = Vec2.distance(output.pointA, output.pointB);
  				output.iterations = iter;
  
  				// Cache the simplex.
  				simplex.writeCache(cache);
  
  				// Apply radii if requested.
  				if (input.useRadii) {
  					var rA = proxyA.m_radius;
  					var rB = proxyB.m_radius;
  
  					if (output.distance > rA + rB && output.distance > Math.EPSILON) {
  						// Shapes are still no overlapped.
  						// Move the witness points to the outer surface.
  						output.distance -= rA + rB;
  						var normal = Vec2.sub(output.pointB, output.pointA);
  						normal.normalize();
  						output.pointA.addMul(rA, normal);
  						output.pointB.subMul(rB, normal);
  					} else {
  						// Shapes are overlapped when radii are considered.
  						// Move the witness points to the middle.
  						var p = Vec2.mid(output.pointA, output.pointB);
  						output.pointA.set(p);
  						output.pointB.set(p);
  						output.distance = 0.0;
  					}
  				}
  			}
  
  			/**
               * A distance proxy is used by the GJK algorithm. It encapsulates any shape.
               */
  			function DistanceProxy () {
  				this.m_buffer = []; // Vec2[2]
  				this.m_vertices = []; // Vec2[]
  				this.m_count = 0;
  				this.m_radius = 0;
  			}
  
  			/**
               * Get the vertex count.
               */
  			DistanceProxy.prototype.getVertexCount = function () {
  				return this.m_count;
  			};
  
  			/**
               * Get a vertex by index. Used by Distance.
               */
  			DistanceProxy.prototype.getVertex = function (index) {
  				_ASSERT && common.assert(index >= 0 && index < this.m_count);
  				return this.m_vertices[index];
  			};
  
  			/**
               * Get the supporting vertex index in the given direction.
               */
  			DistanceProxy.prototype.getSupport = function (d) {
  				var bestIndex = 0;
  				var bestValue = Vec2.dot(this.m_vertices[0], d);
  				for (var i = 0; i < this.m_count; ++i) {
  					var value = Vec2.dot(this.m_vertices[i], d);
  					if (value > bestValue) {
  						bestIndex = i;
  						bestValue = value;
  					}
  				}
  				return bestIndex;
  			};
  
  			/**
               * Get the supporting vertex in the given direction.
               */
  			DistanceProxy.prototype.getSupportVertex = function (d) {
  				return this.m_vertices[this.getSupport(d)];
  			};
  
  			/**
               * Initialize the proxy using the given shape. The shape must remain in scope
               * while the proxy is in use.
               */
  			DistanceProxy.prototype.set = function (shape, index) {
  				// TODO remove, use shape instead
  				_ASSERT && common.assert(typeof shape.computeDistanceProxy === 'function');
  				shape.computeDistanceProxy(this, index);
  			};
  
  			function SimplexVertex () {
  				this.indexA; // wA index
  				this.indexB; // wB index
  				this.wA = Vec2.zero(); // support point in proxyA
  				this.wB = Vec2.zero(); // support point in proxyB
  				this.w = Vec2.zero(); // wB - wA
  				this.a; // barycentric coordinate for closest point
  			}
  
  			SimplexVertex.prototype.set = function (v) {
  				this.indexA = v.indexA;
  				this.indexB = v.indexB;
  				this.wA = Vec2.clone(v.wA);
  				this.wB = Vec2.clone(v.wB);
  				this.w = Vec2.clone(v.w);
  				this.a = v.a;
  			};
  
  			function Simplex () {
  				this.m_v1 = new SimplexVertex();
  				this.m_v2 = new SimplexVertex();
  				this.m_v3 = new SimplexVertex();
  				this.m_v = [this.m_v1, this.m_v2, this.m_v3];
  				this.m_count;
  			}
  
  			Simplex.prototype.print = function () {
  				if (this.m_count == 3) {
  					return [`+${this.m_count}`, this.m_v1.a, this.m_v1.wA.x, this.m_v1.wA.y, this.m_v1.wB.x, this.m_v1.wB.y, this.m_v2.a, this.m_v2.wA.x, this.m_v2.wA.y, this.m_v2.wB.x, this.m_v2.wB.y, this.m_v3.a, this.m_v3.wA.x, this.m_v3.wA.y, this.m_v3.wB.x, this.m_v3.wB.y].toString();
  				} else if (this.m_count == 2) {
  					return [`+${this.m_count}`, this.m_v1.a, this.m_v1.wA.x, this.m_v1.wA.y, this.m_v1.wB.x, this.m_v1.wB.y, this.m_v2.a, this.m_v2.wA.x, this.m_v2.wA.y, this.m_v2.wB.x, this.m_v2.wB.y].toString();
  				} else if (this.m_count == 1) {
  					return [`+${this.m_count}`, this.m_v1.a, this.m_v1.wA.x, this.m_v1.wA.y, this.m_v1.wB.x, this.m_v1.wB.y].toString();
  				} else {
  					return `+${this.m_count}`;
  				}
  			};
  
  			// (SimplexCache, DistanceProxy, ...)
  			Simplex.prototype.readCache = function (cache, proxyA, transformA, proxyB, transformB) {
  				_ASSERT && common.assert(cache.count <= 3);
  
  				// Copy data from cache.
  				this.m_count = cache.count;
  				for (var i = 0; i < this.m_count; ++i) {
  					var v = this.m_v[i];
  					v.indexA = cache.indexA[i];
  					v.indexB = cache.indexB[i];
  					var wALocal = proxyA.getVertex(v.indexA);
  					var wBLocal = proxyB.getVertex(v.indexB);
  					v.wA = Transform.mulVec2(transformA, wALocal);
  					v.wB = Transform.mulVec2(transformB, wBLocal);
  					v.w = Vec2.sub(v.wB, v.wA);
  					v.a = 0.0;
  				}
  
  				// Compute the new simplex metric, if it is substantially different than
  				// old metric then flush the simplex.
  				if (this.m_count > 1) {
  					var metric1 = cache.metric;
  					var metric2 = this.getMetric();
  					if (metric2 < 0.5 * metric1 || 2.0 * metric1 < metric2 || metric2 < Math.EPSILON) {
  						// Reset the simplex.
  						this.m_count = 0;
  					}
  				}
  
  				// If the cache is empty or invalid...
  				if (this.m_count == 0) {
  					var v = this.m_v[0]; // SimplexVertex
  					v.indexA = 0;
  					v.indexB = 0;
  					var wALocal = proxyA.getVertex(0);
  					var wBLocal = proxyB.getVertex(0);
  					v.wA = Transform.mulVec2(transformA, wALocal);
  					v.wB = Transform.mulVec2(transformB, wBLocal);
  					v.w = Vec2.sub(v.wB, v.wA);
  					v.a = 1.0;
  					this.m_count = 1;
  				}
  			};
  
  			// (SimplexCache)
  			Simplex.prototype.writeCache = function (cache) {
  				cache.metric = this.getMetric();
  				cache.count = this.m_count;
  				for (var i = 0; i < this.m_count; ++i) {
  					cache.indexA[i] = this.m_v[i].indexA;
  					cache.indexB[i] = this.m_v[i].indexB;
  				}
  			};
  
  			Simplex.prototype.getSearchDirection = function () {
  				switch (this.m_count) {
  					case 1:
  						return Vec2.neg(this.m_v1.w);
  
  					case 2: {
  						var e12 = Vec2.sub(this.m_v2.w, this.m_v1.w);
  						var sgn = Vec2.cross(e12, Vec2.neg(this.m_v1.w));
  						if (sgn > 0.0) {
  							// Origin is left of e12.
  							return Vec2.cross(1.0, e12);
  						} else {
  							// Origin is right of e12.
  							return Vec2.cross(e12, 1.0);
  						}
  					}
  
  					default:
  						_ASSERT && common.assert(false);
  						return Vec2.zero();
  				}
  			};
  
  			Simplex.prototype.getClosestPoint = function () {
  				switch (this.m_count) {
  					case 0:
  						_ASSERT && common.assert(false);
  						return Vec2.zero();
  
  					case 1:
  						return Vec2.clone(this.m_v1.w);
  
  					case 2:
  						return Vec2.combine(this.m_v1.a, this.m_v1.w, this.m_v2.a, this.m_v2.w);
  
  					case 3:
  						return Vec2.zero();
  
  					default:
  						_ASSERT && common.assert(false);
  						return Vec2.zero();
  				}
  			};
  
  			Simplex.prototype.getWitnessPoints = function (pA, pB) {
  				switch (this.m_count) {
  					case 0:
  						_ASSERT && common.assert(false);
  						break;
  
  					case 1:
  						pA.set(this.m_v1.wA);
  						pB.set(this.m_v1.wB);
  						break;
  
  					case 2:
  						pA.setCombine(this.m_v1.a, this.m_v1.wA, this.m_v2.a, this.m_v2.wA);
  						pB.setCombine(this.m_v1.a, this.m_v1.wB, this.m_v2.a, this.m_v2.wB);
  						break;
  
  					case 3:
  						pA.setCombine(this.m_v1.a, this.m_v1.wA, this.m_v2.a, this.m_v2.wA);
  						pA.addMul(this.m_v3.a, this.m_v3.wA);
  						pB.set(pA);
  						break;
  
  					default:
  						_ASSERT && common.assert(false);
  						break;
  				}
  			};
  
  			Simplex.prototype.getMetric = function () {
  				switch (this.m_count) {
  					case 0:
  						_ASSERT && common.assert(false);
  						return 0.0;
  
  					case 1:
  						return 0.0;
  
  					case 2:
  						return Vec2.distance(this.m_v1.w, this.m_v2.w);
  
  					case 3:
  						return Vec2.cross(Vec2.sub(this.m_v2.w, this.m_v1.w), Vec2.sub(this.m_v3.w, this.m_v1.w));
  
  					default:
  						_ASSERT && common.assert(false);
  						return 0.0;
  				}
  			};
  
  			Simplex.prototype.solve = function () {
  				switch (this.m_count) {
  					case 1:
  						break;
  
  					case 2:
  						this.solve2();
  						break;
  
  					case 3:
  						this.solve3();
  						break;
  
  					default:
  						_ASSERT && common.assert(false);
  				}
  			};
  
  			// Solve a line segment using barycentric coordinates.
  			//
  			// p = a1 * w1 + a2 * w2
  			// a1 + a2 = 1
  			//
  			// The vector from the origin to the closest point on the line is
  			// perpendicular to the line.
  			// e12 = w2 - w1
  			// dot(p, e) = 0
  			// a1 * dot(w1, e) + a2 * dot(w2, e) = 0
  			//
  			// 2-by-2 linear system
  			// [1 1 ][a1] = [1]
  			// [w1.e12 w2.e12][a2] = [0]
  			//
  			// Define
  			// d12_1 = dot(w2, e12)
  			// d12_2 = -dot(w1, e12)
  			// d12 = d12_1 + d12_2
  			//
  			// Solution
  			// a1 = d12_1 / d12
  			// a2 = d12_2 / d12
  			Simplex.prototype.solve2 = function () {
  				var w1 = this.m_v1.w;
  				var w2 = this.m_v2.w;
  				var e12 = Vec2.sub(w2, w1);
  
  				// w1 region
  				var d12_2 = -Vec2.dot(w1, e12);
  				if (d12_2 <= 0.0) {
  					// a2 <= 0, so we clamp it to 0
  					this.m_v1.a = 1.0;
  					this.m_count = 1;
  					return;
  				}
  
  				// w2 region
  				var d12_1 = Vec2.dot(w2, e12);
  				if (d12_1 <= 0.0) {
  					// a1 <= 0, so we clamp it to 0
  					this.m_v2.a = 1.0;
  					this.m_count = 1;
  					this.m_v1.set(this.m_v2);
  					return;
  				}
  
  				// Must be in e12 region.
  				var inv_d12 = 1.0 / (d12_1 + d12_2);
  				this.m_v1.a = d12_1 * inv_d12;
  				this.m_v2.a = d12_2 * inv_d12;
  				this.m_count = 2;
  			};
  
  			// Possible regions:
  			// - points[2]
  			// - edge points[0]-points[2]
  			// - edge points[1]-points[2]
  			// - inside the triangle
  			Simplex.prototype.solve3 = function () {
  				var w1 = this.m_v1.w;
  				var w2 = this.m_v2.w;
  				var w3 = this.m_v3.w;
  
  				// Edge12
  				// [1 1 ][a1] = [1]
  				// [w1.e12 w2.e12][a2] = [0]
  				// a3 = 0
  				var e12 = Vec2.sub(w2, w1);
  				var w1e12 = Vec2.dot(w1, e12);
  				var w2e12 = Vec2.dot(w2, e12);
  				var d12_1 = w2e12;
  				var d12_2 = -w1e12;
  
  				// Edge13
  				// [1 1 ][a1] = [1]
  				// [w1.e13 w3.e13][a3] = [0]
  				// a2 = 0
  				var e13 = Vec2.sub(w3, w1);
  				var w1e13 = Vec2.dot(w1, e13);
  				var w3e13 = Vec2.dot(w3, e13);
  				var d13_1 = w3e13;
  				var d13_2 = -w1e13;
  
  				// Edge23
  				// [1 1 ][a2] = [1]
  				// [w2.e23 w3.e23][a3] = [0]
  				// a1 = 0
  				var e23 = Vec2.sub(w3, w2); // Vec2
  				var w2e23 = Vec2.dot(w2, e23);
  				var w3e23 = Vec2.dot(w3, e23);
  				var d23_1 = w3e23;
  				var d23_2 = -w2e23;
  
  				// Triangle123
  				var n123 = Vec2.cross(e12, e13);
  
  				var d123_1 = n123 * Vec2.cross(w2, w3);
  				var d123_2 = n123 * Vec2.cross(w3, w1);
  				var d123_3 = n123 * Vec2.cross(w1, w2);
  
  				// w1 region
  				if (d12_2 <= 0.0 && d13_2 <= 0.0) {
  					this.m_v1.a = 1.0;
  					this.m_count = 1;
  					return;
  				}
  
  				// e12
  				if (d12_1 > 0.0 && d12_2 > 0.0 && d123_3 <= 0.0) {
  					var inv_d12 = 1.0 / (d12_1 + d12_2);
  					this.m_v1.a = d12_1 * inv_d12;
  					this.m_v2.a = d12_2 * inv_d12;
  					this.m_count = 2;
  					return;
  				}
  
  				// e13
  				if (d13_1 > 0.0 && d13_2 > 0.0 && d123_2 <= 0.0) {
  					var inv_d13 = 1.0 / (d13_1 + d13_2);
  					this.m_v1.a = d13_1 * inv_d13;
  					this.m_v3.a = d13_2 * inv_d13;
  					this.m_count = 2;
  					this.m_v2.set(this.m_v3);
  					return;
  				}
  
  				// w2 region
  				if (d12_1 <= 0.0 && d23_2 <= 0.0) {
  					this.m_v2.a = 1.0;
  					this.m_count = 1;
  					this.m_v1.set(this.m_v2);
  					return;
  				}
  
  				// w3 region
  				if (d13_1 <= 0.0 && d23_1 <= 0.0) {
  					this.m_v3.a = 1.0;
  					this.m_count = 1;
  					this.m_v1.set(this.m_v3);
  					return;
  				}
  
  				// e23
  				if (d23_1 > 0.0 && d23_2 > 0.0 && d123_1 <= 0.0) {
  					var inv_d23 = 1.0 / (d23_1 + d23_2);
  					this.m_v2.a = d23_1 * inv_d23;
  					this.m_v3.a = d23_2 * inv_d23;
  					this.m_count = 2;
  					this.m_v1.set(this.m_v3);
  					return;
  				}
  
  				// Must be in triangle123
  				var inv_d123 = 1.0 / (d123_1 + d123_2 + d123_3);
  				this.m_v1.a = d123_1 * inv_d123;
  				this.m_v2.a = d123_2 * inv_d123;
  				this.m_v3.a = d123_3 * inv_d123;
  				this.m_count = 3;
  			};
  
  			/**
               * Determine if two generic shapes overlap.
               */
  			Distance.testOverlap = function (shapeA, indexA, shapeB, indexB, xfA, xfB) {
  				var input = new DistanceInput();
  				input.proxyA.set(shapeA, indexA);
  				input.proxyB.set(shapeB, indexB);
  				input.transformA = xfA;
  				input.transformB = xfB;
  				input.useRadii = true;
  
  				var cache = new SimplexCache();
  
  				var output = new DistanceOutput();
  				Distance(output, cache, input);
  
  				return output.distance < 10.0 * Math.EPSILON;
  			};
  
  			/***/
  		},
  		/* 23 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = CircleShape;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var options = __webpack_require__(7);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Rot = __webpack_require__(3);
  			var Vec2 = __webpack_require__(0);
  			var AABB = __webpack_require__(17);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  
  			CircleShape._super = Shape;
  			CircleShape.prototype = create(CircleShape._super.prototype);
  
  			CircleShape.TYPE = 'circle';
  			Shape.TYPES[CircleShape.TYPE] = CircleShape;
  
  			function CircleShape (a, b) {
  				if (!(this instanceof CircleShape)) {
  					return new CircleShape(a, b);
  				}
  
  				CircleShape._super.call(this);
  
  				this.m_type = CircleShape.TYPE;
  				this.m_p = Vec2.zero();
  				this.m_radius = 1;
  
  				if (typeof a === 'object' && Vec2.isValid(a)) {
  					this.m_p.set(a);
  
  					if (typeof b === 'number') {
  						this.m_radius = b;
  					}
  				} else if (typeof a === 'number') {
  					this.m_radius = a;
  				}
  			}
  
  			CircleShape.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  
  					p: this.m_p,
  					radius: this.m_radius
  				};
  			};
  
  			CircleShape._deserialize = function (data) {
  				return new CircleShape(data.p, data.radius);
  			};
  
  			CircleShape.prototype.getRadius = function () {
  				return this.m_radius;
  			};
  
  			CircleShape.prototype.getCenter = function () {
  				return this.m_p;
  			};
  
  			CircleShape.prototype.getVertex = function (index) {
  				_ASSERT && common.assert(index == 0);
  				return this.m_p;
  			};
  
  			CircleShape.prototype.getVertexCount = function (index) {
  				return 1;
  			};
  
  			/**
               * @deprecated
               */
  			CircleShape.prototype._clone = function () {
  				var clone = new CircleShape();
  				clone.m_type = this.m_type;
  				clone.m_radius = this.m_radius;
  				clone.m_p = this.m_p.clone();
  				return clone;
  			};
  
  			CircleShape.prototype.getChildCount = function () {
  				return 1;
  			};
  
  			CircleShape.prototype.testPoint = function (xf, p) {
  				var center = Vec2.add(xf.p, Rot.mulVec2(xf.q, this.m_p));
  				var d = Vec2.sub(p, center);
  				return Vec2.dot(d, d) <= this.m_radius * this.m_radius;
  			};
  
  			// Collision Detection in Interactive 3D Environments by Gino van den Bergen
  			// From Section 3.1.2
  			// x = s + a * r
  			// norm(x) = radius
  			CircleShape.prototype.rayCast = function (output, input, xf, childIndex) {
  				var position = Vec2.add(xf.p, Rot.mulVec2(xf.q, this.m_p));
  				var s = Vec2.sub(input.p1, position);
  				var b = Vec2.dot(s, s) - this.m_radius * this.m_radius;
  
  				// Solve quadratic equation.
  				var r = Vec2.sub(input.p2, input.p1);
  				var c = Vec2.dot(s, r);
  				var rr = Vec2.dot(r, r);
  				var sigma = c * c - rr * b;
  
  				// Check for negative discriminant and short segment.
  				if (sigma < 0.0 || rr < Math.EPSILON) {
  					return false;
  				}
  
  				// Find the point of intersection of the line with the circle.
  				var a = -(c + Math.sqrt(sigma));
  
  				// Is the intersection point on the segment?
  				if (a >= 0.0 && a <= input.maxFraction * rr) {
  					a /= rr;
  					output.fraction = a;
  					output.normal = Vec2.add(s, Vec2.mul(a, r));
  					output.normal.normalize();
  					return true;
  				}
  
  				return false;
  			};
  
  			CircleShape.prototype.computeAABB = function (aabb, xf, childIndex) {
  				var p = Vec2.add(xf.p, Rot.mulVec2(xf.q, this.m_p));
  				aabb.lowerBound.set(p.x - this.m_radius, p.y - this.m_radius);
  				aabb.upperBound.set(p.x + this.m_radius, p.y + this.m_radius);
  			};
  
  			CircleShape.prototype.computeMass = function (massData, density) {
  				massData.mass = density * Math.PI * this.m_radius * this.m_radius;
  				massData.center = this.m_p;
  				// inertia about the local origin
  				massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + Vec2.dot(this.m_p, this.m_p));
  			};
  
  			CircleShape.prototype.computeDistanceProxy = function (proxy) {
  				proxy.m_vertices.push(this.m_p);
  				proxy.m_count = 1;
  				proxy.m_radius = this.m_radius;
  			};
  
  			/***/
  		},
  		/* 24 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = EdgeShape;
  
  			var create = __webpack_require__(6);
  			var options = __webpack_require__(7);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Rot = __webpack_require__(3);
  			var Vec2 = __webpack_require__(0);
  			var AABB = __webpack_require__(17);
  
  			EdgeShape._super = Shape;
  			EdgeShape.prototype = create(EdgeShape._super.prototype);
  
  			EdgeShape.TYPE = 'edge';
  			Shape.TYPES[EdgeShape.TYPE] = EdgeShape;
  
  			/**
               * A line segment (edge) shape. These can be connected in chains or loops to
               * other edge shapes. The connectivity information is used to ensure correct
               * contact normals.
               */
  			function EdgeShape (v1, v2) {
  				if (!(this instanceof EdgeShape)) {
  					return new EdgeShape(v1, v2);
  				}
  
  				EdgeShape._super.call(this);
  
  				this.m_type = EdgeShape.TYPE;
  				this.m_radius = Settings.polygonRadius;
  
  				// These are the edge vertices
  				this.m_vertex1 = v1 ? Vec2.clone(v1) : Vec2.zero();
  				this.m_vertex2 = v2 ? Vec2.clone(v2) : Vec2.zero();
  
  				// Optional adjacent vertices. These are used for smooth collision.
  				// Used by chain shape.
  				this.m_vertex0 = Vec2.zero();
  				this.m_vertex3 = Vec2.zero();
  				this.m_hasVertex0 = false;
  				this.m_hasVertex3 = false;
  			}
  
  			EdgeShape.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  
  					vertex1: this.m_vertex1,
  					vertex2: this.m_vertex2,
  
  					vertex0: this.m_vertex0,
  					vertex3: this.m_vertex3,
  					hasVertex0: this.m_hasVertex0,
  					hasVertex3: this.m_hasVertex3
  				};
  			};
  
  			EdgeShape._deserialize = function (data) {
  				var shape = new EdgeShape(data.vertex1, data.vertex2);
  				if (shape.hasVertex0) {
  					shape.setPrev(data.vertex0);
  				}
  				if (shape.hasVertex3) {
  					shape.setNext(data.vertex3);
  				}
  				return shape;
  			};
  
  			EdgeShape.prototype.setNext = function (v3) {
  				if (v3) {
  					this.m_vertex3.set(v3);
  					this.m_hasVertex3 = true;
  				} else {
  					this.m_vertex3.setZero();
  					this.m_hasVertex3 = false;
  				}
  				return this;
  			};
  
  			EdgeShape.prototype.setPrev = function (v0) {
  				if (v0) {
  					this.m_vertex0.set(v0);
  					this.m_hasVertex0 = true;
  				} else {
  					this.m_vertex0.setZero();
  					this.m_hasVertex0 = false;
  				}
  				return this;
  			};
  
  			/**
               * Set this as an isolated edge.
               */
  			EdgeShape.prototype._set = function (v1, v2) {
  				this.m_vertex1.set(v1);
  				this.m_vertex2.set(v2);
  				this.m_hasVertex0 = false;
  				this.m_hasVertex3 = false;
  				return this;
  			};
  
  			/**
               * @deprecated
               */
  			EdgeShape.prototype._clone = function () {
  				var clone = new EdgeShape();
  				clone.m_type = this.m_type;
  				clone.m_radius = this.m_radius;
  				clone.m_vertex1.set(this.m_vertex1);
  				clone.m_vertex2.set(this.m_vertex2);
  				clone.m_vertex0.set(this.m_vertex0);
  				clone.m_vertex3.set(this.m_vertex3);
  				clone.m_hasVertex0 = this.m_hasVertex0;
  				clone.m_hasVertex3 = this.m_hasVertex3;
  				return clone;
  			};
  
  			EdgeShape.prototype.getChildCount = function () {
  				return 1;
  			};
  
  			EdgeShape.prototype.testPoint = function (xf, p) {
  				return false;
  			};
  
  			// p = p1 + t * d
  			// v = v1 + s * e
  			// p1 + t * d = v1 + s * e
  			// s * e - t * d = p1 - v1
  			EdgeShape.prototype.rayCast = function (output, input, xf, childIndex) {
  				// NOT_USED(childIndex);
  
  				// Put the ray into the edge's frame of reference.
  				var p1 = Rot.mulTVec2(xf.q, Vec2.sub(input.p1, xf.p));
  				var p2 = Rot.mulTVec2(xf.q, Vec2.sub(input.p2, xf.p));
  				var d = Vec2.sub(p2, p1);
  
  				var v1 = this.m_vertex1;
  				var v2 = this.m_vertex2;
  				var e = Vec2.sub(v2, v1);
  				var normal = Vec2.neo(e.y, -e.x);
  				normal.normalize();
  
  				// q = p1 + t * d
  				// dot(normal, q - v1) = 0
  				// dot(normal, p1 - v1) + t * dot(normal, d) = 0
  				var numerator = Vec2.dot(normal, Vec2.sub(v1, p1));
  				var denominator = Vec2.dot(normal, d);
  
  				if (denominator == 0.0) {
  					return false;
  				}
  
  				var t = numerator / denominator;
  				if (t < 0.0 || input.maxFraction < t) {
  					return false;
  				}
  
  				var q = Vec2.add(p1, Vec2.mul(t, d));
  
  				// q = v1 + s * r
  				// s = dot(q - v1, r) / dot(r, r)
  				var r = Vec2.sub(v2, v1);
  				var rr = Vec2.dot(r, r);
  				if (rr == 0.0) {
  					return false;
  				}
  
  				var s = Vec2.dot(Vec2.sub(q, v1), r) / rr;
  				if (s < 0.0 || s > 1.0) {
  					return false;
  				}
  
  				output.fraction = t;
  				if (numerator > 0.0) {
  					output.normal = Rot.mulVec2(xf.q, normal).neg();
  				} else {
  					output.normal = Rot.mulVec2(xf.q, normal);
  				}
  				return true;
  			};
  
  			EdgeShape.prototype.computeAABB = function (aabb, xf, childIndex) {
  				var v1 = Transform.mulVec2(xf, this.m_vertex1);
  				var v2 = Transform.mulVec2(xf, this.m_vertex2);
  
  				aabb.combinePoints(v1, v2);
  				aabb.extend(this.m_radius);
  			};
  
  			EdgeShape.prototype.computeMass = function (massData, density) {
  				massData.mass = 0.0;
  				massData.center.setCombine(0.5, this.m_vertex1, 0.5, this.m_vertex2);
  				massData.I = 0.0;
  			};
  
  			EdgeShape.prototype.computeDistanceProxy = function (proxy) {
  				proxy.m_vertices.push(this.m_vertex1);
  				proxy.m_vertices.push(this.m_vertex2);
  				proxy.m_count = 2;
  				proxy.m_radius = this.m_radius;
  			};
  
  			/***/
  		}, /* 26 */ /* 27 */, ,
  
  		/* 25 */ /***/ function (module, exports, __webpack_require__) {
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			exports.toString = function (newline) {
  				newline = typeof newline === 'string' ? newline : '\n';
  				var string = '';
  				for (var name in this) {
  					if (typeof this[name] !== 'function' && typeof this[name] !== 'object') {
  						string += `${name}: ${this[name]}${newline}`;
  					}
  				}
  				return string;
  			};
  
  			/***/
  		},
  		/* 28 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = ChainShape;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var options = __webpack_require__(7);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Rot = __webpack_require__(3);
  			var Vec2 = __webpack_require__(0);
  			var AABB = __webpack_require__(17);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  			var EdgeShape = __webpack_require__(24);
  
  			ChainShape._super = Shape;
  			ChainShape.prototype = create(ChainShape._super.prototype);
  
  			ChainShape.TYPE = 'chain';
  			Shape.TYPES[ChainShape.TYPE] = ChainShape;
  
  			/**
               * A chain shape is a free form sequence of line segments. The chain has
               * two-sided collision, so you can use inside and outside collision. Therefore,
               * you may use any winding order. Connectivity information is used to create
               * smooth collisions.
               *
               * WARNING: The chain will not collide properly if there are self-intersections.
               */
  			function ChainShape (vertices, loop) {
  				if (!(this instanceof ChainShape)) {
  					return new ChainShape(vertices, loop);
  				}
  
  				ChainShape._super.call(this);
  
  				this.m_type = ChainShape.TYPE;
  				this.m_radius = Settings.polygonRadius;
  				this.m_vertices = [];
  				this.m_count = 0;
  				this.m_prevVertex = null;
  				this.m_nextVertex = null;
  				this.m_hasPrevVertex = false;
  				this.m_hasNextVertex = false;
  
  				this.m_isLoop = loop;
  
  				if (vertices && vertices.length) {
  					if (loop) {
  						this._createLoop(vertices);
  					} else {
  						this._createChain(vertices);
  					}
  				}
  			}
  
  			ChainShape.prototype._serialize = function () {
  				const data = {
  					type: this.m_type,
  					vertices: this.m_vertices,
  					isLoop: this.m_isLoop,
  					hasPrevVertex: this.m_hasPrevVertex,
  					hasNextVertex: this.m_hasNextVertex
  				};
  				if (this.m_prevVertex) {
  					data.prevVertex = this.m_prevVertex;
  				}
  				if (this.m_nextVertex) {
  					data.nextVertex = this.m_nextVertex;
  				}
  				return data;
  			};
  
  			ChainShape._deserialize = function (data) {
  				var shape = new ChainShape(data.vertices.map(Vec2._deserialize), data.isLoop);
  				if (data.prevVertex) {
  					shape._setPrevVertex(data.prevVertex);
  				}
  				if (data.nextVertex) {
  					shape._setNextVertex(data.nextVertex);
  				}
  				return shape;
  			};
  
  			// ChainShape.clear = function() {
  			// this.m_vertices.length = 0;
  			// this.m_count = 0;
  			// }
  
  			/**
               * Create a loop. This automatically adjusts connectivity.
               *
               * @param vertices an array of vertices, these are copied
               * @param count the vertex count
               */
  			ChainShape.prototype._createLoop = function (vertices) {
  				_ASSERT && common.assert(this.m_vertices.length == 0 && this.m_count == 0);
  				_ASSERT && common.assert(vertices.length >= 3);
  				for (var i = 1; i < vertices.length; ++i) {
  					var v1 = vertices[i - 1];
  					var v2 = vertices[i];
  					// If the code crashes here, it means your vertices are too close together.
  					_ASSERT && common.assert(Vec2.distanceSquared(v1, v2) > Settings.linearSlopSquared);
  				}
  
  				this.m_vertices.length = 0;
  				this.m_count = vertices.length + 1;
  				for (var i = 0; i < vertices.length; ++i) {
  					this.m_vertices[i] = vertices[i].clone();
  				}
  				this.m_vertices[vertices.length] = vertices[0].clone();
  
  				this.m_prevVertex = this.m_vertices[this.m_count - 2];
  				this.m_nextVertex = this.m_vertices[1];
  				this.m_hasPrevVertex = true;
  				this.m_hasNextVertex = true;
  				return this;
  			};
  
  			/**
               * Create a chain with isolated end vertices.
               *
               * @param vertices an array of vertices, these are copied
               * @param count the vertex count
               */
  			ChainShape.prototype._createChain = function (vertices) {
  				_ASSERT && common.assert(this.m_vertices.length == 0 && this.m_count == 0);
  				_ASSERT && common.assert(vertices.length >= 2);
  				for (var i = 1; i < vertices.length; ++i) {
  					// If the code crashes here, it means your vertices are too close together.
  					var v1 = vertices[i - 1];
  					var v2 = vertices[i];
  					_ASSERT && common.assert(Vec2.distanceSquared(v1, v2) > Settings.linearSlopSquared);
  				}
  
  				this.m_count = vertices.length;
  				for (var i = 0; i < vertices.length; ++i) {
  					this.m_vertices[i] = vertices[i].clone();
  				}
  
  				this.m_hasPrevVertex = false;
  				this.m_hasNextVertex = false;
  				this.m_prevVertex = null;
  				this.m_nextVertex = null;
  				return this;
  			};
  
  			/**
               * Establish connectivity to a vertex that precedes the first vertex. Don't call
               * this for loops.
               */
  			ChainShape.prototype._setPrevVertex = function (prevVertex) {
  				this.m_prevVertex = prevVertex;
  				this.m_hasPrevVertex = true;
  			};
  
  			/**
               * Establish connectivity to a vertex that follows the last vertex. Don't call
               * this for loops.
               */
  			ChainShape.prototype._setNextVertex = function (nextVertex) {
  				this.m_nextVertex = nextVertex;
  				this.m_hasNextVertex = true;
  			};
  
  			/**
               * @deprecated
               */
  			ChainShape.prototype._clone = function () {
  				var clone = new ChainShape();
  				clone.createChain(this.m_vertices);
  				clone.m_type = this.m_type;
  				clone.m_radius = this.m_radius;
  				clone.m_prevVertex = this.m_prevVertex;
  				clone.m_nextVertex = this.m_nextVertex;
  				clone.m_hasPrevVertex = this.m_hasPrevVertex;
  				clone.m_hasNextVertex = this.m_hasNextVertex;
  				return clone;
  			};
  
  			ChainShape.prototype.getChildCount = function () {
  				// edge count = vertex count - 1
  				return this.m_count - 1;
  			};
  
  			// Get a child edge.
  			ChainShape.prototype.getChildEdge = function (edge, childIndex) {
  				_ASSERT && common.assert(childIndex >= 0 && childIndex < this.m_count - 1);
  				edge.m_type = EdgeShape.TYPE;
  				edge.m_radius = this.m_radius;
  
  				edge.m_vertex1 = this.m_vertices[childIndex];
  				edge.m_vertex2 = this.m_vertices[childIndex + 1];
  
  				if (childIndex > 0) {
  					edge.m_vertex0 = this.m_vertices[childIndex - 1];
  					edge.m_hasVertex0 = true;
  				} else {
  					edge.m_vertex0 = this.m_prevVertex;
  					edge.m_hasVertex0 = this.m_hasPrevVertex;
  				}
  
  				if (childIndex < this.m_count - 2) {
  					edge.m_vertex3 = this.m_vertices[childIndex + 2];
  					edge.m_hasVertex3 = true;
  				} else {
  					edge.m_vertex3 = this.m_nextVertex;
  					edge.m_hasVertex3 = this.m_hasNextVertex;
  				}
  			};
  
  			ChainShape.prototype.getVertex = function (index) {
  				_ASSERT && common.assert(index >= 0 && index <= this.m_count);
  				if (index < this.m_count) {
  					return this.m_vertices[index];
  				} else {
  					return this.m_vertices[0];
  				}
  			};
  
  			/**
               * This always return false.
               */
  			ChainShape.prototype.testPoint = function (xf, p) {
  				return false;
  			};
  
  			ChainShape.prototype.rayCast = function (output, input, xf, childIndex) {
  				_ASSERT && common.assert(childIndex >= 0 && childIndex < this.m_count);
  
  				var edgeShape = new EdgeShape(this.getVertex(childIndex), this.getVertex(childIndex + 1));
  				return edgeShape.rayCast(output, input, xf, 0);
  			};
  
  			ChainShape.prototype.computeAABB = function (aabb, xf, childIndex) {
  				_ASSERT && common.assert(childIndex >= 0 && childIndex < this.m_count);
  
  				var v1 = Transform.mulVec2(xf, this.getVertex(childIndex));
  				var v2 = Transform.mulVec2(xf, this.getVertex(childIndex + 1));
  
  				aabb.combinePoints(v1, v2);
  			};
  
  			/**
               * Chains have zero mass.
               */
  			ChainShape.prototype.computeMass = function (massData, density) {
  				massData.mass = 0.0;
  				massData.center = Vec2.neo();
  				massData.I = 0.0;
  			};
  
  			ChainShape.prototype.computeDistanceProxy = function (proxy, childIndex) {
  				_ASSERT && common.assert(childIndex >= 0 && childIndex < this.m_count);
  				proxy.m_buffer[0] = this.getVertex(childIndex);
  				proxy.m_buffer[1] = this.getVertex(childIndex + 1);
  				proxy.m_vertices = proxy.m_buffer;
  				proxy.m_count = 2;
  				proxy.m_radius = this.m_radius;
  			};
  
  			/***/
  		}, /* 30 */,
  		/* 29 */ /***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = World;
  
  			var options = __webpack_require__(7);
  			var common = __webpack_require__(2);
  			var Vec2 = __webpack_require__(0);
  			var BroadPhase = __webpack_require__(41);
  			var Solver = __webpack_require__(43);
  			var Body = __webpack_require__(8);
  			var Joint = __webpack_require__(12);
  			var Contact = __webpack_require__(18);
  
  			/**
               * @typedef {Object} WorldDef
               *
               * @prop {Vec2} [gravity = { x : 0, y : 0}]
               * @prop {boolean} [allowSleep = true]
               * @prop {boolean} [warmStarting = true]
               * @prop {boolean} [continuousPhysics = true]
               * @prop {boolean} [subStepping = false]
               * @prop {boolean} [blockSolve = true]
               * @prop {int} [velocityIterations = 8] For the velocity constraint solver.
               * @prop {int} [positionIterations = 3] For the position constraint solver.
               */
  			var WorldDef = {
  				gravity: Vec2.zero(),
  				allowSleep: true,
  				warmStarting: true,
  				continuousPhysics: true,
  				subStepping: false,
  				blockSolve: true,
  				velocityIterations: 8,
  				positionIterations: 3
  			};
  
  			/**
               * @param {WordDef|Vec2} def World definition or gravity vector.
               */
  			function World (def) {
  				if (!(this instanceof World)) {
  					return new World(def);
  				}
  
  				if (def && Vec2.isValid(def)) {
  					def = { gravity: def };
  				}
  
  				def = options(def, WorldDef);
  
  				this.m_solver = new Solver(this);
  
  				this.m_broadPhase = new BroadPhase();
  
  				this.m_contactList = null;
  				this.m_contactCount = 0;
  
  				this.m_bodyList = null;
  				this.m_bodyCount = 0;
  
  				this.m_jointList = null;
  				this.m_jointCount = 0;
  
  				this.m_stepComplete = true;
  
  				this.m_allowSleep = def.allowSleep;
  				this.m_gravity = Vec2.clone(def.gravity);
  
  				this.m_clearForces = true;
  				this.m_newFixture = false;
  				this.m_locked = false;
  
  				// These are for debugging the solver.
  				this.m_warmStarting = def.warmStarting;
  				this.m_continuousPhysics = def.continuousPhysics;
  				this.m_subStepping = def.subStepping;
  
  				this.m_blockSolve = def.blockSolve;
  				this.m_velocityIterations = def.velocityIterations;
  				this.m_positionIterations = def.positionIterations;
  
  				this.m_t = 0;
  
  				this.m_stepCount = 0;
  
  				// Broad-phase callback.
  				this.addPair = this.createContact.bind(this);
  			}
  
  			World.prototype._serialize = function () {
  				var bodies = [];
  				var joints = [];
  
  				for (var b = this.getBodyList(); b; b = b.getNext()) {
  					bodies.push(b);
  				}
  
  				for (var j = this.getJointList(); j; j = j.getNext()) {
  					if (typeof j._serialize === 'function') {
  						joints.push(j);
  					}
  				}
  
  				return {
  					gravity: this.m_gravity,
  					bodies: bodies,
  					joints: joints
  				};
  			};
  
  			World._deserialize = function (data, context, restore) {
  				if (!data) {
  					return new World();
  				}
  
  				var world = new World(data.gravity);
  
  				data.bodies &&
                      data.bodies.reverse().forEach(function (data) {
                      	world._addBody(restore(Body, data, world));
                      });
  
  				data.joints &&
                      data.joints.reverse().forEach(function (data) {
                      	world.createJoint(restore(Joint, data, world));
                      });
  
  				return world;
  			};
  
  			/**
               * Get the world body list. With the returned body, use Body.getNext to get the
               * next body in the world list. A null body indicates the end of the list.
               *
               * @return the head of the world body list.
               */
  			World.prototype.getBodyList = function () {
  				return this.m_bodyList;
  			};
  
  			/**
               * Get the world joint list. With the returned joint, use Joint.getNext to get
               * the next joint in the world list. A null joint indicates the end of the list.
               *
               * @return the head of the world joint list.
               */
  			World.prototype.getJointList = function () {
  				return this.m_jointList;
  			};
  
  			/**
               * Get the world contact list. With the returned contact, use Contact.getNext to
               * get the next contact in the world list. A null contact indicates the end of
               * the list.
               *
               * @return the head of the world contact list. Warning: contacts are created and
               *         destroyed in the middle of a time step. Use ContactListener to avoid
               *         missing contacts.
               */
  			World.prototype.getContactList = function () {
  				return this.m_contactList;
  			};
  
  			World.prototype.getBodyCount = function () {
  				return this.m_bodyCount;
  			};
  
  			World.prototype.getJointCount = function () {
  				return this.m_jointCount;
  			};
  
  			/**
               * Get the number of contacts (each may have 0 or more contact points).
               */
  			World.prototype.getContactCount = function () {
  				return this.m_contactCount;
  			};
  
  			/**
               * Change the global gravity vector.
               */
  			World.prototype.setGravity = function (gravity) {
  				this.m_gravity = gravity;
  			};
  
  			/**
               * Get the global gravity vector.
               */
  			World.prototype.getGravity = function () {
  				return this.m_gravity;
  			};
  
  			/**
               * Is the world locked (in the middle of a time step).
               */
  			World.prototype.isLocked = function () {
  				return this.m_locked;
  			};
  
  			/**
               * Enable/disable sleep.
               */
  			World.prototype.setAllowSleeping = function (flag) {
  				if (flag == this.m_allowSleep) {
  					return;
  				}
  
  				this.m_allowSleep = flag;
  				if (this.m_allowSleep == false) {
  					for (var b = this.m_bodyList; b; b = b.m_next) {
  						b.setAwake(true);
  					}
  				}
  			};
  
  			World.prototype.getAllowSleeping = function () {
  				return this.m_allowSleep;
  			};
  
  			/**
               * Enable/disable warm starting. For testing.
               */
  			World.prototype.setWarmStarting = function (flag) {
  				this.m_warmStarting = flag;
  			};
  
  			World.prototype.getWarmStarting = function () {
  				return this.m_warmStarting;
  			};
  
  			/**
               * Enable/disable continuous physics. For testing.
               */
  			World.prototype.setContinuousPhysics = function (flag) {
  				this.m_continuousPhysics = flag;
  			};
  
  			World.prototype.getContinuousPhysics = function () {
  				return this.m_continuousPhysics;
  			};
  
  			/**
               * Enable/disable single stepped continuous physics. For testing.
               */
  			World.prototype.setSubStepping = function (flag) {
  				this.m_subStepping = flag;
  			};
  
  			World.prototype.getSubStepping = function () {
  				return this.m_subStepping;
  			};
  
  			/**
               * Set flag to control automatic clearing of forces after each time step.
               */
  			World.prototype.setAutoClearForces = function (flag) {
  				this.m_clearForces = flag;
  			};
  
  			/**
               * Get the flag that controls automatic clearing of forces after each time step.
               */
  			World.prototype.getAutoClearForces = function () {
  				return this.m_clearForces;
  			};
  
  			/**
               * Manually clear the force buffer on all bodies. By default, forces are cleared
               * automatically after each call to step. The default behavior is modified by
               * calling setAutoClearForces. The purpose of this function is to support
               * sub-stepping. Sub-stepping is often used to maintain a fixed sized time step
               * under a variable frame-rate. When you perform sub-stepping you will disable
               * auto clearing of forces and instead call clearForces after all sub-steps are
               * complete in one pass of your game loop.
               *
               * @see setAutoClearForces
               */
  			World.prototype.clearForces = function () {
  				for (var body = this.m_bodyList; body; body = body.getNext()) {
  					body.m_force.setZero();
  					body.m_torque = 0.0;
  				}
  			};
  
  			/**
               * @function World~rayCastCallback
               *
               * @param fixture
               */
  
  			/**
               * Query the world for all fixtures that potentially overlap the provided AABB.
               *
               * @param {World~queryCallback} queryCallback Called for each fixture
               *          found in the query AABB. It may return `false` to terminate the
               *          query.
               *
               * @param aabb The query box.
               */
  			World.prototype.queryAABB = function (aabb, queryCallback) {
  				_ASSERT && common.assert(typeof queryCallback === 'function');
  				var broadPhase = this.m_broadPhase;
  				this.m_broadPhase.query(aabb, function (proxyId) {
  					// TODO GC
  					var proxy = broadPhase.getUserData(proxyId); // FixtureProxy
  					return queryCallback(proxy.fixture);
  				});
  			};
  
  			/**
               * @function World~rayCastCallback
               *
               * Callback class for ray casts. See World.rayCast
               *
               * Called for each fixture found in the query. You control how the ray cast
               * proceeds by returning a float: return -1: ignore this fixture and continue
               * return 0: terminate the ray cast return fraction: clip the ray to this point
               * return 1: don't clip the ray and continue
               *
               * @param fixture The fixture hit by the ray
               * @param point The point of initial intersection
               * @param normal The normal vector at the point of intersection
               * @param fraction
               *
               * @return {float} -1 to filter, 0 to terminate, fraction to clip the ray for
               *         closest hit, 1 to continue
               */
  
  			/**
               *
               * Ray-cast the world for all fixtures in the path of the ray. Your callback
               * controls whether you get the closest point, any point, or n-points. The
               * ray-cast ignores shapes that contain the starting point.
               *
               * @param {World~RayCastCallback} reportFixtureCallback A user implemented
               *          callback function.
               * @param point1 The ray starting point
               * @param point2 The ray ending point
               */
  			World.prototype.rayCast = function (point1, point2, reportFixtureCallback) {
  				_ASSERT && common.assert(typeof reportFixtureCallback === 'function');
  				var broadPhase = this.m_broadPhase;
  
  				this.m_broadPhase.rayCast(
  					{
  						maxFraction: 1.0,
  						p1: point1,
  						p2: point2
  					},
  					function (input, proxyId) {
  						// TODO GC
  						var proxy = broadPhase.getUserData(proxyId); // FixtureProxy
  						var fixture = proxy.fixture;
  						var index = proxy.childIndex;
  						var output = {}; // TODO GC
  						var hit = fixture.rayCast(output, input, index);
  						if (hit) {
  							var fraction = output.fraction;
  							var point = Vec2.add(Vec2.mul(1.0 - fraction, input.p1), Vec2.mul(fraction, input.p2));
  							return reportFixtureCallback(fixture, point, output.normal, fraction);
  						}
  						return input.maxFraction;
  					}
  				);
  			};
  
  			/**
               * Get the number of broad-phase proxies.
               */
  			World.prototype.getProxyCount = function () {
  				return this.m_broadPhase.getProxyCount();
  			};
  
  			/**
               * Get the height of broad-phase dynamic tree.
               */
  			World.prototype.getTreeHeight = function () {
  				return this.m_broadPhase.getTreeHeight();
  			};
  
  			/**
               * Get the balance of broad-phase dynamic tree.
               *
               * @returns {int}
               */
  			World.prototype.getTreeBalance = function () {
  				return this.m_broadPhase.getTreeBalance();
  			};
  
  			/**
               * Get the quality metric of broad-phase dynamic tree. The smaller the better.
               * The minimum is 1.
               *
               * @returns {float}
               */
  			World.prototype.getTreeQuality = function () {
  				return this.m_broadPhase.getTreeQuality();
  			};
  
  			/**
               * Shift the world origin. Useful for large worlds. The body shift formula is:
               * position -= newOrigin
               *
               * @param {Vec2} newOrigin The new origin with respect to the old origin
               */
  			World.prototype.shiftOrigin = function (newOrigin) {
  				_ASSERT && common.assert(this.m_locked == false);
  				if (this.m_locked) {
  					return;
  				}
  
  				for (var b = this.m_bodyList; b; b = b.m_next) {
  					b.m_xf.p.sub(newOrigin);
  					b.m_sweep.c0.sub(newOrigin);
  					b.m_sweep.c.sub(newOrigin);
  				}
  
  				for (var j = this.m_jointList; j; j = j.m_next) {
  					j.shiftOrigin(newOrigin);
  				}
  
  				this.m_broadPhase.shiftOrigin(newOrigin);
  			};
  
  			/**
               * @internal Used for deserialize.
               */
  			World.prototype._addBody = function (body) {
  				_ASSERT && common.assert(this.isLocked() === false);
  				if (this.isLocked()) {
  					return;
  				}
  
  				// Add to world doubly linked list.
  				body.m_prev = null;
  				body.m_next = this.m_bodyList;
  				if (this.m_bodyList) {
  					this.m_bodyList.m_prev = body;
  				}
  				this.m_bodyList = body;
  				++this.m_bodyCount;
  			};
  
  			/**
               * Create a rigid body given a definition. No reference to the definition is
               * retained.
               *
               * Warning: This function is locked during callbacks.
               *
               * @param {BodyDef|Vec2} def Body definition or position.
               * @param {float} angle Body angle if def is position.
               */
  			World.prototype.createBody = function (def, angle) {
  				_ASSERT && common.assert(this.isLocked() == false);
  				if (this.isLocked()) {
  					return null;
  				}
  
  				if (def && Vec2.isValid(def)) {
  					def = {
  						position: def,
  						angle: angle
  					};
  				}
  
  				var body = new Body(this, def);
  
  				this._addBody(body);
  
  				return body;
  			};
  
  			World.prototype.createDynamicBody = function (def, angle) {
  				if (!def) {
  					def = {};
  				} else if (Vec2.isValid(def)) {
  					def = { position: def, angle: angle };
  				}
  				def.type = 'dynamic';
  				return this.createBody(def);
  			};
  
  			World.prototype.createKinematicBody = function (def, angle) {
  				if (!def) {
  					def = {};
  				} else if (Vec2.isValid(def)) {
  					def = { position: def, angle: angle };
  				}
  				def.type = 'kinematic';
  				return this.createBody(def);
  			};
  
  			/**
               * Destroy a rigid body given a definition. No reference to the definition is
               * retained.
               *
               * Warning: This automatically deletes all associated shapes and joints.
               *
               * Warning: This function is locked during callbacks.
               *
               * @param {Body} b
               */
  			World.prototype.destroyBody = function (b) {
  				_ASSERT && common.assert(this.m_bodyCount > 0);
  				_ASSERT && common.assert(this.isLocked() == false);
  				if (this.isLocked()) {
  					return;
  				}
  
  				if (b.m_destroyed) {
  					return false;
  				}
  
  				// Delete the attached joints.
  				var je = b.m_jointList;
  				while (je) {
  					var je0 = je;
  					je = je.next;
  
  					this.publish('remove-joint', je0.joint);
  					this.destroyJoint(je0.joint);
  
  					b.m_jointList = je;
  				}
  				b.m_jointList = null;
  
  				// Delete the attached contacts.
  				var ce = b.m_contactList;
  				while (ce) {
  					var ce0 = ce;
  					ce = ce.next;
  
  					this.destroyContact(ce0.contact);
  
  					b.m_contactList = ce;
  				}
  				b.m_contactList = null;
  
  				// Delete the attached fixtures. This destroys broad-phase proxies.
  				var f = b.m_fixtureList;
  				while (f) {
  					var f0 = f;
  					f = f.m_next;
  
  					this.publish('remove-fixture', f0);
  					f0.destroyProxies(this.m_broadPhase);
  
  					b.m_fixtureList = f;
  				}
  				b.m_fixtureList = null;
  
  				// Remove world body list.
  				if (b.m_prev) {
  					b.m_prev.m_next = b.m_next;
  				}
  
  				if (b.m_next) {
  					b.m_next.m_prev = b.m_prev;
  				}
  
  				if (b == this.m_bodyList) {
  					this.m_bodyList = b.m_next;
  				}
  
  				b.m_destroyed = true;
  
  				--this.m_bodyCount;
  
  				this.publish('remove-body', b);
  
  				return true;
  			};
  
  			/**
               * Create a joint to constrain bodies together. No reference to the definition
               * is retained. This may cause the connected bodies to cease colliding.
               *
               * Warning: This function is locked during callbacks.
               *
               * @param {Joint} join
               * @param {Body} bodyB
               * @param {Body} bodyA
               */
  			World.prototype.createJoint = function (joint) {
  				_ASSERT && common.assert(!!joint.m_bodyA);
  				_ASSERT && common.assert(!!joint.m_bodyB);
  				_ASSERT && common.assert(this.isLocked() == false);
  				if (this.isLocked()) {
  					return null;
  				}
  
  				// Connect to the world list.
  				joint.m_prev = null;
  				joint.m_next = this.m_jointList;
  				if (this.m_jointList) {
  					this.m_jointList.m_prev = joint;
  				}
  				this.m_jointList = joint;
  				++this.m_jointCount;
  
  				// Connect to the bodies' doubly linked lists.
  				joint.m_edgeA.joint = joint;
  				joint.m_edgeA.other = joint.m_bodyB;
  				joint.m_edgeA.prev = null;
  				joint.m_edgeA.next = joint.m_bodyA.m_jointList;
  				if (joint.m_bodyA.m_jointList) joint.m_bodyA.m_jointList.prev = joint.m_edgeA;
  				joint.m_bodyA.m_jointList = joint.m_edgeA;
  
  				joint.m_edgeB.joint = joint;
  				joint.m_edgeB.other = joint.m_bodyA;
  				joint.m_edgeB.prev = null;
  				joint.m_edgeB.next = joint.m_bodyB.m_jointList;
  				if (joint.m_bodyB.m_jointList) joint.m_bodyB.m_jointList.prev = joint.m_edgeB;
  				joint.m_bodyB.m_jointList = joint.m_edgeB;
  
  				// If the joint prevents collisions, then flag any contacts for filtering.
  				if (joint.m_collideConnected == false) {
  					for (var edge = joint.m_bodyB.getContactList(); edge; edge = edge.next) {
  						if (edge.other == joint.m_bodyA) {
  							// Flag the contact for filtering at the next time step (where either
  							// body is awake).
  							edge.contact.flagForFiltering();
  						}
  					}
  				}
  
  				// Note: creating a joint doesn't wake the bodies.
  
  				return joint;
  			};
  
  			/**
               * Destroy a joint. This may cause the connected bodies to begin colliding.
               * Warning: This function is locked during callbacks.
               *
               * @param {Joint} join
               */
  			World.prototype.destroyJoint = function (joint) {
  				_ASSERT && common.assert(this.isLocked() == false);
  				if (this.isLocked()) {
  					return;
  				}
  
  				// Remove from the doubly linked list.
  				if (joint.m_prev) {
  					joint.m_prev.m_next = joint.m_next;
  				}
  
  				if (joint.m_next) {
  					joint.m_next.m_prev = joint.m_prev;
  				}
  
  				if (joint == this.m_jointList) {
  					this.m_jointList = joint.m_next;
  				}
  
  				// Disconnect from bodies.
  				var bodyA = joint.m_bodyA;
  				var bodyB = joint.m_bodyB;
  
  				// Wake up connected bodies.
  				bodyA.setAwake(true);
  				bodyB.setAwake(true);
  
  				// Remove from body 1.
  				if (joint.m_edgeA.prev) {
  					joint.m_edgeA.prev.next = joint.m_edgeA.next;
  				}
  
  				if (joint.m_edgeA.next) {
  					joint.m_edgeA.next.prev = joint.m_edgeA.prev;
  				}
  
  				if (joint.m_edgeA == bodyA.m_jointList) {
  					bodyA.m_jointList = joint.m_edgeA.next;
  				}
  
  				joint.m_edgeA.prev = null;
  				joint.m_edgeA.next = null;
  
  				// Remove from body 2
  				if (joint.m_edgeB.prev) {
  					joint.m_edgeB.prev.next = joint.m_edgeB.next;
  				}
  
  				if (joint.m_edgeB.next) {
  					joint.m_edgeB.next.prev = joint.m_edgeB.prev;
  				}
  
  				if (joint.m_edgeB == bodyB.m_jointList) {
  					bodyB.m_jointList = joint.m_edgeB.next;
  				}
  
  				joint.m_edgeB.prev = null;
  				joint.m_edgeB.next = null;
  
  				_ASSERT && common.assert(this.m_jointCount > 0);
  				--this.m_jointCount;
  
  				// If the joint prevents collisions, then flag any contacts for filtering.
  				if (joint.m_collideConnected == false) {
  					var edge = bodyB.getContactList();
  					while (edge) {
  						if (edge.other == bodyA) {
  							// Flag the contact for filtering at the next time step (where either
  							// body is awake).
  							edge.contact.flagForFiltering();
  						}
  
  						edge = edge.next;
  					}
  				}
  
  				this.publish('remove-joint', joint);
  			};
  
  			var s_step = new Solver.TimeStep(); // reuse
  
  			/**
               * Take a time step. This performs collision detection, integration, and
               * constraint solution.
               *
               * Broad-phase, narrow-phase, solve and solve time of impacts.
               *
               * @param {float} timeStep Time step, this should not vary.
               * @param {int} velocityIterations
               * @param {int} positionIterations
               */
  			World.prototype.step = function (timeStep, velocityIterations, positionIterations) {
  				if ((velocityIterations | 0) !== velocityIterations) {
  					// TODO: remove this in future
  					velocityIterations = 0;
  				}
  
  				velocityIterations = velocityIterations || this.m_velocityIterations;
  				positionIterations = positionIterations || this.m_positionIterations;
  
  				// TODO: move this to testbed
  				this.m_stepCount++;
  
  				// If new fixtures were added, we need to find the new contacts.
  				if (this.m_newFixture) {
  					this.findNewContacts();
  					this.m_newFixture = false;
  				}
  
  				this.m_locked = true;
  
  				s_step.reset(timeStep);
  				s_step.velocityIterations = velocityIterations;
  				s_step.positionIterations = positionIterations;
  				s_step.warmStarting = this.m_warmStarting;
  				s_step.blockSolve = this.m_blockSolve;
  
  				// Update contacts. This is where some contacts are destroyed.
  				this.updateContacts();
  
  				// Integrate velocities, solve velocity constraints, and integrate positions.
  				if (this.m_stepComplete && timeStep > 0.0) {
  					this.m_solver.solveWorld(s_step);
  
  					// Synchronize fixtures, check for out of range bodies.
  					for (var b = this.m_bodyList; b; b = b.getNext()) {
  						// If a body was not in an island then it did not move.
  						if (b.m_islandFlag == false) {
  							continue;
  						}
  
  						if (b.isStatic()) {
  							continue;
  						}
  
  						// Update fixtures (for broad-phase).
  						b.synchronizeFixtures();
  					}
  					// Look for new contacts.
  					this.findNewContacts();
  				}
  
  				// Handle TOI events.
  				if (this.m_continuousPhysics && timeStep > 0.0) {
  					this.m_solver.solveWorldTOI(s_step);
  				}
  
  				if (this.m_clearForces) {
  					this.clearForces();
  				}
  
  				this.m_locked = false;
  			};
  
  			/**
               * Call this method to find new contacts.
               */
  			World.prototype.findNewContacts = function () {
  				this.m_broadPhase.updatePairs(this.addPair);
  			};
  
  			/**
               * @private
               *
               * @param {FixtureProxy} proxyA
               * @param {FixtureProxy} proxyB
               */
  			World.prototype.createContact = function (proxyA, proxyB) {
  				var fixtureA = proxyA.fixture;
  				var fixtureB = proxyB.fixture;
  
  				var indexA = proxyA.childIndex;
  				var indexB = proxyB.childIndex;
  
  				var bodyA = fixtureA.getBody();
  				var bodyB = fixtureB.getBody();
  
  				// Are the fixtures on the same body?
  				if (bodyA == bodyB) {
  					return;
  				}
  
  				// TODO_ERIN use a hash table to remove a potential bottleneck when both
  				// bodies have a lot of contacts.
  				// Does a contact already exist?
  				var edge = bodyB.getContactList(); // ContactEdge
  				while (edge) {
  					if (edge.other == bodyA) {
  						var fA = edge.contact.getFixtureA();
  						var fB = edge.contact.getFixtureB();
  						var iA = edge.contact.getChildIndexA();
  						var iB = edge.contact.getChildIndexB();
  
  						if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) {
  							// A contact already exists.
  							return;
  						}
  
  						if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) {
  							// A contact already exists.
  							return;
  						}
  					}
  
  					edge = edge.next;
  				}
  
  				if (bodyB.shouldCollide(bodyA) == false) {
  					return;
  				}
  				if (fixtureB.shouldCollide(fixtureA) == false) {
  					return;
  				}
  
  				// Call the factory.
  				var contact = Contact.create(fixtureA, indexA, fixtureB, indexB);
  				if (contact == null) {
  					return;
  				}
  
  				// Insert into the world.
  				contact.m_prev = null;
  				if (this.m_contactList != null) {
  					contact.m_next = this.m_contactList;
  					this.m_contactList.m_prev = contact;
  				}
  				this.m_contactList = contact;
  
  				++this.m_contactCount;
  			};
  
  			/**
               * Removes old non-overlapping contacts, applies filters and updates contacts.
               */
  			World.prototype.updateContacts = function () {
  				// Update awake contacts.
  				var c;
  				var next_c = this.m_contactList;
  				while ((c = next_c)) {
  					next_c = c.getNext();
  					var fixtureA = c.getFixtureA();
  					var fixtureB = c.getFixtureB();
  					var indexA = c.getChildIndexA();
  					var indexB = c.getChildIndexB();
  					var bodyA = fixtureA.getBody();
  					var bodyB = fixtureB.getBody();
  
  					// Is this contact flagged for filtering?
  					if (c.m_filterFlag) {
  						if (bodyB.shouldCollide(bodyA) == false) {
  							this.destroyContact(c);
  							continue;
  						}
  
  						if (fixtureB.shouldCollide(fixtureA) == false) {
  							this.destroyContact(c);
  							continue;
  						}
  
  						// Clear the filtering flag.
  						c.m_filterFlag = false;
  					}
  
  					var activeA = bodyA.isAwake() && !bodyA.isStatic();
  					var activeB = bodyB.isAwake() && !bodyB.isStatic();
  
  					// At least one body must be awake and it must be dynamic or kinematic.
  					if (activeA == false && activeB == false) {
  						continue;
  					}
  
  					var proxyIdA = fixtureA.m_proxies[indexA].proxyId;
  					var proxyIdB = fixtureB.m_proxies[indexB].proxyId;
  					var overlap = this.m_broadPhase.testOverlap(proxyIdA, proxyIdB);
  
  					// Here we destroy contacts that cease to overlap in the broad-phase.
  					if (overlap == false) {
  						this.destroyContact(c);
  						continue;
  					}
  
  					// The contact persists.
  					c.update(this);
  				}
  			};
  
  			/**
               * @param {Contact} contact
               */
  			World.prototype.destroyContact = function (contact) {
  				Contact.destroy(contact, this);
  
  				// Remove from the world.
  				if (contact.m_prev) {
  					contact.m_prev.m_next = contact.m_next;
  				}
  				if (contact.m_next) {
  					contact.m_next.m_prev = contact.m_prev;
  				}
  				if (contact == this.m_contactList) {
  					this.m_contactList = contact.m_next;
  				}
  
  				--this.m_contactCount;
  			};
  
  			World.prototype._listeners = null;
  
  			/**
               * Register an event listener.
               *
               * @param {string} name
               * @param {function} listener
               */
  			World.prototype.on = function (name, listener) {
  				if (typeof name !== 'string' || typeof listener !== 'function') {
  					return this;
  				}
  				if (!this._listeners) {
  					this._listeners = {};
  				}
  				if (!this._listeners[name]) {
  					this._listeners[name] = [];
  				}
  				this._listeners[name].push(listener);
  				return this;
  			};
  
  			/**
               * Remove an event listener.
               *
               * @param {string} name
               * @param {function} listener
               */
  			World.prototype.off = function (name, listener) {
  				if (typeof name !== 'string' || typeof listener !== 'function') {
  					return this;
  				}
  				var listeners = this._listeners && this._listeners[name];
  				if (!listeners || !listeners.length) {
  					return this;
  				}
  				var index = listeners.indexOf(listener);
  				if (index >= 0) {
  					listeners.splice(index, 1);
  				}
  				return this;
  			};
  
  			World.prototype.publish = function (name, arg1, arg2, arg3) {
  				var listeners = this._listeners && this._listeners[name];
  				if (!listeners || !listeners.length) {
  					return 0;
  				}
  				for (var l = 0; l < listeners.length; l++) {
  					listeners[l].call(this, arg1, arg2, arg3);
  				}
  				return listeners.length;
  			};
  
  			/**
               * @event World#remove-body
               * @event World#remove-joint
               * @event World#remove-fixture
               *
               * Joints and fixtures are destroyed when their associated body is destroyed.
               * Register a destruction listener so that you may nullify references to these
               * joints and shapes.
               *
               * `function(object)` is called when any joint or fixture is about to
               * be destroyed due to the destruction of one of its attached or parent bodies.
               */
  
  			/**
               * @private
               * @param {Contact} contact
               */
  			World.prototype.beginContact = function (contact) {
  				this.publish('begin-contact', contact);
  			};
  
  			/**
               * @event World#begin-contact
               *
               * Called when two fixtures begin to touch.
               *
               * Implement contact callbacks to get contact information. You can use these
               * results for things like sounds and game logic. You can also get contact
               * results by traversing the contact lists after the time step. However, you
               * might miss some contacts because continuous physics leads to sub-stepping.
               * Additionally you may receive multiple callbacks for the same contact in a
               * single time step. You should strive to make your callbacks efficient because
               * there may be many callbacks per time step.
               *
               * Warning: You cannot create/destroy world entities inside these callbacks.
               */
  
  			/**
               * @private
               * @param {Contact} contact
               */
  			World.prototype.endContact = function (contact) {
  				this.publish('end-contact', contact);
  			};
  
  			/**
               * @event World#end-contact
               *
               * Called when two fixtures cease to touch.
               *
               * Implement contact callbacks to get contact information. You can use these
               * results for things like sounds and game logic. You can also get contact
               * results by traversing the contact lists after the time step. However, you
               * might miss some contacts because continuous physics leads to sub-stepping.
               * Additionally you may receive multiple callbacks for the same contact in a
               * single time step. You should strive to make your callbacks efficient because
               * there may be many callbacks per time step.
               *
               * Warning: You cannot create/destroy world entities inside these callbacks.
               */
  
  			/**
               * @private
               * @param {Contact} contact
               * @param {Manifold} oldManifold
               */
  			World.prototype.preSolve = function (contact, oldManifold) {
  				this.publish('pre-solve', contact, oldManifold);
  			};
  
  			/**
               * @event World#pre-solve
               *
               * This is called after a contact is updated. This allows you to inspect a
               * contact before it goes to the solver. If you are careful, you can modify the
               * contact manifold (e.g. disable contact). A copy of the old manifold is
               * provided so that you can detect changes. Note: this is called only for awake
               * bodies. Note: this is called even when the number of contact points is zero.
               * Note: this is not called for sensors. Note: if you set the number of contact
               * points to zero, you will not get an endContact callback. However, you may get
               * a beginContact callback the next step.
               *
               * Warning: You cannot create/destroy world entities inside these callbacks.
               */
  
  			/**
               * @private
               * @param {Contact} contact
               * @param {ContactImpulse} impulse
               */
  			World.prototype.postSolve = function (contact, impulse) {
  				this.publish('post-solve', contact, impulse);
  			};
  
  			/**
               * @event World#post-solve
               *
               * This lets you inspect a contact after the solver is finished. This is useful
               * for inspecting impulses. Note: the contact manifold does not include time of
               * impact impulses, which can be arbitrarily large if the sub-step is small.
               * Hence the impulse is provided explicitly in a separate data structure. Note:
               * this is only called for contacts that are touching, solid, and awake.
               *
               * Warning: You cannot create/destroy world entities inside these callbacks.
               */
  
  			/**
               * Register a contact filter to provide specific control over collision.
               * Otherwise the default filter is used (defaultFilter). The listener is owned
               * by you and must remain in scope.
               *
               * Moved to Fixture.
               */
  
  			/***/
  		},
  		/* 31 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var Settings = __webpack_require__(4);
  			var common = __webpack_require__(2);
  			var Pool = __webpack_require__(42);
  			var Vec2 = __webpack_require__(0);
  			var Math = __webpack_require__(1);
  			var AABB = __webpack_require__(17);
  
  			module.exports = DynamicTree;
  
  			/**
               * A node in the dynamic tree. The client does not interact with this directly.
               *
               * @prop {AABB} aabb Enlarged AABB
               * @prop {integer} height 0: leaf, -1: free node
               */
  			function TreeNode (id) {
  				this.id = id;
  				this.aabb = new AABB();
  				this.userData = null;
  				this.parent = null;
  				this.child1 = null;
  				this.child2 = null;
  				this.height = -1;
  
  				this.toString = function () {
  					return `${this.id}: ${this.userData}`;
  				};
  			}
  
  			TreeNode.prototype.isLeaf = function () {
  				return this.child1 == null;
  			};
  			/**
               * A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt. A
               * dynamic tree arranges data in a binary tree to accelerate queries such as
               * volume queries and ray casts. Leafs are proxies with an AABB. In the tree we
               * expand the proxy AABB by `aabbExtension` so that the proxy AABB is bigger
               * than the client object. This allows the client object to move by small
               * amounts without triggering a tree update.
               *
               * Nodes are pooled and relocatable, so we use node indices rather than
               * pointers.
               */
  			function DynamicTree () {
  				this.m_root = null;
  				this.m_nodes = {};
  				this.m_lastProxyId = 0;
  
  				this.m_pool = new Pool({
  					create: function () {
  						return new TreeNode();
  					}
  				});
  			}
  
  			/**
               * Get proxy user data.
               *
               * @return the proxy user data or 0 if the id is invalid.
               */
  			DynamicTree.prototype.getUserData = function (id) {
  				var node = this.m_nodes[id];
  				_ASSERT && common.assert(!!node);
  				return node.userData;
  			};
  
  			/**
               * Get the fat AABB for a node id.
               *
               * @return the proxy user data or 0 if the id is invalid.
               */
  			DynamicTree.prototype.getFatAABB = function (id) {
  				var node = this.m_nodes[id];
  				_ASSERT && common.assert(!!node);
  				return node.aabb;
  			};
  
  			DynamicTree.prototype.allocateNode = function () {
  				var node = this.m_pool.allocate();
  				node.id = ++this.m_lastProxyId;
  				node.userData = null;
  				node.parent = null;
  				node.child1 = null;
  				node.child2 = null;
  				node.height = -1;
  				this.m_nodes[node.id] = node;
  				return node;
  			};
  
  			DynamicTree.prototype.freeNode = function (node) {
  				this.m_pool.release(node);
  				node.height = -1;
  				delete this.m_nodes[node.id];
  			};
  
  			/**
               * Create a proxy in the tree as a leaf node. We return the index of the node
               * instead of a pointer so that we can grow the node pool.
               *
               * Create a proxy. Provide a tight fitting AABB and a userData pointer.
               */
  			DynamicTree.prototype.createProxy = function (aabb, userData) {
  				_ASSERT && common.assert(AABB.isValid(aabb));
  
  				var node = this.allocateNode();
  
  				node.aabb.set(aabb);
  
  				// Fatten the aabb.
  				AABB.extend(node.aabb, Settings.aabbExtension);
  
  				node.userData = userData;
  				node.height = 0;
  
  				this.insertLeaf(node);
  
  				return node.id;
  			};
  
  			/**
               * Destroy a proxy. This asserts if the id is invalid.
               */
  			DynamicTree.prototype.destroyProxy = function (id) {
  				var node = this.m_nodes[id];
  
  				_ASSERT && common.assert(!!node);
  				_ASSERT && common.assert(node.isLeaf());
  
  				this.removeLeaf(node);
  				this.freeNode(node);
  			};
  
  			/**
               * Move a proxy with a swepted AABB. If the proxy has moved outside of its
               * fattened AABB, then the proxy is removed from the tree and re-inserted.
               * Otherwise the function returns immediately.
               *
               * @param id
               * @param aabb
               * @param {Vec2} d Displacement
               *
               * @return true if the proxy was re-inserted.
               */
  			DynamicTree.prototype.moveProxy = function (id, aabb, d) {
  				_ASSERT && common.assert(AABB.isValid(aabb));
  				_ASSERT && common.assert(!d || Vec2.isValid(d));
  
  				var node = this.m_nodes[id];
  
  				_ASSERT && common.assert(!!node);
  				_ASSERT && common.assert(node.isLeaf());
  
  				if (node.aabb.contains(aabb)) {
  					return false;
  				}
  
  				this.removeLeaf(node);
  
  				node.aabb.set(aabb);
  
  				// Extend AABB.
  				aabb = node.aabb;
  				AABB.extend(aabb, Settings.aabbExtension);
  
  				// Predict AABB displacement.
  				// var d = Vec2.mul(Settings.aabbMultiplier, displacement);
  
  				if (d.x < 0.0) {
  					aabb.lowerBound.x += d.x * Settings.aabbMultiplier;
  				} else {
  					aabb.upperBound.x += d.x * Settings.aabbMultiplier;
  				}
  
  				if (d.y < 0.0) {
  					aabb.lowerBound.y += d.y * Settings.aabbMultiplier;
  				} else {
  					aabb.upperBound.y += d.y * Settings.aabbMultiplier;
  				}
  
  				this.insertLeaf(node);
  
  				return true;
  			};
  
  			DynamicTree.prototype.insertLeaf = function (leaf) {
  				_ASSERT && common.assert(AABB.isValid(leaf.aabb));
  
  				if (this.m_root == null) {
  					this.m_root = leaf;
  					this.m_root.parent = null;
  					return;
  				}
  
  				// Find the best sibling for this node
  				var leafAABB = leaf.aabb;
  				var index = this.m_root;
  				while (index.isLeaf() == false) {
  					var child1 = index.child1;
  					var child2 = index.child2;
  
  					var area = index.aabb.getPerimeter();
  
  					var combinedAABB = new AABB();
  					combinedAABB.combine(index.aabb, leafAABB);
  					var combinedArea = combinedAABB.getPerimeter();
  
  					// Cost of creating a new parent for this node and the new leaf
  					var cost = 2.0 * combinedArea;
  
  					// Minimum cost of pushing the leaf further down the tree
  					var inheritanceCost = 2.0 * (combinedArea - area);
  
  					// Cost of descending into child1
  					var cost1;
  					if (child1.isLeaf()) {
  						var aabb = new AABB();
  						aabb.combine(leafAABB, child1.aabb);
  						cost1 = aabb.getPerimeter() + inheritanceCost;
  					} else {
  						var aabb = new AABB();
  						aabb.combine(leafAABB, child1.aabb);
  						var oldArea = child1.aabb.getPerimeter();
  						var newArea = aabb.getPerimeter();
  						cost1 = newArea - oldArea + inheritanceCost;
  					}
  
  					// Cost of descending into child2
  					var cost2;
  					if (child2.isLeaf()) {
  						var aabb = new AABB();
  						aabb.combine(leafAABB, child2.aabb);
  						cost2 = aabb.getPerimeter() + inheritanceCost;
  					} else {
  						var aabb = new AABB();
  						aabb.combine(leafAABB, child2.aabb);
  						var oldArea = child2.aabb.getPerimeter();
  						var newArea = aabb.getPerimeter();
  						cost2 = newArea - oldArea + inheritanceCost;
  					}
  
  					// Descend according to the minimum cost.
  					if (cost < cost1 && cost < cost2) {
  						break;
  					}
  
  					// Descend
  					if (cost1 < cost2) {
  						index = child1;
  					} else {
  						index = child2;
  					}
  				}
  
  				var sibling = index;
  
  				// Create a new parent.
  				var oldParent = sibling.parent;
  				var newParent = this.allocateNode();
  				newParent.parent = oldParent;
  				newParent.userData = null;
  				newParent.aabb.combine(leafAABB, sibling.aabb);
  				newParent.height = sibling.height + 1;
  
  				if (oldParent != null) {
  					// The sibling was not the root.
  					if (oldParent.child1 == sibling) {
  						oldParent.child1 = newParent;
  					} else {
  						oldParent.child2 = newParent;
  					}
  
  					newParent.child1 = sibling;
  					newParent.child2 = leaf;
  					sibling.parent = newParent;
  					leaf.parent = newParent;
  				} else {
  					// The sibling was the root.
  					newParent.child1 = sibling;
  					newParent.child2 = leaf;
  					sibling.parent = newParent;
  					leaf.parent = newParent;
  					this.m_root = newParent;
  				}
  
  				// Walk back up the tree fixing heights and AABBs
  				index = leaf.parent;
  				while (index != null) {
  					index = this.balance(index);
  
  					var child1 = index.child1;
  					var child2 = index.child2;
  
  					_ASSERT && common.assert(child1 != null);
  					_ASSERT && common.assert(child2 != null);
  
  					index.height = 1 + Math.max(child1.height, child2.height);
  					index.aabb.combine(child1.aabb, child2.aabb);
  
  					index = index.parent;
  				}
  
  				// validate();
  			};
  
  			DynamicTree.prototype.removeLeaf = function (leaf) {
  				if (leaf == this.m_root) {
  					this.m_root = null;
  					return;
  				}
  
  				var parent = leaf.parent;
  				var grandParent = parent.parent;
  				var sibling;
  				if (parent.child1 == leaf) {
  					sibling = parent.child2;
  				} else {
  					sibling = parent.child1;
  				}
  
  				if (grandParent != null) {
  					// Destroy parent and connect sibling to grandParent.
  					if (grandParent.child1 == parent) {
  						grandParent.child1 = sibling;
  					} else {
  						grandParent.child2 = sibling;
  					}
  					sibling.parent = grandParent;
  					this.freeNode(parent);
  
  					// Adjust ancestor bounds.
  					var index = grandParent;
  					while (index != null) {
  						index = this.balance(index);
  
  						var child1 = index.child1;
  						var child2 = index.child2;
  
  						index.aabb.combine(child1.aabb, child2.aabb);
  						index.height = 1 + Math.max(child1.height, child2.height);
  
  						index = index.parent;
  					}
  				} else {
  					this.m_root = sibling;
  					sibling.parent = null;
  					this.freeNode(parent);
  				}
  
  				// validate();
  			};
  
  			/**
               * Perform a left or right rotation if node A is imbalanced. Returns the new
               * root index.
               */
  			DynamicTree.prototype.balance = function (iA) {
  				_ASSERT && common.assert(iA != null);
  
  				var A = iA;
  				if (A.isLeaf() || A.height < 2) {
  					return iA;
  				}
  
  				var B = A.child1;
  				var C = A.child2;
  
  				var balance = C.height - B.height;
  
  				// Rotate C up
  				if (balance > 1) {
  					var F = C.child1;
  					var G = C.child2;
  
  					// Swap A and C
  					C.child1 = A;
  					C.parent = A.parent;
  					A.parent = C;
  
  					// A's old parent should point to C
  					if (C.parent != null) {
  						if (C.parent.child1 == iA) {
  							C.parent.child1 = C;
  						} else {
  							C.parent.child2 = C;
  						}
  					} else {
  						this.m_root = C;
  					}
  
  					// Rotate
  					if (F.height > G.height) {
  						C.child2 = F;
  						A.child2 = G;
  						G.parent = A;
  						A.aabb.combine(B.aabb, G.aabb);
  						C.aabb.combine(A.aabb, F.aabb);
  
  						A.height = 1 + Math.max(B.height, G.height);
  						C.height = 1 + Math.max(A.height, F.height);
  					} else {
  						C.child2 = G;
  						A.child2 = F;
  						F.parent = A;
  						A.aabb.combine(B.aabb, F.aabb);
  						C.aabb.combine(A.aabb, G.aabb);
  
  						A.height = 1 + Math.max(B.height, F.height);
  						C.height = 1 + Math.max(A.height, G.height);
  					}
  
  					return C;
  				}
  
  				// Rotate B up
  				if (balance < -1) {
  					var D = B.child1;
  					var E = B.child2;
  
  					// Swap A and B
  					B.child1 = A;
  					B.parent = A.parent;
  					A.parent = B;
  
  					// A's old parent should point to B
  					if (B.parent != null) {
  						if (B.parent.child1 == A) {
  							B.parent.child1 = B;
  						} else {
  							B.parent.child2 = B;
  						}
  					} else {
  						this.m_root = B;
  					}
  
  					// Rotate
  					if (D.height > E.height) {
  						B.child2 = D;
  						A.child1 = E;
  						E.parent = A;
  						A.aabb.combine(C.aabb, E.aabb);
  						B.aabb.combine(A.aabb, D.aabb);
  
  						A.height = 1 + Math.max(C.height, E.height);
  						B.height = 1 + Math.max(A.height, D.height);
  					} else {
  						B.child2 = E;
  						A.child1 = D;
  						D.parent = A;
  						A.aabb.combine(C.aabb, D.aabb);
  						B.aabb.combine(A.aabb, E.aabb);
  
  						A.height = 1 + Math.max(C.height, D.height);
  						B.height = 1 + Math.max(A.height, E.height);
  					}
  
  					return B;
  				}
  
  				return A;
  			};
  
  			/**
               * Compute the height of the binary tree in O(N) time. Should not be called
               * often.
               */
  			DynamicTree.prototype.getHeight = function () {
  				if (this.m_root == null) {
  					return 0;
  				}
  
  				return this.m_root.height;
  			};
  
  			/**
               * Get the ratio of the sum of the node areas to the root area.
               */
  			DynamicTree.prototype.getAreaRatio = function () {
  				if (this.m_root == null) {
  					return 0.0;
  				}
  
  				var root = this.m_root;
  				var rootArea = root.aabb.getPerimeter();
  
  				var totalArea = 0.0;
  				var node;
  				var it = iteratorPool.allocate().preorder(this.m_root);
  				while ((node = it.next())) {
  					if (node.height < 0) {
  						// Free node in pool
  						continue;
  					}
  
  					totalArea += node.aabb.getPerimeter();
  				}
  
  				iteratorPool.release(it);
  
  				return totalArea / rootArea;
  			};
  
  			/**
               * Compute the height of a sub-tree.
               */
  			DynamicTree.prototype.computeHeight = function (id) {
  				var node;
  				if (typeof id !== 'undefined') {
  					node = this.m_nodes[id];
  				} else {
  					node = this.m_root;
  				}
  
  				// _ASSERT && common.assert(0 <= id && id < this.m_nodeCapacity);
  
  				if (node.isLeaf()) {
  					return 0;
  				}
  
  				var height1 = this.computeHeight(node.child1.id);
  				var height2 = this.computeHeight(node.child2.id);
  				return 1 + Math.max(height1, height2);
  			};
  
  			DynamicTree.prototype.validateStructure = function (node) {
  				if (node == null) {
  					return;
  				}
  
  				if (node == this.m_root) {
  					_ASSERT && common.assert(node.parent == null);
  				}
  
  				var child1 = node.child1;
  				var child2 = node.child2;
  
  				if (node.isLeaf()) {
  					_ASSERT && common.assert(child1 == null);
  					_ASSERT && common.assert(child2 == null);
  					_ASSERT && common.assert(node.height == 0);
  					return;
  				}
  
  				// _ASSERT && common.assert(0 <= child1 && child1 < this.m_nodeCapacity);
  				// _ASSERT && common.assert(0 <= child2 && child2 < this.m_nodeCapacity);
  
  				_ASSERT && common.assert(child1.parent == node);
  				_ASSERT && common.assert(child2.parent == node);
  
  				this.validateStructure(child1);
  				this.validateStructure(child2);
  			};
  
  			DynamicTree.prototype.validateMetrics = function (node) {
  				if (node == null) {
  					return;
  				}
  
  				var child1 = node.child1;
  				var child2 = node.child2;
  
  				if (node.isLeaf()) {
  					_ASSERT && common.assert(child1 == null);
  					_ASSERT && common.assert(child2 == null);
  					_ASSERT && common.assert(node.height == 0);
  					return;
  				}
  
  				// _ASSERT && common.assert(0 <= child1 && child1 < this.m_nodeCapacity);
  				// _ASSERT && common.assert(0 <= child2 && child2 < this.m_nodeCapacity);
  
  				var height1 = child1.height;
  				var height2 = child2.height;
  				var height = 1 + Math.max(height1, height2);
  				_ASSERT && common.assert(node.height == height);
  
  				var aabb = new AABB();
  				aabb.combine(child1.aabb, child2.aabb);
  
  				_ASSERT && common.assert(AABB.areEqual(aabb, node.aabb));
  
  				this.validateMetrics(child1);
  				this.validateMetrics(child2);
  			};
  
  			// Validate this tree. For testing.
  			DynamicTree.prototype.validate = function () {
  				this.validateStructure(this.m_root);
  				this.validateMetrics(this.m_root);
  
  				_ASSERT && common.assert(this.getHeight() == this.computeHeight());
  			};
  
  			/**
               * Get the maximum balance of an node in the tree. The balance is the difference
               * in height of the two children of a node.
               */
  			DynamicTree.prototype.getMaxBalance = function () {
  				var maxBalance = 0;
  				var node;
  				var it = iteratorPool.allocate().preorder(this.m_root);
  				while ((node = it.next())) {
  					if (node.height <= 1) {
  						continue;
  					}
  
  					_ASSERT && common.assert(node.isLeaf() == false);
  
  					var balance = Math.abs(node.child2.height - node.child1.height);
  					maxBalance = Math.max(maxBalance, balance);
  				}
  				iteratorPool.release(it);
  
  				return maxBalance;
  			};
  
  			/**
               * Build an optimal tree. Very expensive. For testing.
               */
  			DynamicTree.prototype.rebuildBottomUp = function () {
  				var nodes = [];
  				var count = 0;
  
  				// Build array of leaves. Free the rest.
  				var node;
  				var it = iteratorPool.allocate().preorder(this.m_root);
  				while ((node = it.next())) {
  					if (node.height < 0) {
  						// free node in pool
  						continue;
  					}
  
  					if (node.isLeaf()) {
  						node.parent = null;
  						nodes[count] = node;
  						++count;
  					} else {
  						this.freeNode(node);
  					}
  				}
  				iteratorPool.release(it);
  
  				while (count > 1) {
  					var minCost = Infinity;
  					var iMin = -1;
  					var jMin = -1;
  					for (var i = 0; i < count; ++i) {
  						var aabbi = nodes[i].aabb;
  						for (var j = i + 1; j < count; ++j) {
  							var aabbj = nodes[j].aabb;
  							var b = new AABB();
  							b.combine(aabbi, aabbj);
  							var cost = b.getPerimeter();
  							if (cost < minCost) {
  								iMin = i;
  								jMin = j;
  								minCost = cost;
  							}
  						}
  					}
  
  					var child1 = nodes[iMin];
  					var child2 = nodes[jMin];
  
  					var parent = this.allocateNode();
  					parent.child1 = child1;
  					parent.child2 = child2;
  					parent.height = 1 + Math.max(child1.height, child2.height);
  					parent.aabb.combine(child1.aabb, child2.aabb);
  					parent.parent = null;
  
  					child1.parent = parent;
  					child2.parent = parent;
  
  					nodes[jMin] = nodes[count - 1];
  					nodes[iMin] = parent;
  					--count;
  				}
  
  				this.m_root = nodes[0];
  
  				this.validate();
  			};
  
  			/**
               * Shift the world origin. Useful for large worlds. The shift formula is:
               * position -= newOrigin
               *
               * @param newOrigin The new origin with respect to the old origin
               */
  			DynamicTree.prototype.shiftOrigin = function (newOrigin) {
  				// Build array of leaves. Free the rest.
  				var node;
  				var it = iteratorPool.allocate().preorder(this.m_root);
  				while ((node = it.next())) {
  					var aabb = node.aabb;
  					aabb.lowerBound.x -= newOrigin.x;
  					aabb.lowerBound.y -= newOrigin.y;
  					aabb.upperBound.x -= newOrigin.x;
  					aabb.upperBound.y -= newOrigin.y;
  				}
  				iteratorPool.release(it);
  			};
  
  			/**
               * @function {DynamicTree~queryCallback}
               *
               * @param id Node id.
               */
  
  			/**
               * Query an AABB for overlapping proxies. The callback class is called for each
               * proxy that overlaps the supplied AABB.
               *
               * @param {DynamicTree~queryCallback} queryCallback
               */
  			DynamicTree.prototype.query = function (aabb, queryCallback) {
  				_ASSERT && common.assert(typeof queryCallback === 'function');
  				var stack = stackPool.allocate();
  
  				stack.push(this.m_root);
  				while (stack.length > 0) {
  					var node = stack.pop();
  					if (node == null) {
  						continue;
  					}
  
  					if (AABB.testOverlap(node.aabb, aabb)) {
  						if (node.isLeaf()) {
  							var proceed = queryCallback(node.id);
  							if (proceed == false) {
  								return;
  							}
  						} else {
  							stack.push(node.child1);
  							stack.push(node.child2);
  						}
  					}
  				}
  
  				stackPool.release(stack);
  			};
  
  			/**
               * Ray-cast against the proxies in the tree. This relies on the callback to
               * perform a exact ray-cast in the case were the proxy contains a shape. The
               * callback also performs the any collision filtering. This has performance
               * roughly equal to k * log(n), where k is the number of collisions and n is the
               * number of proxies in the tree.
               *
               * @param input The ray-cast input data. The ray extends from p1 to p1 +
               *          maxFraction * (p2 - p1).
               * @param rayCastCallback A function that is called for each proxy that is hit by
               *          the ray.
               */
  			DynamicTree.prototype.rayCast = function (input, rayCastCallback) {
  				// TODO GC
  				_ASSERT && common.assert(typeof rayCastCallback === 'function');
  				var p1 = input.p1;
  				var p2 = input.p2;
  				var r = Vec2.sub(p2, p1);
  				_ASSERT && common.assert(r.lengthSquared() > 0.0);
  				r.normalize();
  
  				// v is perpendicular to the segment.
  				var v = Vec2.cross(1.0, r);
  				var abs_v = Vec2.abs(v);
  
  				// Separating axis for segment (Gino, p80).
  				// |dot(v, p1 - c)| > dot(|v|, h)
  
  				var maxFraction = input.maxFraction;
  
  				// Build a bounding box for the segment.
  				var segmentAABB = new AABB();
  				var t = Vec2.combine(1 - maxFraction, p1, maxFraction, p2);
  				segmentAABB.combinePoints(p1, t);
  
  				var stack = stackPool.allocate();
  				var subInput = inputPool.allocate();
  
  				stack.push(this.m_root);
  				while (stack.length > 0) {
  					var node = stack.pop();
  					if (node == null) {
  						continue;
  					}
  
  					if (AABB.testOverlap(node.aabb, segmentAABB) == false) {
  						continue;
  					}
  
  					// Separating axis for segment (Gino, p80).
  					// |dot(v, p1 - c)| > dot(|v|, h)
  					var c = node.aabb.getCenter();
  					var h = node.aabb.getExtents();
  					var separation = Math.abs(Vec2.dot(v, Vec2.sub(p1, c))) - Vec2.dot(abs_v, h);
  					if (separation > 0.0) {
  						continue;
  					}
  
  					if (node.isLeaf()) {
  						subInput.p1 = Vec2.clone(input.p1);
  						subInput.p2 = Vec2.clone(input.p2);
  						subInput.maxFraction = maxFraction;
  
  						var value = rayCastCallback(subInput, node.id);
  
  						if (value == 0.0) {
  							// The client has terminated the ray cast.
  							return;
  						}
  
  						if (value > 0.0) {
  							// update segment bounding box.
  							maxFraction = value;
  							t = Vec2.combine(1 - maxFraction, p1, maxFraction, p2);
  							segmentAABB.combinePoints(p1, t);
  						}
  					} else {
  						stack.push(node.child1);
  						stack.push(node.child2);
  					}
  				}
  
  				stackPool.release(stack);
  				inputPool.release(subInput);
  			};
  
  			var inputPool = new Pool({
  				create: function () {
  					return {};
  				},
  				release: function (stack) {}
  			});
  
  			var stackPool = new Pool({
  				create: function () {
  					return [];
  				},
  				release: function (stack) {
  					stack.length = 0;
  				}
  			});
  
  			var iteratorPool = new Pool({
  				create: function () {
  					return new Iterator();
  				},
  				release: function (iterator) {
  					iterator.close();
  				}
  			});
  
  			function Iterator () {
  				var parents = [];
  				var states = [];
  				return {
  					preorder: function (root) {
  						parents.length = 0;
  						parents.push(root);
  						states.length = 0;
  						states.push(0);
  						return this;
  					},
  					next: function () {
  						while (parents.length > 0) {
  							var i = parents.length - 1;
  							var node = parents[i];
  							if (states[i] === 0) {
  								states[i] = 1;
  								return node;
  							}
  							if (states[i] === 1) {
  								states[i] = 2;
  								if (node.child1) {
  									parents.push(node.child1);
  									states.push(1);
  									return node.child1;
  								}
  							}
  							if (states[i] === 2) {
  								states[i] = 3;
  								if (node.child2) {
  									parents.push(node.child2);
  									states.push(1);
  									return node.child2;
  								}
  							}
  							parents.pop();
  							states.pop();
  						}
  					},
  					close: function () {
  						parents.length = 0;
  					}
  				};
  			}
  
  			/***/
  		},
  		/* 32 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Fixture;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  
  			var AABB = __webpack_require__(17);
  
  			var Shape = __webpack_require__(16);
  
  			/**
               * @typedef {Object} FixtureDef
               *
               * A fixture definition is used to create a fixture. This class defines an
               * abstract fixture definition. You can reuse fixture definitions safely.
               *
               * @prop friction The friction coefficient, usually in the range [0,1]
               * @prop restitution The restitution (elasticity) usually in the range [0,1]
               * @prop density The density, usually in kg/m^2
               * @prop isSensor A sensor shape collects contact information but never
               *       generates a collision response
               * @prop userData
               * @prop filterGroupIndex Zero, positive or negative collision group. Fixtures with same positive groupIndex always collide and fixtures with same
               * negative groupIndex never collide.
               * @prop filterCategoryBits Collision category bit or bits that this fixture belongs
               *       to. If groupIndex is zero or not matching, then at least one bit in this fixture
               * categoryBits should match other fixture maskBits and vice versa.
               * @prop filterMaskBits Collision category bit or bits that this fixture accept for
               *       collision.
               */
  			var FixtureDef = {
  				userData: null,
  				friction: 0.2,
  				restitution: 0.0,
  				density: 0.0,
  				isSensor: false,
  
  				filterGroupIndex: 0,
  				filterCategoryBits: 0x0001,
  				filterMaskBits: 0xffff
  			};
  
  			/**
               * This proxy is used internally to connect shape children to the broad-phase.
               */
  			function FixtureProxy (fixture, childIndex) {
  				this.aabb = new AABB();
  				this.fixture = fixture;
  				this.childIndex = childIndex;
  				this.proxyId;
  			}
  
  			/**
               * A fixture is used to attach a shape to a body for collision detection. A
               * fixture inherits its transform from its parent. Fixtures hold additional
               * non-geometric data such as friction, collision filters, etc. Fixtures are
               * created via Body.createFixture.
               *
               * @param {Body} body
               * @param {Shape|FixtureDef} shape Shape of fixture definition.
               * @param {FixtureDef|number} def Fixture definition or number.
               */
  			function Fixture (body, shape, def) {
  				if (shape.shape) {
  					def = shape;
  					shape = shape.shape;
  				} else if (typeof def === 'number') {
  					def = { density: def };
  				}
  
  				def = options(def, FixtureDef);
  
  				this.m_body = body;
  
  				this.m_friction = def.friction;
  				this.m_restitution = def.restitution;
  				this.m_density = def.density;
  				this.m_isSensor = def.isSensor;
  
  				this.m_filterGroupIndex = def.filterGroupIndex;
  				this.m_filterCategoryBits = def.filterCategoryBits;
  				this.m_filterMaskBits = def.filterMaskBits;
  
  				// TODO validate shape
  				this.m_shape = shape; // .clone();
  
  				this.m_next = null;
  
  				this.m_proxies = [];
  				this.m_proxyCount = 0;
  
  				var childCount = this.m_shape.getChildCount();
  				for (var i = 0; i < childCount; ++i) {
  					this.m_proxies[i] = new FixtureProxy(this, i);
  				}
  
  				this.m_userData = def.userData;
  			}
  
  			/**
               * Re-setup fixture.
               * @private
               */
  			Fixture.prototype._reset = function () {
  				var body = this.getBody();
  				var broadPhase = body.m_world.m_broadPhase;
  				this.destroyProxies(broadPhase);
  				if (this.m_shape._reset) {
  					this.m_shape._reset();
  				}
  				var childCount = this.m_shape.getChildCount();
  				for (var i = 0; i < childCount; ++i) {
  					this.m_proxies[i] = new FixtureProxy(this, i);
  				}
  				this.createProxies(broadPhase, body.m_xf);
  				body.resetMassData();
  			};
  
  			Fixture.prototype._serialize = function () {
  				return {
  					friction: this.m_friction,
  					restitution: this.m_restitution,
  					density: this.m_density,
  					isSensor: this.m_isSensor,
  
  					filterGroupIndex: this.m_filterGroupIndex,
  					filterCategoryBits: this.m_filterCategoryBits,
  					filterMaskBits: this.m_filterMaskBits,
  
  					shape: this.m_shape
  				};
  			};
  
  			Fixture._deserialize = function (data, body, restore) {
  				var shape = restore(Shape, data.shape);
  				var fixture = shape && new Fixture(body, shape, data);
  				return fixture;
  			};
  
  			/**
               * Get the type of the child shape. You can use this to down cast to the
               * concrete shape.
               */
  			Fixture.prototype.getType = function () {
  				return this.m_shape.getType();
  			};
  
  			/**
               * Get the child shape. You can modify the child shape, however you should not
               * change the number of vertices because this will crash some collision caching
               * mechanisms. Manipulating the shape may lead to non-physical behavior.
               */
  			Fixture.prototype.getShape = function () {
  				return this.m_shape;
  			};
  			/**
               * A sensor shape collects contact information but never generates a collision
               * response.
               */
  			Fixture.prototype.isSensor = function () {
  				return this.m_isSensor;
  			};
  
  			/**
               * Set if this fixture is a sensor.
               */
  			Fixture.prototype.setSensor = function (sensor) {
  				if (sensor != this.m_isSensor) {
  					this.m_body.setAwake(true);
  					this.m_isSensor = sensor;
  				}
  			};
  
  			/**
               * Get the contact filtering data.
               */
  			// Fixture.prototype.getFilterData = function() {
  			//   return this.m_filter;
  			// }
  
  			/**
               * Get the user data that was assigned in the fixture definition. Use this to
               * store your application specific data.
               */
  			Fixture.prototype.getUserData = function () {
  				return this.m_userData;
  			};
  
  			/**
               * Set the user data. Use this to store your application specific data.
               */
  			Fixture.prototype.setUserData = function (data) {
  				this.m_userData = data;
  			};
  
  			/**
               * Get the parent body of this fixture. This is null if the fixture is not
               * attached.
               */
  			Fixture.prototype.getBody = function () {
  				return this.m_body;
  			};
  
  			/**
               * Get the next fixture in the parent body's fixture list.
               */
  			Fixture.prototype.getNext = function () {
  				return this.m_next;
  			};
  
  			/**
               * Get the density of this fixture.
               */
  			Fixture.prototype.getDensity = function () {
  				return this.m_density;
  			};
  
  			/**
               * Set the density of this fixture. This will _not_ automatically adjust the
               * mass of the body. You must call Body.resetMassData to update the body's mass.
               */
  			Fixture.prototype.setDensity = function (density) {
  				_ASSERT && common.assert(Math.isFinite(density) && density >= 0.0);
  				this.m_density = density;
  			};
  
  			/**
               * Get the coefficient of friction, usually in the range [0,1].
               */
  			Fixture.prototype.getFriction = function () {
  				return this.m_friction;
  			};
  
  			/**
               * Set the coefficient of friction. This will not change the friction of
               * existing contacts.
               */
  			Fixture.prototype.setFriction = function (friction) {
  				this.m_friction = friction;
  			};
  
  			/**
               * Get the coefficient of restitution.
               */
  			Fixture.prototype.getRestitution = function () {
  				return this.m_restitution;
  			};
  
  			/**
               * Set the coefficient of restitution. This will not change the restitution of
               * existing contacts.
               */
  			Fixture.prototype.setRestitution = function (restitution) {
  				this.m_restitution = restitution;
  			};
  
  			/**
               * Test a point in world coordinates for containment in this fixture.
               */
  			Fixture.prototype.testPoint = function (p) {
  				return this.m_shape.testPoint(this.m_body.getTransform(), p);
  			};
  
  			/**
               * Cast a ray against this shape.
               */
  			Fixture.prototype.rayCast = function (output, input, childIndex) {
  				return this.m_shape.rayCast(output, input, this.m_body.getTransform(), childIndex);
  			};
  
  			/**
               * Get the mass data for this fixture. The mass data is based on the density and
               * the shape. The rotational inertia is about the shape's origin. This operation
               * may be expensive.
               */
  			Fixture.prototype.getMassData = function (massData) {
  				this.m_shape.computeMass(massData, this.m_density);
  			};
  
  			/**
               * Get the fixture's AABB. This AABB may be enlarge and/or stale. If you need a
               * more accurate AABB, compute it using the shape and the body transform.
               */
  			Fixture.prototype.getAABB = function (childIndex) {
  				_ASSERT && common.assert(childIndex >= 0 && childIndex < this.m_proxyCount);
  				return this.m_proxies[childIndex].aabb;
  			};
  
  			/**
               * These support body activation/deactivation.
               */
  			Fixture.prototype.createProxies = function (broadPhase, xf) {
  				_ASSERT && common.assert(this.m_proxyCount == 0);
  
  				// Create proxies in the broad-phase.
  				this.m_proxyCount = this.m_shape.getChildCount();
  
  				for (var i = 0; i < this.m_proxyCount; ++i) {
  					var proxy = this.m_proxies[i];
  					this.m_shape.computeAABB(proxy.aabb, xf, i);
  					proxy.proxyId = broadPhase.createProxy(proxy.aabb, proxy);
  				}
  			};
  
  			Fixture.prototype.destroyProxies = function (broadPhase) {
  				// Destroy proxies in the broad-phase.
  				for (var i = 0; i < this.m_proxyCount; ++i) {
  					var proxy = this.m_proxies[i];
  					broadPhase.destroyProxy(proxy.proxyId);
  					proxy.proxyId = null;
  				}
  
  				this.m_proxyCount = 0;
  			};
  
  			/**
               * Updates this fixture proxy in broad-phase (with combined AABB of current and
               * next transformation).
               */
  			Fixture.prototype.synchronize = function (broadPhase, xf1, xf2) {
  				for (var i = 0; i < this.m_proxyCount; ++i) {
  					var proxy = this.m_proxies[i];
  					// Compute an AABB that covers the swept shape (may miss some rotation
  					// effect).
  					var aabb1 = new AABB();
  					var aabb2 = new AABB();
  					this.m_shape.computeAABB(aabb1, xf1, proxy.childIndex);
  					this.m_shape.computeAABB(aabb2, xf2, proxy.childIndex);
  
  					proxy.aabb.combine(aabb1, aabb2);
  
  					var displacement = Vec2.sub(xf2.p, xf1.p);
  
  					broadPhase.moveProxy(proxy.proxyId, proxy.aabb, displacement);
  				}
  			};
  
  			/**
               * Set the contact filtering data. This will not update contacts until the next
               * time step when either parent body is active and awake. This automatically
               * calls refilter.
               */
  			Fixture.prototype.setFilterData = function (filter) {
  				this.m_filterGroupIndex = filter.groupIndex;
  				this.m_filterCategoryBits = filter.categoryBits;
  				this.m_filterMaskBits = filter.maskBits;
  				this.refilter();
  			};
  
  			Fixture.prototype.getFilterGroupIndex = function () {
  				return this.m_filterGroupIndex;
  			};
  
  			Fixture.prototype.setFilterGroupIndex = function (groupIndex) {
  				return (this.m_filterGroupIndex = groupIndex);
  			};
  
  			Fixture.prototype.getFilterCategoryBits = function () {
  				return this.m_filterCategoryBits;
  			};
  
  			Fixture.prototype.setFilterCategoryBits = function (categoryBits) {
  				this.m_filterCategoryBits = categoryBits;
  			};
  
  			Fixture.prototype.getFilterMaskBits = function () {
  				return this.m_filterMaskBits;
  			};
  
  			Fixture.prototype.setFilterMaskBits = function (maskBits) {
  				this.m_filterMaskBits = maskBits;
  			};
  
  			/**
               * Call this if you want to establish collision that was previously disabled by
               * ContactFilter.
               */
  			Fixture.prototype.refilter = function () {
  				if (this.m_body == null) {
  					return;
  				}
  
  				// Flag associated contacts for filtering.
  				var edge = this.m_body.getContactList();
  				while (edge) {
  					var contact = edge.contact;
  					var fixtureA = contact.getFixtureA();
  					var fixtureB = contact.getFixtureB();
  					if (fixtureA == this || fixtureB == this) {
  						contact.flagForFiltering();
  					}
  
  					edge = edge.next;
  				}
  
  				var world = this.m_body.getWorld();
  
  				if (world == null) {
  					return;
  				}
  
  				// Touch each proxy so that new pairs may be created
  				var broadPhase = world.m_broadPhase;
  				for (var i = 0; i < this.m_proxyCount; ++i) {
  					broadPhase.touchProxy(this.m_proxies[i].proxyId);
  				}
  			};
  
  			/**
               * Implement this method to provide collision filtering, if you want finer
               * control over contact creation.
               *
               * Return true if contact calculations should be performed between these two
               * fixtures.
               *
               * Warning: for performance reasons this is only called when the AABBs begin to
               * overlap.
               *
               * @param {Fixture} fixtureA
               * @param {Fixture} fixtureB
               */
  			Fixture.prototype.shouldCollide = function (that) {
  				if (that.m_filterGroupIndex == this.m_filterGroupIndex && that.m_filterGroupIndex != 0) {
  					return that.m_filterGroupIndex > 0;
  				}
  
  				var collide = (that.m_filterMaskBits & this.m_filterCategoryBits) != 0 && (that.m_filterCategoryBits & this.m_filterMaskBits) != 0;
  				return collide;
  			};
  
  			/***/
  		},
  		/* 33 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = TimeOfImpact;
  			module.exports.Input = TOIInput;
  			module.exports.Output = TOIOutput;
  
  			var Settings = __webpack_require__(4);
  
  			var common = __webpack_require__(2);
  			var Timer = __webpack_require__(44);
  
  			var stats = __webpack_require__(27);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Distance = __webpack_require__(22);
  			var DistanceInput = Distance.Input;
  			var DistanceOutput = Distance.Output;
  			var DistanceProxy = Distance.Proxy;
  			var SimplexCache = Distance.Cache;
  
  			/**
               * Input parameters for TimeOfImpact.
               *
               * @prop {DistanceProxy} proxyA
               * @prop {DistanceProxy} proxyB
               * @prop {Sweep} sweepA
               * @prop {Sweep} sweepB
               * @prop tMax defines sweep interval [0, tMax]
               */
  			function TOIInput () {
  				this.proxyA = new DistanceProxy();
  				this.proxyB = new DistanceProxy();
  				this.sweepA = new Sweep();
  				this.sweepB = new Sweep();
  				this.tMax;
  			}
  
  			// TOIOutput State
  			TOIOutput.e_unknown = 0;
  			TOIOutput.e_failed = 1;
  			TOIOutput.e_overlapped = 2;
  			TOIOutput.e_touching = 3;
  			TOIOutput.e_separated = 4;
  
  			/**
               * Output parameters for TimeOfImpact.
               *
               * @prop state
               * @prop t
               */
  			function TOIOutput () {
  				this.state;
  				this.t;
  			}
  
  			stats.toiTime = 0;
  			stats.toiMaxTime = 0;
  			stats.toiCalls = 0;
  			stats.toiIters = 0;
  			stats.toiMaxIters = 0;
  			stats.toiRootIters = 0;
  			stats.toiMaxRootIters = 0;
  
  			/**
               * Compute the upper bound on time before two shapes penetrate. Time is
               * represented as a fraction between [0,tMax]. This uses a swept separating axis
               * and may miss some intermediate, non-tunneling collision. If you change the
               * time interval, you should call this function again.
               *
               * Note: use Distance to compute the contact point and normal at the time of
               * impact.
               *
               * CCD via the local separating axis method. This seeks progression by computing
               * the largest time at which separation is maintained.
               */
  			function TimeOfImpact (output, input) {
  				var timer = Timer.now();
  
  				++stats.toiCalls;
  
  				output.state = TOIOutput.e_unknown;
  				output.t = input.tMax;
  
  				var proxyA = input.proxyA; // DistanceProxy
  				var proxyB = input.proxyB; // DistanceProxy
  
  				var sweepA = input.sweepA; // Sweep
  				var sweepB = input.sweepB; // Sweep
  
  				// Large rotations can make the root finder fail, so we normalize the
  				// sweep angles.
  				sweepA.normalize();
  				sweepB.normalize();
  
  				var tMax = input.tMax;
  
  				var totalRadius = proxyA.m_radius + proxyB.m_radius;
  				var target = Math.max(Settings.linearSlop, totalRadius - 3.0 * Settings.linearSlop);
  				var tolerance = 0.25 * Settings.linearSlop;
  				_ASSERT && common.assert(target > tolerance);
  
  				var t1 = 0.0;
  				var k_maxIterations = Settings.maxTOIIterations;
  				var iter = 0;
  
  				// Prepare input for distance query.
  				var cache = new SimplexCache();
  
  				var distanceInput = new DistanceInput();
  				distanceInput.proxyA = input.proxyA;
  				distanceInput.proxyB = input.proxyB;
  				distanceInput.useRadii = false;
  
  				// The outer loop progressively attempts to compute new separating axes.
  				// This loop terminates when an axis is repeated (no progress is made).
  				for (;;) {
  					var xfA = Transform.identity();
  					var xfB = Transform.identity();
  					sweepA.getTransform(xfA, t1);
  					sweepB.getTransform(xfB, t1);
  
  					// Get the distance between shapes. We can also use the results
  					// to get a separating axis.
  					distanceInput.transformA = xfA;
  					distanceInput.transformB = xfB;
  					var distanceOutput = new DistanceOutput();
  					Distance(distanceOutput, cache, distanceInput);
  
  					// If the shapes are overlapped, we give up on continuous collision.
  					if (distanceOutput.distance <= 0.0) {
  						// Failure!
  						output.state = TOIOutput.e_overlapped;
  						output.t = 0.0;
  						break;
  					}
  
  					if (distanceOutput.distance < target + tolerance) {
  						// Victory!
  						output.state = TOIOutput.e_touching;
  						output.t = t1;
  						break;
  					}
  
  					// Initialize the separating axis.
  					var fcn = new SeparationFunction();
  					fcn.initialize(cache, proxyA, sweepA, proxyB, sweepB, t1);
  
  					// if (false) {
  					//   // Dump the curve seen by the root finder
  					//   var N = 100;
  					//   var dx = 1.0 / N;
  					//   var xs = []; // [ N + 1 ];
  					//   var fs = []; // [ N + 1 ];
  					//   var x = 0.0;
  					//   for (var i = 0; i <= N; ++i) {
  					//     sweepA.getTransform(xfA, x);
  					//     sweepB.getTransform(xfB, x);
  					//     var f = fcn.evaluate(xfA, xfB) - target;
  					//     printf("%g %g\n", x, f);
  					//     xs[i] = x;
  					//     fs[i] = f;
  					//     x += dx;
  					//   }
  					// }
  
  					// Compute the TOI on the separating axis. We do this by successively
  					// resolving the deepest point. This loop is bounded by the number of
  					// vertices.
  					var done = false;
  					var t2 = tMax;
  					var pushBackIter = 0;
  					for (;;) {
  						// Find the deepest point at t2. Store the witness point indices.
  						var s2 = fcn.findMinSeparation(t2);
  						var indexA = fcn.indexA;
  						var indexB = fcn.indexB;
  
  						// Is the final configuration separated?
  						if (s2 > target + tolerance) {
  							// Victory!
  							output.state = TOIOutput.e_separated;
  							output.t = tMax;
  							done = true;
  							break;
  						}
  
  						// Has the separation reached tolerance?
  						if (s2 > target - tolerance) {
  							// Advance the sweeps
  							t1 = t2;
  							break;
  						}
  
  						// Compute the initial separation of the witness points.
  						var s1 = fcn.evaluate(t1);
  						var indexA = fcn.indexA;
  						var indexB = fcn.indexB;
  
  						// Check for initial overlap. This might happen if the root finder
  						// runs out of iterations.
  						if (s1 < target - tolerance) {
  							output.state = TOIOutput.e_failed;
  							output.t = t1;
  							done = true;
  							break;
  						}
  
  						// Check for touching
  						if (s1 <= target + tolerance) {
  							// Victory! t1 should hold the TOI (could be 0.0).
  							output.state = TOIOutput.e_touching;
  							output.t = t1;
  							done = true;
  							break;
  						}
  
  						// Compute 1D root of: f(x) - target = 0
  						var rootIterCount = 0;
  						var a1 = t1;
  						var a2 = t2;
  						for (;;) {
  							// Use a mix of the secant rule and bisection.
  							var t;
  							if (rootIterCount & 1) {
  								// Secant rule to improve convergence.
  								t = a1 + ((target - s1) * (a2 - a1)) / (s2 - s1);
  							} else {
  								// Bisection to guarantee progress.
  								t = 0.5 * (a1 + a2);
  							}
  
  							++rootIterCount;
  							++stats.toiRootIters;
  
  							var s = fcn.evaluate(t);
  							var indexA = fcn.indexA;
  							var indexB = fcn.indexB;
  
  							if (Math.abs(s - target) < tolerance) {
  								// t2 holds a tentative value for t1
  								t2 = t;
  								break;
  							}
  
  							// Ensure we continue to bracket the root.
  							if (s > target) {
  								a1 = t;
  								s1 = s;
  							} else {
  								a2 = t;
  								s2 = s;
  							}
  
  							if (rootIterCount == 50) {
  								break;
  							}
  						}
  
  						stats.toiMaxRootIters = Math.max(stats.toiMaxRootIters, rootIterCount);
  
  						++pushBackIter;
  
  						if (pushBackIter == Settings.maxPolygonVertices) {
  							break;
  						}
  					}
  
  					++iter;
  					++stats.toiIters;
  
  					if (done) {
  						break;
  					}
  
  					if (iter == k_maxIterations) {
  						// Root finder got stuck. Semi-victory.
  						output.state = TOIOutput.e_failed;
  						output.t = t1;
  						break;
  					}
  				}
  
  				stats.toiMaxIters = Math.max(stats.toiMaxIters, iter);
  
  				var time = Timer.diff(timer);
  				stats.toiMaxTime = Math.max(stats.toiMaxTime, time);
  				stats.toiTime += time;
  			}
  
  			// SeparationFunction Type
  			var e_points = 1;
  			var e_faceA = 2;
  			var e_faceB = 3;
  
  			function SeparationFunction () {
  				this.m_proxyA = new DistanceProxy();
  				this.m_proxyB = new DistanceProxy();
  				this.m_sweepA; // Sweep
  				this.m_sweepB; // Sweep
  				this.indexA; // integer
  				this.indexB; // integer
  				this.m_type;
  				this.m_localPoint = Vec2.zero();
  				this.m_axis = Vec2.zero();
  			}
  
  			// TODO_ERIN might not need to return the separation
  
  			/**
               * @param {SimplexCache} cache
               * @param {DistanceProxy} proxyA
               * @param {Sweep} sweepA
               * @param {DistanceProxy} proxyB
               * @param {Sweep} sweepB
               * @param {float} t1
               */
  			SeparationFunction.prototype.initialize = function (cache, proxyA, sweepA, proxyB, sweepB, t1) {
  				this.m_proxyA = proxyA;
  				this.m_proxyB = proxyB;
  				var count = cache.count;
  				_ASSERT && common.assert(count > 0 && count < 3);
  
  				this.m_sweepA = sweepA;
  				this.m_sweepB = sweepB;
  
  				var xfA = Transform.identity();
  				var xfB = Transform.identity();
  				this.m_sweepA.getTransform(xfA, t1);
  				this.m_sweepB.getTransform(xfB, t1);
  
  				if (count == 1) {
  					this.m_type = e_points;
  					var localPointA = this.m_proxyA.getVertex(cache.indexA[0]);
  					var localPointB = this.m_proxyB.getVertex(cache.indexB[0]);
  					var pointA = Transform.mulVec2(xfA, localPointA);
  					var pointB = Transform.mulVec2(xfB, localPointB);
  					this.m_axis.setCombine(1, pointB, -1, pointA);
  					var s = this.m_axis.normalize();
  					return s;
  				} else if (cache.indexA[0] == cache.indexA[1]) {
  					// Two points on B and one on A.
  					this.m_type = e_faceB;
  					var localPointB1 = proxyB.getVertex(cache.indexB[0]);
  					var localPointB2 = proxyB.getVertex(cache.indexB[1]);
  
  					this.m_axis = Vec2.cross(Vec2.sub(localPointB2, localPointB1), 1.0);
  					this.m_axis.normalize();
  					var normal = Rot.mulVec2(xfB.q, this.m_axis);
  
  					this.m_localPoint = Vec2.mid(localPointB1, localPointB2);
  					var pointB = Transform.mulVec2(xfB, this.m_localPoint);
  
  					var localPointA = proxyA.getVertex(cache.indexA[0]);
  					var pointA = Transform.mulVec2(xfA, localPointA);
  
  					var s = Vec2.dot(pointA, normal) - Vec2.dot(pointB, normal);
  					if (s < 0.0) {
  						this.m_axis = Vec2.neg(this.m_axis);
  						s = -s;
  					}
  					return s;
  				} else {
  					// Two points on A and one or two points on B.
  					this.m_type = e_faceA;
  					var localPointA1 = this.m_proxyA.getVertex(cache.indexA[0]);
  					var localPointA2 = this.m_proxyA.getVertex(cache.indexA[1]);
  
  					this.m_axis = Vec2.cross(Vec2.sub(localPointA2, localPointA1), 1.0);
  					this.m_axis.normalize();
  					var normal = Rot.mulVec2(xfA.q, this.m_axis);
  
  					this.m_localPoint = Vec2.mid(localPointA1, localPointA2);
  					var pointA = Transform.mulVec2(xfA, this.m_localPoint);
  
  					var localPointB = this.m_proxyB.getVertex(cache.indexB[0]);
  					var pointB = Transform.mulVec2(xfB, localPointB);
  
  					var s = Vec2.dot(pointB, normal) - Vec2.dot(pointA, normal);
  					if (s < 0.0) {
  						this.m_axis = Vec2.neg(this.m_axis);
  						s = -s;
  					}
  					return s;
  				}
  			};
  
  			SeparationFunction.prototype.compute = function (find, t) {
  				// It was findMinSeparation and evaluate
  				var xfA = Transform.identity();
  				var xfB = Transform.identity();
  				this.m_sweepA.getTransform(xfA, t);
  				this.m_sweepB.getTransform(xfB, t);
  
  				switch (this.m_type) {
  					case e_points: {
  						if (find) {
  							var axisA = Rot.mulTVec2(xfA.q, this.m_axis);
  							var axisB = Rot.mulTVec2(xfB.q, Vec2.neg(this.m_axis));
  
  							this.indexA = this.m_proxyA.getSupport(axisA);
  							this.indexB = this.m_proxyB.getSupport(axisB);
  						}
  
  						var localPointA = this.m_proxyA.getVertex(this.indexA);
  						var localPointB = this.m_proxyB.getVertex(this.indexB);
  
  						var pointA = Transform.mulVec2(xfA, localPointA);
  						var pointB = Transform.mulVec2(xfB, localPointB);
  
  						var sep = Vec2.dot(pointB, this.m_axis) - Vec2.dot(pointA, this.m_axis);
  						return sep;
  					}
  
  					case e_faceA: {
  						var normal = Rot.mulVec2(xfA.q, this.m_axis);
  						var pointA = Transform.mulVec2(xfA, this.m_localPoint);
  
  						if (find) {
  							var axisB = Rot.mulTVec2(xfB.q, Vec2.neg(normal));
  
  							this.indexA = -1;
  							this.indexB = this.m_proxyB.getSupport(axisB);
  						}
  
  						var localPointB = this.m_proxyB.getVertex(this.indexB);
  						var pointB = Transform.mulVec2(xfB, localPointB);
  
  						var sep = Vec2.dot(pointB, normal) - Vec2.dot(pointA, normal);
  						return sep;
  					}
  
  					case e_faceB: {
  						var normal = Rot.mulVec2(xfB.q, this.m_axis);
  						var pointB = Transform.mulVec2(xfB, this.m_localPoint);
  
  						if (find) {
  							var axisA = Rot.mulTVec2(xfA.q, Vec2.neg(normal));
  
  							this.indexB = -1;
  							this.indexA = this.m_proxyA.getSupport(axisA);
  						}
  
  						var localPointA = this.m_proxyA.getVertex(this.indexA);
  						var pointA = Transform.mulVec2(xfA, localPointA);
  
  						var sep = Vec2.dot(pointA, normal) - Vec2.dot(pointB, normal);
  						return sep;
  					}
  
  					default:
  						_ASSERT && common.assert(false);
  						if (find) {
  							this.indexA = -1;
  							this.indexB = -1;
  						}
  						return 0.0;
  				}
  			};
  
  			SeparationFunction.prototype.findMinSeparation = function (t) {
  				return this.compute(true, t);
  			};
  
  			SeparationFunction.prototype.evaluate = function (t) {
  				return this.compute(false, t);
  			};
  
  			/***/
  		},
  		/* 34 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = RevoluteJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			var inactiveLimit = 0;
  			var atLowerLimit = 1;
  			var atUpperLimit = 2;
  			var equalLimits = 3;
  
  			RevoluteJoint.TYPE = 'revolute-joint';
  			Joint.TYPES[RevoluteJoint.TYPE] = RevoluteJoint;
  
  			RevoluteJoint._super = Joint;
  			RevoluteJoint.prototype = create(RevoluteJoint._super.prototype);
  
  			/**
               * @typedef {Object} RevoluteJointDef
               *
               * Revolute joint definition. This requires defining an anchor point where the
               * bodies are joined. The definition uses local anchor points so that the
               * initial configuration can violate the constraint slightly. You also need to
               * specify the initial relative angle for joint limits. This helps when saving
               * and loading a game.
               *
               * The local anchor points are measured from the body's origin rather than the
               * center of mass because: 1. you might not know where the center of mass will
               * be. 2. if you add/remove shapes from a body and recompute the mass, the
               * joints will be broken.
               *
               * @prop {bool} enableLimit A flag to enable joint limits.
               * @prop {bool} enableMotor A flag to enable the joint motor.
               * @prop {float} lowerAngle The lower angle for the joint limit (radians).
               * @prop {float} upperAngle The upper angle for the joint limit (radians).
               * @prop {float} motorSpeed The desired motor speed. Usually in radians per
               *       second.
               * @prop {float} maxMotorTorque The maximum motor torque used to achieve the
               *       desired motor speed. Usually in N-m.
               *
               * @prop {Vec2} localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} localAnchorB The local anchor point relative to bodyB's origin.
               * @prop {float} referenceAngle The bodyB angle minus bodyA angle in the
               *       reference state (radians).
               */
  
  			var DEFAULTS = {
  				lowerAngle: 0.0,
  				upperAngle: 0.0,
  				maxMotorTorque: 0.0,
  				motorSpeed: 0.0,
  				enableLimit: false,
  				enableMotor: false
  			};
  
  			/**
               * A revolute joint constrains two bodies to share a common point while they are
               * free to rotate about the point. The relative rotation about the shared point
               * is the joint angle. You can limit the relative rotation with a joint limit
               * that specifies a lower and upper angle. You can use a motor to drive the
               * relative rotation about the shared point. A maximum motor torque is provided
               * so that infinite forces are not generated.
               *
               * @param {RevoluteJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function RevoluteJoint (def, bodyA, bodyB, anchor) {
  				if (!(this instanceof RevoluteJoint)) {
  					return new RevoluteJoint(def, bodyA, bodyB, anchor);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = RevoluteJoint.TYPE;
  
  				this.m_localAnchorA = Vec2.clone(anchor ? bodyA.getLocalPoint(anchor) : def.localAnchorA || Vec2.zero());
  				this.m_localAnchorB = Vec2.clone(anchor ? bodyB.getLocalPoint(anchor) : def.localAnchorB || Vec2.zero());
  				this.m_referenceAngle = Math.isFinite(def.referenceAngle) ? def.referenceAngle : bodyB.getAngle() - bodyA.getAngle();
  
  				this.m_impulse = Vec3();
  				this.m_motorImpulse = 0.0;
  
  				this.m_lowerAngle = def.lowerAngle;
  				this.m_upperAngle = def.upperAngle;
  				this.m_maxMotorTorque = def.maxMotorTorque;
  				this.m_motorSpeed = def.motorSpeed;
  				this.m_enableLimit = def.enableLimit;
  				this.m_enableMotor = def.enableMotor;
  
  				// Solver temp
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				// effective mass for point-to-point constraint.
  				this.m_mass = new Mat33();
  				// effective mass for motor/limit angular constraint.
  				this.m_motorMass; // float
  				this.m_limitState = inactiveLimit;
  
  				// Point-to-point constraint
  				// C = p2 - p1
  				// Cdot = v2 - v1
  				// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
  				// J = [-I -r1_skew I r2_skew ]
  				// Identity used:
  				// w k % (rx i + ry j) = w * (-ry i + rx j)
  
  				// Motor constraint
  				// Cdot = w2 - w1
  				// J = [0 0 -1 0 0 1]
  				// K = invI1 + invI2
  			}
  
  			RevoluteJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					lowerAngle: this.m_lowerAngle,
  					upperAngle: this.m_upperAngle,
  					maxMotorTorque: this.m_maxMotorTorque,
  					motorSpeed: this.m_motorSpeed,
  					enableLimit: this.m_enableLimit,
  					enableMotor: this.m_enableMotor,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					referenceAngle: this.m_referenceAngle
  				};
  			};
  
  			RevoluteJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new RevoluteJoint(data);
  				return joint;
  			};
  
  			/**
               * @internal
               */
  			RevoluteJoint.prototype._setAnchors = function (def) {
  				if (def.anchorA) {
  					this.m_localAnchorA.set(this.m_bodyA.getLocalPoint(def.anchorA));
  				} else if (def.localAnchorA) {
  					this.m_localAnchorA.set(def.localAnchorA);
  				}
  
  				if (def.anchorB) {
  					this.m_localAnchorB.set(this.m_bodyB.getLocalPoint(def.anchorB));
  				} else if (def.localAnchorB) {
  					this.m_localAnchorB.set(def.localAnchorB);
  				}
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			RevoluteJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			RevoluteJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * Get the reference angle.
               */
  			RevoluteJoint.prototype.getReferenceAngle = function () {
  				return this.m_referenceAngle;
  			};
  
  			/**
               * Get the current joint angle in radians.
               */
  			RevoluteJoint.prototype.getJointAngle = function () {
  				var bA = this.m_bodyA;
  				var bB = this.m_bodyB;
  				return bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle;
  			};
  
  			/**
               * Get the current joint angle speed in radians per second.
               */
  			RevoluteJoint.prototype.getJointSpeed = function () {
  				var bA = this.m_bodyA;
  				var bB = this.m_bodyB;
  				return bB.m_angularVelocity - bA.m_angularVelocity;
  			};
  
  			/**
               * Is the joint motor enabled?
               */
  			RevoluteJoint.prototype.isMotorEnabled = function () {
  				return this.m_enableMotor;
  			};
  
  			/**
               * Enable/disable the joint motor.
               */
  			RevoluteJoint.prototype.enableMotor = function (flag) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_enableMotor = flag;
  			};
  
  			/**
               * Get the current motor torque given the inverse time step. Unit is N*m.
               */
  			RevoluteJoint.prototype.getMotorTorque = function (inv_dt) {
  				return inv_dt * this.m_motorImpulse;
  			};
  
  			/**
               * Set the motor speed in radians per second.
               */
  			RevoluteJoint.prototype.setMotorSpeed = function (speed) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_motorSpeed = speed;
  			};
  
  			/**
               * Get the motor speed in radians per second.
               */
  			RevoluteJoint.prototype.getMotorSpeed = function () {
  				return this.m_motorSpeed;
  			};
  
  			/**
               * Set the maximum motor torque, usually in N-m.
               */
  			RevoluteJoint.prototype.setMaxMotorTorque = function (torque) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_maxMotorTorque = torque;
  			};
  
  			RevoluteJoint.prototype.getMaxMotorTorque = function () {
  				return this.m_maxMotorTorque;
  			};
  
  			/**
               * Is the joint limit enabled?
               */
  			RevoluteJoint.prototype.isLimitEnabled = function () {
  				return this.m_enableLimit;
  			};
  
  			/**
               * Enable/disable the joint limit.
               */
  			RevoluteJoint.prototype.enableLimit = function (flag) {
  				if (flag != this.m_enableLimit) {
  					this.m_bodyA.setAwake(true);
  					this.m_bodyB.setAwake(true);
  					this.m_enableLimit = flag;
  					this.m_impulse.z = 0.0;
  				}
  			};
  
  			/**
               * Get the lower joint limit in radians.
               */
  			RevoluteJoint.prototype.getLowerLimit = function () {
  				return this.m_lowerAngle;
  			};
  
  			/**
               * Get the upper joint limit in radians.
               */
  			RevoluteJoint.prototype.getUpperLimit = function () {
  				return this.m_upperAngle;
  			};
  
  			/**
               * Set the joint limits in radians.
               */
  			RevoluteJoint.prototype.setLimits = function (lower, upper) {
  				_ASSERT && common.assert(lower <= upper);
  
  				if (lower != this.m_lowerAngle || upper != this.m_upperAngle) {
  					this.m_bodyA.setAwake(true);
  					this.m_bodyB.setAwake(true);
  					this.m_impulse.z = 0.0;
  					this.m_lowerAngle = lower;
  					this.m_upperAngle = upper;
  				}
  			};
  
  			RevoluteJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			RevoluteJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			/**
               * Get the reaction force given the inverse time step. Unit is N.
               */
  			RevoluteJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.neo(this.m_impulse.x, this.m_impulse.y).mul(inv_dt);
  			};
  
  			/**
               * Get the reaction torque due to the joint limit given the inverse time step.
               * Unit is N*m.
               */
  			RevoluteJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * this.m_impulse.z;
  			};
  
  			RevoluteJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				this.m_rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				this.m_rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				// J = [-I -r1_skew I r2_skew]
  				// [ 0 -1 0 1]
  				// r_skew = [-ry; rx]
  
  				// Matlab
  				// K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
  				// [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
  				// [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var fixedRotation = iA + iB === 0.0; // bool
  
  				this.m_mass.ex.x = mA + mB + this.m_rA.y * this.m_rA.y * iA + this.m_rB.y * this.m_rB.y * iB;
  				this.m_mass.ey.x = -this.m_rA.y * this.m_rA.x * iA - this.m_rB.y * this.m_rB.x * iB;
  				this.m_mass.ez.x = -this.m_rA.y * iA - this.m_rB.y * iB;
  				this.m_mass.ex.y = this.m_mass.ey.x;
  				this.m_mass.ey.y = mA + mB + this.m_rA.x * this.m_rA.x * iA + this.m_rB.x * this.m_rB.x * iB;
  				this.m_mass.ez.y = this.m_rA.x * iA + this.m_rB.x * iB;
  				this.m_mass.ex.z = this.m_mass.ez.x;
  				this.m_mass.ey.z = this.m_mass.ez.y;
  				this.m_mass.ez.z = iA + iB;
  
  				this.m_motorMass = iA + iB;
  				if (this.m_motorMass > 0.0) {
  					this.m_motorMass = 1.0 / this.m_motorMass;
  				}
  
  				if (this.m_enableMotor == false || fixedRotation) {
  					this.m_motorImpulse = 0.0;
  				}
  
  				if (this.m_enableLimit && fixedRotation == false) {
  					var jointAngle = aB - aA - this.m_referenceAngle; // float
  
  					if (Math.abs(this.m_upperAngle - this.m_lowerAngle) < 2.0 * Settings.angularSlop) {
  						this.m_limitState = equalLimits;
  					} else if (jointAngle <= this.m_lowerAngle) {
  						if (this.m_limitState != atLowerLimit) {
  							this.m_impulse.z = 0.0;
  						}
  						this.m_limitState = atLowerLimit;
  					} else if (jointAngle >= this.m_upperAngle) {
  						if (this.m_limitState != atUpperLimit) {
  							this.m_impulse.z = 0.0;
  						}
  						this.m_limitState = atUpperLimit;
  					} else {
  						this.m_limitState = inactiveLimit;
  						this.m_impulse.z = 0.0;
  					}
  				} else {
  					this.m_limitState = inactiveLimit;
  				}
  
  				if (step.warmStarting) {
  					// Scale impulses to support a variable time step.
  					this.m_impulse.mul(step.dtRatio);
  					this.m_motorImpulse *= step.dtRatio;
  
  					var P = Vec2.neo(this.m_impulse.x, this.m_impulse.y);
  
  					vA.subMul(mA, P);
  					wA -= iA * (Vec2.cross(this.m_rA, P) + this.m_motorImpulse + this.m_impulse.z);
  
  					vB.addMul(mB, P);
  					wB += iB * (Vec2.cross(this.m_rB, P) + this.m_motorImpulse + this.m_impulse.z);
  				} else {
  					this.m_impulse.setZero();
  					this.m_motorImpulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			RevoluteJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var fixedRotation = iA + iB === 0.0; // bool
  
  				// Solve motor constraint.
  				if (this.m_enableMotor && this.m_limitState != equalLimits && fixedRotation == false) {
  					var Cdot = wB - wA - this.m_motorSpeed; // float
  					var impulse = -this.m_motorMass * Cdot; // float
  					var oldImpulse = this.m_motorImpulse; // float
  					var maxImpulse = step.dt * this.m_maxMotorTorque; // float
  					this.m_motorImpulse = Math.clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse);
  					impulse = this.m_motorImpulse - oldImpulse;
  
  					wA -= iA * impulse;
  					wB += iB * impulse;
  				}
  
  				// Solve limit constraint.
  				if (this.m_enableLimit && this.m_limitState != inactiveLimit && fixedRotation == false) {
  					var Cdot1 = Vec2.zero();
  					Cdot1.addCombine(1, vB, 1, Vec2.cross(wB, this.m_rB));
  					Cdot1.subCombine(1, vA, 1, Vec2.cross(wA, this.m_rA));
  					var Cdot2 = wB - wA; // float
  					var Cdot = Vec3(Cdot1.x, Cdot1.y, Cdot2);
  
  					var impulse = Vec3.neg(this.m_mass.solve33(Cdot)); // Vec3
  
  					if (this.m_limitState == equalLimits) {
  						this.m_impulse.add(impulse);
  					} else if (this.m_limitState == atLowerLimit) {
  						var newImpulse = this.m_impulse.z + impulse.z; // float
  
  						if (newImpulse < 0.0) {
  							var rhs = Vec2.combine(-1, Cdot1, this.m_impulse.z, Vec2.neo(this.m_mass.ez.x, this.m_mass.ez.y)); // Vec2
  							var reduced = this.m_mass.solve22(rhs); // Vec2
  							impulse.x = reduced.x;
  							impulse.y = reduced.y;
  							impulse.z = -this.m_impulse.z;
  							this.m_impulse.x += reduced.x;
  							this.m_impulse.y += reduced.y;
  							this.m_impulse.z = 0.0;
  						} else {
  							this.m_impulse.add(impulse);
  						}
  					} else if (this.m_limitState == atUpperLimit) {
  						var newImpulse = this.m_impulse.z + impulse.z; // float
  
  						if (newImpulse > 0.0) {
  							var rhs = Vec2.combine(-1, Cdot1, this.m_impulse.z, Vec2.neo(this.m_mass.ez.x, this.m_mass.ez.y)); // Vec2
  							var reduced = this.m_mass.solve22(rhs); // Vec2
  							impulse.x = reduced.x;
  							impulse.y = reduced.y;
  							impulse.z = -this.m_impulse.z;
  							this.m_impulse.x += reduced.x;
  							this.m_impulse.y += reduced.y;
  							this.m_impulse.z = 0.0;
  						} else {
  							this.m_impulse.add(impulse);
  						}
  					}
  
  					var P = Vec2.neo(impulse.x, impulse.y);
  
  					vA.subMul(mA, P);
  					wA -= iA * (Vec2.cross(this.m_rA, P) + impulse.z);
  
  					vB.addMul(mB, P);
  					wB += iB * (Vec2.cross(this.m_rB, P) + impulse.z);
  				} else {
  					// Solve point-to-point constraint
  					var Cdot = Vec2.zero();
  					Cdot.addCombine(1, vB, 1, Vec2.cross(wB, this.m_rB));
  					Cdot.subCombine(1, vA, 1, Vec2.cross(wA, this.m_rA));
  					var impulse = this.m_mass.solve22(Vec2.neg(Cdot)); // Vec2
  
  					this.m_impulse.x += impulse.x;
  					this.m_impulse.y += impulse.y;
  
  					vA.subMul(mA, impulse);
  					wA -= iA * Vec2.cross(this.m_rA, impulse);
  
  					vB.addMul(mB, impulse);
  					wB += iB * Vec2.cross(this.m_rB, impulse);
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			RevoluteJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var angularError = 0.0; // float
  				var positionError = 0.0; // float
  
  				var fixedRotation = this.m_invIA + this.m_invIB == 0.0; // bool
  
  				// Solve angular limit constraint.
  				if (this.m_enableLimit && this.m_limitState != inactiveLimit && fixedRotation == false) {
  					var angle = aB - aA - this.m_referenceAngle; // float
  					var limitImpulse = 0.0; // float
  
  					if (this.m_limitState == equalLimits) {
  						// Prevent large angular corrections
  						var C = Math.clamp(angle - this.m_lowerAngle, -Settings.maxAngularCorrection, Settings.maxAngularCorrection); // float
  						limitImpulse = -this.m_motorMass * C;
  						angularError = Math.abs(C);
  					} else if (this.m_limitState == atLowerLimit) {
  						var C = angle - this.m_lowerAngle; // float
  						angularError = -C;
  
  						// Prevent large angular corrections and allow some slop.
  						C = Math.clamp(C + Settings.angularSlop, -Settings.maxAngularCorrection, 0.0);
  						limitImpulse = -this.m_motorMass * C;
  					} else if (this.m_limitState == atUpperLimit) {
  						var C = angle - this.m_upperAngle; // float
  						angularError = C;
  
  						// Prevent large angular corrections and allow some slop.
  						C = Math.clamp(C - Settings.angularSlop, 0.0, Settings.maxAngularCorrection);
  						limitImpulse = -this.m_motorMass * C;
  					}
  
  					aA -= this.m_invIA * limitImpulse;
  					aB += this.m_invIB * limitImpulse;
  				}
  
  				// Solve point-to-point constraint.
  				{
  					qA.set(aA);
  					qB.set(aB);
  					var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA)); // Vec2
  					var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB)); // Vec2
  
  					var C = Vec2.zero();
  					C.addCombine(1, cB, 1, rB);
  					C.subCombine(1, cA, 1, rA);
  					positionError = C.length();
  
  					var mA = this.m_invMassA;
  					var mB = this.m_invMassB; // float
  					var iA = this.m_invIA;
  					var iB = this.m_invIB; // float
  
  					var K = new Mat22();
  					K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y;
  					K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y;
  					K.ey.x = K.ex.y;
  					K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x;
  
  					var impulse = Vec2.neg(K.solve(C)); // Vec2
  
  					cA.subMul(mA, impulse);
  					aA -= iA * Vec2.cross(rA, impulse);
  
  					cB.addMul(mB, impulse);
  					aB += iB * Vec2.cross(rB, impulse);
  				}
  
  				this.m_bodyA.c_position.c.set(cA);
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c.set(cB);
  				this.m_bodyB.c_position.a = aB;
  
  				return positionError <= Settings.linearSlop && angularError <= Settings.angularSlop;
  			};
  
  			/***/
  		},
  		/* 35 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = PrismaticJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			var inactiveLimit = 0;
  			var atLowerLimit = 1;
  			var atUpperLimit = 2;
  			var equalLimits = 3;
  
  			PrismaticJoint.TYPE = 'prismatic-joint';
  			Joint.TYPES[PrismaticJoint.TYPE] = PrismaticJoint;
  
  			PrismaticJoint._super = Joint;
  			PrismaticJoint.prototype = create(PrismaticJoint._super.prototype);
  
  			/**
               * @typedef {Object} PrismaticJointDef
               *
               * Prismatic joint definition. This requires defining a line of motion using an
               * axis and an anchor point. The definition uses local anchor points and a local
               * axis so that the initial configuration can violate the constraint slightly.
               * The joint translation is zero when the local anchor points coincide in world
               * space. Using local anchors and a local axis helps when saving and loading a
               * game.
               *
               * @prop {boolean} enableLimit Enable/disable the joint limit.
               * @prop {float} lowerTranslation The lower translation limit, usually in
               *       meters.
               * @prop {float} upperTranslation The upper translation limit, usually in
               *       meters.
               * @prop {boolean} enableMotor Enable/disable the joint motor.
               * @prop {float} maxMotorForce The maximum motor torque, usually in N-m.
               * @prop {float} motorSpeed The desired motor speed in radians per second.
               *
               * @prop {Vec2} localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} localAnchorB The local anchor point relative to bodyB's origin.
               * @prop {Vec2} localAxisA The local translation unit axis in bodyA.
               * @prop {float} referenceAngle The constrained angle between the bodies:
               *       bodyB_angle - bodyA_angle.
               */
  
  			var DEFAULTS = {
  				enableLimit: false,
  				lowerTranslation: 0.0,
  				upperTranslation: 0.0,
  				enableMotor: false,
  				maxMotorForce: 0.0,
  				motorSpeed: 0.0
  			};
  
  			/**
               * A prismatic joint. This joint provides one degree of freedom: translation
               * along an axis fixed in bodyA. Relative rotation is prevented. You can use a
               * joint limit to restrict the range of motion and a joint motor to drive the
               * motion or to model joint friction.
               *
               * @param {PrismaticJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function PrismaticJoint (def, bodyA, bodyB, anchor, axis) {
  				if (!(this instanceof PrismaticJoint)) {
  					return new PrismaticJoint(def, bodyA, bodyB, anchor, axis);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = PrismaticJoint.TYPE;
  
  				this.m_localAnchorA = anchor ? bodyA.getLocalPoint(anchor) : def.localAnchorA || Vec2.zero();
  				this.m_localAnchorB = anchor ? bodyB.getLocalPoint(anchor) : def.localAnchorB || Vec2.zero();
  				this.m_localXAxisA = axis ? bodyA.getLocalVector(axis) : def.localAxisA || Vec2.neo(1.0, 0.0);
  				this.m_localXAxisA.normalize();
  				this.m_localYAxisA = Vec2.cross(1.0, this.m_localXAxisA);
  				this.m_referenceAngle = Math.isFinite(def.referenceAngle) ? def.referenceAngle : bodyB.getAngle() - bodyA.getAngle();
  
  				this.m_impulse = Vec3();
  				this.m_motorMass = 0.0;
  				this.m_motorImpulse = 0.0;
  
  				this.m_lowerTranslation = def.lowerTranslation;
  				this.m_upperTranslation = def.upperTranslation;
  				this.m_maxMotorForce = def.maxMotorForce;
  				this.m_motorSpeed = def.motorSpeed;
  				this.m_enableLimit = def.enableLimit;
  				this.m_enableMotor = def.enableMotor;
  				this.m_limitState = inactiveLimit;
  
  				this.m_axis = Vec2.zero();
  				this.m_perp = Vec2.zero();
  
  				// Solver temp
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				this.m_axis, this.m_perp; // Vec2
  				this.m_s1, this.m_s2; // float
  				this.m_a1, this.m_a2; // float
  				this.m_K = new Mat33();
  				this.m_motorMass; // float
  
  				// Linear constraint (point-to-line)
  				// d = p2 - p1 = x2 + r2 - x1 - r1
  				// C = dot(perp, d)
  				// Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 -
  				// cross(w1, r1))
  				// = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) +
  				// dot(cross(r2, perp), v2)
  				// J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)]
  				//
  				// Angular constraint
  				// C = a2 - a1 + a_initial
  				// Cdot = w2 - w1
  				// J = [0 0 -1 0 0 1]
  				//
  				// K = J * invM * JT
  				//
  				// J = [-a -s1 a s2]
  				// [0 -1 0 1]
  				// a = perp
  				// s1 = cross(d + r1, a) = cross(p2 - x1, a)
  				// s2 = cross(r2, a) = cross(p2 - x2, a)
  
  				// Motor/Limit linear constraint
  				// C = dot(ax1, d)
  				// Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) +
  				// dot(cross(r2, ax1), v2)
  				// J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
  
  				// Block Solver
  				// We develop a block solver that includes the joint limit. This makes the
  				// limit stiff (inelastic) even
  				// when the mass has poor distribution (leading to large torques about the
  				// joint anchor points).
  				//
  				// The Jacobian has 3 rows:
  				// J = [-uT -s1 uT s2] // linear
  				// [0 -1 0 1] // angular
  				// [-vT -a1 vT a2] // limit
  				//
  				// u = perp
  				// v = axis
  				// s1 = cross(d + r1, u), s2 = cross(r2, u)
  				// a1 = cross(d + r1, v), a2 = cross(r2, v)
  
  				// M * (v2 - v1) = JT * df
  				// J * v2 = bias
  				//
  				// v2 = v1 + invM * JT * df
  				// J * (v1 + invM * JT * df) = bias
  				// K * df = bias - J * v1 = -Cdot
  				// K = J * invM * JT
  				// Cdot = J * v1 - bias
  				//
  				// Now solve for f2.
  				// df = f2 - f1
  				// K * (f2 - f1) = -Cdot
  				// f2 = invK * (-Cdot) + f1
  				//
  				// Clamp accumulated limit impulse.
  				// lower: f2(3) = max(f2(3), 0)
  				// upper: f2(3) = min(f2(3), 0)
  				//
  				// Solve for correct f2(1:2)
  				// K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:3) * f1
  				// = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:2) * f1(1:2) + K(1:2,3) * f1(3)
  				// K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3)) +
  				// K(1:2,1:2) * f1(1:2)
  				// f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) +
  				// f1(1:2)
  				//
  				// Now compute impulse to be applied:
  				// df = f2 - f1
  			}
  
  			PrismaticJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					lowerTranslation: this.m_lowerTranslation,
  					upperTranslation: this.m_upperTranslation,
  					maxMotorForce: this.m_maxMotorForce,
  					motorSpeed: this.m_motorSpeed,
  					enableLimit: this.m_enableLimit,
  					enableMotor: this.m_enableMotor,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					localAxisA: this.m_localXAxisA,
  					referenceAngle: this.m_referenceAngle
  				};
  			};
  
  			PrismaticJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				data.localAxisA = Vec2(data.localAxisA);
  				var joint = new PrismaticJoint(data);
  				return joint;
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			PrismaticJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			PrismaticJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * The local joint axis relative to bodyA.
               */
  			PrismaticJoint.prototype.getLocalAxisA = function () {
  				return this.m_localXAxisA;
  			};
  
  			/**
               * Get the reference angle.
               */
  			PrismaticJoint.prototype.getReferenceAngle = function () {
  				return this.m_referenceAngle;
  			};
  
  			/**
               * Get the current joint translation, usually in meters.
               */
  			PrismaticJoint.prototype.getJointTranslation = function () {
  				var pA = this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  				var pB = this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  				var d = Vec2.sub(pB, pA);
  				var axis = this.m_bodyA.getWorldVector(this.m_localXAxisA);
  
  				var translation = Vec2.dot(d, axis);
  				return translation;
  			};
  
  			/**
               * Get the current joint translation speed, usually in meters per second.
               */
  			PrismaticJoint.prototype.getJointSpeed = function () {
  				var bA = this.m_bodyA;
  				var bB = this.m_bodyB;
  
  				var rA = Rot.mulVec2(bA.m_xf.q, Vec2.sub(this.m_localAnchorA, bA.m_sweep.localCenter)); // Vec2
  				var rB = Rot.mulVec2(bB.m_xf.q, Vec2.sub(this.m_localAnchorB, bB.m_sweep.localCenter)); // Vec2
  				var p1 = Vec2.add(bA.m_sweep.c, rA); // Vec2
  				var p2 = Vec2.add(bB.m_sweep.c, rB); // Vec2
  				var d = Vec2.sub(p2, p1); // Vec2
  				var axis = Rot.mulVec2(bA.m_xf.q, this.m_localXAxisA); // Vec2
  
  				var vA = bA.m_linearVelocity; // Vec2
  				var vB = bB.m_linearVelocity; // Vec2
  				var wA = bA.m_angularVelocity; // float
  				var wB = bB.m_angularVelocity; // float
  
  				var speed = Vec2.dot(d, Vec2.cross(wA, axis)) + Vec2.dot(axis, Vec2.sub(Vec2.addCross(vB, wB, rB), Vec2.addCross(vA, wA, rA))); // float
  				return speed;
  			};
  
  			/**
               * Is the joint limit enabled?
               */
  			PrismaticJoint.prototype.isLimitEnabled = function () {
  				return this.m_enableLimit;
  			};
  
  			/**
               * Enable/disable the joint limit.
               */
  			PrismaticJoint.prototype.enableLimit = function (flag) {
  				if (flag != this.m_enableLimit) {
  					this.m_bodyA.setAwake(true);
  					this.m_bodyB.setAwake(true);
  					this.m_enableLimit = flag;
  					this.m_impulse.z = 0.0;
  				}
  			};
  
  			/**
               * Get the lower joint limit, usually in meters.
               */
  			PrismaticJoint.prototype.getLowerLimit = function () {
  				return this.m_lowerTranslation;
  			};
  
  			/**
               * Get the upper joint limit, usually in meters.
               */
  			PrismaticJoint.prototype.getUpperLimit = function () {
  				return this.m_upperTranslation;
  			};
  
  			/**
               * Set the joint limits, usually in meters.
               */
  			PrismaticJoint.prototype.setLimits = function (lower, upper) {
  				_ASSERT && common.assert(lower <= upper);
  				if (lower != this.m_lowerTranslation || upper != this.m_upperTranslation) {
  					this.m_bodyA.setAwake(true);
  					this.m_bodyB.setAwake(true);
  					this.m_lowerTranslation = lower;
  					this.m_upperTranslation = upper;
  					this.m_impulse.z = 0.0;
  				}
  			};
  
  			/**
               * Is the joint motor enabled?
               */
  			PrismaticJoint.prototype.isMotorEnabled = function () {
  				return this.m_enableMotor;
  			};
  
  			/**
               * Enable/disable the joint motor.
               */
  			PrismaticJoint.prototype.enableMotor = function (flag) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_enableMotor = flag;
  			};
  
  			/**
               * Set the motor speed, usually in meters per second.
               */
  			PrismaticJoint.prototype.setMotorSpeed = function (speed) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_motorSpeed = speed;
  			};
  
  			/**
               * Set the maximum motor force, usually in N.
               */
  			PrismaticJoint.prototype.setMaxMotorForce = function (force) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_maxMotorForce = force;
  			};
  
  			/**
               * Get the motor speed, usually in meters per second.
               */
  			PrismaticJoint.prototype.getMotorSpeed = function () {
  				return this.m_motorSpeed;
  			};
  
  			/**
               * Get the current motor force given the inverse time step, usually in N.
               */
  			PrismaticJoint.prototype.getMotorForce = function (inv_dt) {
  				return inv_dt * this.m_motorImpulse;
  			};
  
  			PrismaticJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			PrismaticJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			PrismaticJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.combine(this.m_impulse.x, this.m_perp, this.m_motorImpulse + this.m_impulse.z, this.m_axis).mul(inv_dt);
  			};
  
  			PrismaticJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * this.m_impulse.y;
  			};
  
  			PrismaticJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				// Compute the effective masses.
  				var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  				var d = Vec2.zero();
  				d.addCombine(1, cB, 1, rB);
  				d.subCombine(1, cA, 1, rA);
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB;
  				var iA = this.m_invIA;
  				var iB = this.m_invIB;
  
  				// Compute motor Jacobian and effective mass.
  				{
  					this.m_axis = Rot.mulVec2(qA, this.m_localXAxisA);
  					this.m_a1 = Vec2.cross(Vec2.add(d, rA), this.m_axis);
  					this.m_a2 = Vec2.cross(rB, this.m_axis);
  
  					this.m_motorMass = mA + mB + iA * this.m_a1 * this.m_a1 + iB * this.m_a2 * this.m_a2;
  					if (this.m_motorMass > 0.0) {
  						this.m_motorMass = 1.0 / this.m_motorMass;
  					}
  				}
  
  				// Prismatic constraint.
  				{
  					this.m_perp = Rot.mulVec2(qA, this.m_localYAxisA);
  
  					this.m_s1 = Vec2.cross(Vec2.add(d, rA), this.m_perp);
  					this.m_s2 = Vec2.cross(rB, this.m_perp);
  
  					var s1test = Vec2.cross(rA, this.m_perp);
  
  					var k11 = mA + mB + iA * this.m_s1 * this.m_s1 + iB * this.m_s2 * this.m_s2;
  					var k12 = iA * this.m_s1 + iB * this.m_s2;
  					var k13 = iA * this.m_s1 * this.m_a1 + iB * this.m_s2 * this.m_a2;
  					var k22 = iA + iB;
  					if (k22 == 0.0) {
  						// For bodies with fixed rotation.
  						k22 = 1.0;
  					}
  					var k23 = iA * this.m_a1 + iB * this.m_a2;
  					var k33 = mA + mB + iA * this.m_a1 * this.m_a1 + iB * this.m_a2 * this.m_a2;
  
  					this.m_K.ex.set(k11, k12, k13);
  					this.m_K.ey.set(k12, k22, k23);
  					this.m_K.ez.set(k13, k23, k33);
  				}
  
  				// Compute motor and limit terms.
  				if (this.m_enableLimit) {
  					var jointTranslation = Vec2.dot(this.m_axis, d); // float
  					if (Math.abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * Settings.linearSlop) {
  						this.m_limitState = equalLimits;
  					} else if (jointTranslation <= this.m_lowerTranslation) {
  						if (this.m_limitState != atLowerLimit) {
  							this.m_limitState = atLowerLimit;
  							this.m_impulse.z = 0.0;
  						}
  					} else if (jointTranslation >= this.m_upperTranslation) {
  						if (this.m_limitState != atUpperLimit) {
  							this.m_limitState = atUpperLimit;
  							this.m_impulse.z = 0.0;
  						}
  					} else {
  						this.m_limitState = inactiveLimit;
  						this.m_impulse.z = 0.0;
  					}
  				} else {
  					this.m_limitState = inactiveLimit;
  					this.m_impulse.z = 0.0;
  				}
  
  				if (this.m_enableMotor == false) {
  					this.m_motorImpulse = 0.0;
  				}
  
  				if (step.warmStarting) {
  					// Account for variable time step.
  					this.m_impulse.mul(step.dtRatio);
  					this.m_motorImpulse *= step.dtRatio;
  
  					var P = Vec2.combine(this.m_impulse.x, this.m_perp, this.m_motorImpulse + this.m_impulse.z, this.m_axis);
  					var LA = this.m_impulse.x * this.m_s1 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a1;
  					var LB = this.m_impulse.x * this.m_s2 + this.m_impulse.y + (this.m_motorImpulse + this.m_impulse.z) * this.m_a2;
  
  					vA.subMul(mA, P);
  					wA -= iA * LA;
  
  					vB.addMul(mB, P);
  					wB += iB * LB;
  				} else {
  					this.m_impulse.setZero();
  					this.m_motorImpulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			PrismaticJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB;
  				var iA = this.m_invIA;
  				var iB = this.m_invIB;
  
  				// Solve linear motor constraint.
  				if (this.m_enableMotor && this.m_limitState != equalLimits) {
  					var Cdot = Vec2.dot(this.m_axis, Vec2.sub(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA;
  					var impulse = this.m_motorMass * (this.m_motorSpeed - Cdot);
  					var oldImpulse = this.m_motorImpulse;
  					var maxImpulse = step.dt * this.m_maxMotorForce;
  					this.m_motorImpulse = Math.clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse);
  					impulse = this.m_motorImpulse - oldImpulse;
  
  					var P = Vec2.mul(impulse, this.m_axis);
  					var LA = impulse * this.m_a1;
  					var LB = impulse * this.m_a2;
  
  					vA.subMul(mA, P);
  					wA -= iA * LA;
  
  					vB.addMul(mB, P);
  					wB += iB * LB;
  				}
  
  				var Cdot1 = Vec2.zero();
  				Cdot1.x += Vec2.dot(this.m_perp, vB) + this.m_s2 * wB;
  				Cdot1.x -= Vec2.dot(this.m_perp, vA) + this.m_s1 * wA;
  				Cdot1.y = wB - wA;
  
  				if (this.m_enableLimit && this.m_limitState != inactiveLimit) {
  					// Solve prismatic and limit constraint in block form.
  					var Cdot2 = 0;
  					Cdot2 += Vec2.dot(this.m_axis, vB) + this.m_a2 * wB;
  					Cdot2 -= Vec2.dot(this.m_axis, vA) + this.m_a1 * wA;
  
  					var Cdot = Vec3(Cdot1.x, Cdot1.y, Cdot2);
  
  					var f1 = Vec3(this.m_impulse);
  					var df = this.m_K.solve33(Vec3.neg(Cdot)); // Vec3
  					this.m_impulse.add(df);
  
  					if (this.m_limitState == atLowerLimit) {
  						this.m_impulse.z = Math.max(this.m_impulse.z, 0.0);
  					} else if (this.m_limitState == atUpperLimit) {
  						this.m_impulse.z = Math.min(this.m_impulse.z, 0.0);
  					}
  
  					// f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) +
  					// f1(1:2)
  					var b = Vec2.combine(-1, Cdot1, -(this.m_impulse.z - f1.z), Vec2.neo(this.m_K.ez.x, this.m_K.ez.y)); // Vec2
  					var f2r = Vec2.add(this.m_K.solve22(b), Vec2.neo(f1.x, f1.y)); // Vec2
  					this.m_impulse.x = f2r.x;
  					this.m_impulse.y = f2r.y;
  
  					df = Vec3.sub(this.m_impulse, f1);
  
  					var P = Vec2.combine(df.x, this.m_perp, df.z, this.m_axis); // Vec2
  					var LA = df.x * this.m_s1 + df.y + df.z * this.m_a1; // float
  					var LB = df.x * this.m_s2 + df.y + df.z * this.m_a2; // float
  
  					vA.subMul(mA, P);
  					wA -= iA * LA;
  
  					vB.addMul(mB, P);
  					wB += iB * LB;
  				} else {
  					// Limit is inactive, just solve the prismatic constraint in block form.
  					var df = this.m_K.solve22(Vec2.neg(Cdot1)); // Vec2
  					this.m_impulse.x += df.x;
  					this.m_impulse.y += df.y;
  
  					var P = Vec2.mul(df.x, this.m_perp); // Vec2
  					var LA = df.x * this.m_s1 + df.y; // float
  					var LB = df.x * this.m_s2 + df.y; // float
  
  					vA.subMul(mA, P);
  					wA -= iA * LA;
  
  					vB.addMul(mB, P);
  					wB += iB * LB;
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			PrismaticJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB;
  				var iA = this.m_invIA;
  				var iB = this.m_invIB;
  
  				// Compute fresh Jacobians
  				var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA)); // Vec2
  				var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB)); // Vec2
  				var d = Vec2.sub(Vec2.add(cB, rB), Vec2.add(cA, rA)); // Vec2
  
  				var axis = Rot.mulVec2(qA, this.m_localXAxisA); // Vec2
  				var a1 = Vec2.cross(Vec2.add(d, rA), axis); // float
  				var a2 = Vec2.cross(rB, axis); // float
  				var perp = Rot.mulVec2(qA, this.m_localYAxisA); // Vec2
  
  				var s1 = Vec2.cross(Vec2.add(d, rA), perp); // float
  				var s2 = Vec2.cross(rB, perp); // float
  
  				var impulse = Vec3();
  				var C1 = Vec2.zero(); // Vec2
  				C1.x = Vec2.dot(perp, d);
  				C1.y = aB - aA - this.m_referenceAngle;
  
  				var linearError = Math.abs(C1.x); // float
  				var angularError = Math.abs(C1.y); // float
  
  				var linearSlop = Settings.linearSlop;
  				var maxLinearCorrection = Settings.maxLinearCorrection;
  
  				var active = false; // bool
  				var C2 = 0.0; // float
  				if (this.m_enableLimit) {
  					var translation = Vec2.dot(axis, d); // float
  					if (Math.abs(this.m_upperTranslation - this.m_lowerTranslation) < 2.0 * linearSlop) {
  						// Prevent large angular corrections
  						C2 = Math.clamp(translation, -maxLinearCorrection, maxLinearCorrection);
  						linearError = Math.max(linearError, Math.abs(translation));
  						active = true;
  					} else if (translation <= this.m_lowerTranslation) {
  						// Prevent large linear corrections and allow some slop.
  						C2 = Math.clamp(translation - this.m_lowerTranslation + linearSlop, -maxLinearCorrection, 0.0);
  						linearError = Math.max(linearError, this.m_lowerTranslation - translation);
  						active = true;
  					} else if (translation >= this.m_upperTranslation) {
  						// Prevent large linear corrections and allow some slop.
  						C2 = Math.clamp(translation - this.m_upperTranslation - linearSlop, 0.0, maxLinearCorrection);
  						linearError = Math.max(linearError, translation - this.m_upperTranslation);
  						active = true;
  					}
  				}
  
  				if (active) {
  					var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; // float
  					var k12 = iA * s1 + iB * s2; // float
  					var k13 = iA * s1 * a1 + iB * s2 * a2; // float
  					var k22 = iA + iB; // float
  					if (k22 == 0.0) {
  						// For fixed rotation
  						k22 = 1.0;
  					}
  					var k23 = iA * a1 + iB * a2; // float
  					var k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; // float
  
  					var K = new Mat33();
  					K.ex.set(k11, k12, k13);
  					K.ey.set(k12, k22, k23);
  					K.ez.set(k13, k23, k33);
  
  					var C = Vec3();
  					C.x = C1.x;
  					C.y = C1.y;
  					C.z = C2;
  
  					impulse = K.solve33(Vec3.neg(C));
  				} else {
  					var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; // float
  					var k12 = iA * s1 + iB * s2; // float
  					var k22 = iA + iB; // float
  					if (k22 == 0.0) {
  						k22 = 1.0;
  					}
  
  					var K = new Mat22();
  					K.ex.set(k11, k12);
  					K.ey.set(k12, k22);
  
  					var impulse1 = K.solve(Vec2.neg(C1)); // Vec2
  					impulse.x = impulse1.x;
  					impulse.y = impulse1.y;
  					impulse.z = 0.0;
  				}
  
  				var P = Vec2.combine(impulse.x, perp, impulse.z, axis); // Vec2
  				var LA = impulse.x * s1 + impulse.y + impulse.z * a1; // float
  				var LB = impulse.x * s2 + impulse.y + impulse.z * a2; // float
  
  				cA.subMul(mA, P);
  				aA -= iA * LA;
  				cB.addMul(mB, P);
  				aB += iB * LB;
  
  				this.m_bodyA.c_position.c = cA;
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c = cB;
  				this.m_bodyB.c_position.a = aB;
  
  				return linearError <= Settings.linearSlop && angularError <= Settings.angularSlop;
  			};
  
  			/***/
  		},, /* 37 */ /* 38 */ /* 39 */, ,
  
  		/* 36 */ /***/ function (module, exports, __webpack_require__) {
  			exports.internal = {};
  
  			exports.Serializer = __webpack_require__(40);
  
  			exports.Math = __webpack_require__(1);
  			exports.Vec2 = __webpack_require__(0);
  			exports.Vec3 = __webpack_require__(11);
  			exports.Mat22 = __webpack_require__(10);
  			exports.Mat33 = __webpack_require__(15);
  			exports.Transform = __webpack_require__(5);
  			exports.Rot = __webpack_require__(3);
  
  			exports.AABB = __webpack_require__(17);
  
  			exports.Shape = __webpack_require__(16);
  			exports.Fixture = __webpack_require__(32);
  			exports.Body = __webpack_require__(8);
  			exports.Contact = __webpack_require__(18);
  			exports.Joint = __webpack_require__(12);
  			exports.World = __webpack_require__(30);
  
  			exports.Circle = __webpack_require__(23);
  			exports.Edge = __webpack_require__(24);
  			exports.Polygon = __webpack_require__(21);
  			exports.Chain = __webpack_require__(28);
  			exports.Box = __webpack_require__(45);
  
  			__webpack_require__(46);
  			__webpack_require__(47);
  			exports.internal.CollidePolygons = __webpack_require__(48);
  			__webpack_require__(49);
  			__webpack_require__(50);
  
  			exports.DistanceJoint = __webpack_require__(51);
  			exports.FrictionJoint = __webpack_require__(52);
  			exports.GearJoint = __webpack_require__(53);
  			exports.MotorJoint = __webpack_require__(54);
  			exports.MouseJoint = __webpack_require__(55);
  			exports.PrismaticJoint = __webpack_require__(35);
  			exports.PulleyJoint = __webpack_require__(56);
  			exports.RevoluteJoint = __webpack_require__(34);
  			exports.RopeJoint = __webpack_require__(57);
  			exports.WeldJoint = __webpack_require__(58);
  			exports.WheelJoint = __webpack_require__(59);
  
  			exports.internal.Sweep = __webpack_require__(9);
  			exports.internal.stats = __webpack_require__(27);
  			exports.internal.Manifold = __webpack_require__(19);
  			exports.internal.Distance = __webpack_require__(22);
  			exports.internal.TimeOfImpact = __webpack_require__(33);
  			exports.internal.DynamicTree = __webpack_require__(31);
  			exports.internal.Settings = __webpack_require__(4);
  
  			/***/
  		},
  		/* 40 */
  		/***/ function (module, exports, __webpack_require__) {
  			var World = __webpack_require__(30);
  			var Body = __webpack_require__(8);
  			var Joint = __webpack_require__(12);
  			var Shape = __webpack_require__(16);
  
  			var SID = 0;
  
  			function Serializer (opts) {
  				opts = opts || {};
  
  				var stringify = opts.stringify || JSON.stringify;
  				var parse = opts.parse || JSON.parse;
  
  				var rootClass = opts.rootClass || World;
  
  				var preSerialize =
                      opts.preSerialize ||
                      function (obj) {
                      	return obj;
                      };
  				var postSerialize =
                      opts.postSerialize ||
                      function (data, obj) {
                      	return data;
                      };
  
  				var preDeserialize =
                      opts.preDeserialize ||
                      function (data) {
                      	return data;
                      };
  				var postDeserialize =
                      opts.postDeserialize ||
                      function (obj, data) {
                      	return obj;
                      };
  
  				var refTypes = {
  					World: World,
  					Body: Body,
  					Joint: Joint
  				};
  
  				this.toJson = function (root) {
  					var flat = [];
  					var queue = [root];
  					var refMap = {};
  
  					function storeRef (value, typeName) {
  						value.__sid = value.__sid || ++SID;
  						if (!refMap[value.__sid]) {
  							queue.push(value);
  							var index = flat.length + queue.length;
  							var ref = {
  								refIndex: index,
  								refType: typeName
  							};
  							refMap[value.__sid] = ref;
  						}
  						return refMap[value.__sid];
  					}
  
  					function serialize (obj) {
  						obj = preSerialize(obj);
  						var data = obj._serialize();
  						data = postSerialize(data, obj);
  						return data;
  					}
  
  					while (queue.length) {
  						var obj = queue.shift();
  						var str = stringify(
  							obj,
  							function (key, value) {
  								if (typeof value !== 'object' || value === null) {
  									return value;
  								}
  								if (typeof value._serialize !== 'function') {
  									return value;
  								}
  								if (value === obj) {
  									return serialize(value);
  								}
  								for (var typeName in refTypes) {
  									if (value instanceof refTypes[typeName]) {
  										return storeRef(value, typeName);
  									}
  								}
  								return serialize(value);
  							},
  							'  '
  						);
  						flat.push(str);
  					}
  
  					var result = `[${flat.join(',')}]`;
  					return result;
  				};
  
  				this.fromJson = function (string) {
  					var flat = parse(string);
  					var refMap = {};
  
  					function deserialize (cls, data, ctx) {
  						data = preDeserialize(data);
  						var obj = cls._deserialize(data, ctx, restoreRef);
  						obj = postDeserialize(obj, data);
  						return obj;
  					}
  
  					function restoreRef (cls, ref, ctx) {
  						if (!ref.refIndex) {
  							return cls && cls._deserialize && deserialize(cls, ref, ctx);
  						}
  						cls = refTypes[ref.refType] || cls;
  						var index = ref.refIndex;
  						if (!refMap[index]) {
  							var data = flat[index];
  							var obj = deserialize(cls, data, ctx);
  							refMap[index] = obj;
  						}
  						return refMap[index];
  					}
  
  					var root = rootClass._deserialize(flat[0], null, restoreRef);
  
  					return root;
  				};
  			}
  
  			module.exports = Serializer;
  
  			var serializer = new Serializer();
  			module.exports.toJson = serializer.toJson;
  			module.exports.fromJson = serializer.fromJson;
  
  			/***/
  		},
  		/* 41 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var Settings = __webpack_require__(4);
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var AABB = __webpack_require__(17);
  			var DynamicTree = __webpack_require__(31);
  
  			module.exports = BroadPhase;
  
  			/**
               * The broad-phase wraps and extends a dynamic-tree to keep track of moved
               * objects and query them on update.
               */
  			function BroadPhase () {
  				this.m_tree = new DynamicTree();
  				this.m_proxyCount = 0;
  				this.m_moveBuffer = [];
  				this.queryCallback = this.queryCallback.bind(this);
  			}
  
  			/**
               * Get user data from a proxy. Returns null if the id is invalid.
               */
  			BroadPhase.prototype.getUserData = function (proxyId) {
  				return this.m_tree.getUserData(proxyId);
  			};
  
  			/**
               * Test overlap of fat AABBs.
               */
  			BroadPhase.prototype.testOverlap = function (proxyIdA, proxyIdB) {
  				var aabbA = this.m_tree.getFatAABB(proxyIdA);
  				var aabbB = this.m_tree.getFatAABB(proxyIdB);
  				return AABB.testOverlap(aabbA, aabbB);
  			};
  
  			/**
               * Get the fat AABB for a proxy.
               */
  			BroadPhase.prototype.getFatAABB = function (proxyId) {
  				return this.m_tree.getFatAABB(proxyId);
  			};
  
  			/**
               * Get the number of proxies.
               */
  			BroadPhase.prototype.getProxyCount = function () {
  				return this.m_proxyCount;
  			};
  
  			/**
               * Get the height of the embedded tree.
               */
  			BroadPhase.prototype.getTreeHeight = function () {
  				return this.m_tree.getHeight();
  			};
  
  			/**
               * Get the balance (integer) of the embedded tree.
               */
  			BroadPhase.prototype.getTreeBalance = function () {
  				return this.m_tree.getMaxBalance();
  			};
  
  			/**
               * Get the quality metric of the embedded tree.
               */
  			BroadPhase.prototype.getTreeQuality = function () {
  				return this.m_tree.getAreaRatio();
  			};
  
  			/**
               * Query an AABB for overlapping proxies. The callback class is called for each
               * proxy that overlaps the supplied AABB.
               */
  			BroadPhase.prototype.query = function (aabb, queryCallback) {
  				this.m_tree.query(aabb, queryCallback);
  			};
  
  			/**
               * Ray-cast against the proxies in the tree. This relies on the callback to
               * perform a exact ray-cast in the case were the proxy contains a shape. The
               * callback also performs the any collision filtering. This has performance
               * roughly equal to k * log(n), where k is the number of collisions and n is the
               * number of proxies in the tree.
               *
               * @param input The ray-cast input data. The ray extends from p1 to p1 +
               *          maxFraction * (p2 - p1).
               * @param rayCastCallback A function that is called for each proxy that is hit by
               *          the ray.
               */
  			BroadPhase.prototype.rayCast = function (input, rayCastCallback) {
  				this.m_tree.rayCast(input, rayCastCallback);
  			};
  
  			/**
               * Shift the world origin. Useful for large worlds. The shift formula is:
               * position -= newOrigin
               *
               * @param newOrigin The new origin with respect to the old origin
               */
  			BroadPhase.prototype.shiftOrigin = function (newOrigin) {
  				this.m_tree.shiftOrigin(newOrigin);
  			};
  
  			/**
               * Create a proxy with an initial AABB. Pairs are not reported until UpdatePairs
               * is called.
               */
  			BroadPhase.prototype.createProxy = function (aabb, userData) {
  				_ASSERT && common.assert(AABB.isValid(aabb));
  				var proxyId = this.m_tree.createProxy(aabb, userData);
  				this.m_proxyCount++;
  				this.bufferMove(proxyId);
  				return proxyId;
  			};
  
  			/**
               * Destroy a proxy. It is up to the client to remove any pairs.
               */
  			BroadPhase.prototype.destroyProxy = function (proxyId) {
  				this.unbufferMove(proxyId);
  				this.m_proxyCount--;
  				this.m_tree.destroyProxy(proxyId);
  			};
  
  			/**
               * Call moveProxy as many times as you like, then when you are done call
               * UpdatePairs to finalized the proxy pairs (for your time step).
               */
  			BroadPhase.prototype.moveProxy = function (proxyId, aabb, displacement) {
  				_ASSERT && common.assert(AABB.isValid(aabb));
  				var changed = this.m_tree.moveProxy(proxyId, aabb, displacement);
  				if (changed) {
  					this.bufferMove(proxyId);
  				}
  			};
  
  			/**
               * Call to trigger a re-processing of it's pairs on the next call to
               * UpdatePairs.
               */
  			BroadPhase.prototype.touchProxy = function (proxyId) {
  				this.bufferMove(proxyId);
  			};
  
  			BroadPhase.prototype.bufferMove = function (proxyId) {
  				this.m_moveBuffer.push(proxyId);
  			};
  
  			BroadPhase.prototype.unbufferMove = function (proxyId) {
  				for (var i = 0; i < this.m_moveBuffer.length; ++i) {
  					if (this.m_moveBuffer[i] == proxyId) {
  						this.m_moveBuffer[i] = null;
  					}
  				}
  			};
  
  			/**
               * @function BroadPhase~addPair
               * @param {Object} userDataA
               * @param {Object} userDataB
               */
  
  			/**
               * Update the pairs. This results in pair callbacks. This can only add pairs.
               *
               * @param {BroadPhase~AddPair} addPairCallback
               */
  			BroadPhase.prototype.updatePairs = function (addPairCallback) {
  				_ASSERT && common.assert(typeof addPairCallback === 'function');
  				this.m_callback = addPairCallback;
  
  				// Perform tree queries for all moving proxies.
  				while (this.m_moveBuffer.length > 0) {
  					this.m_queryProxyId = this.m_moveBuffer.pop();
  					if (this.m_queryProxyId === null) {
  						continue;
  					}
  
  					// We have to query the tree with the fat AABB so that
  					// we don't fail to create a pair that may touch later.
  					var fatAABB = this.m_tree.getFatAABB(this.m_queryProxyId);
  
  					// Query tree, create pairs and add them pair buffer.
  					this.m_tree.query(fatAABB, this.queryCallback);
  				}
  
  				// Try to keep the tree balanced.
  				// this.m_tree.rebalance(4);
  			};
  
  			BroadPhase.prototype.queryCallback = function (proxyId) {
  				// A proxy cannot form a pair with itself.
  				if (proxyId == this.m_queryProxyId) {
  					return true;
  				}
  
  				var proxyIdA = Math.min(proxyId, this.m_queryProxyId);
  				var proxyIdB = Math.max(proxyId, this.m_queryProxyId);
  
  				// TODO: Skip any duplicate pairs.
  
  				var userDataA = this.m_tree.getUserData(proxyIdA);
  				var userDataB = this.m_tree.getUserData(proxyIdB);
  
  				// Send the pairs back to the client.
  				this.m_callback(userDataA, userDataB);
  
  				return true;
  			};
  
  			/***/
  		},
  		/* 42 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Pool;
  
  			function Pool (opts) {
  				var _list = [];
  				var _max = opts.max || Infinity;
  
  				var _createFn = opts.create;
  				var _outFn = opts.allocate;
  				var _inFn = opts.release;
  				var _discardFn = opts.discard;
  
  				var _createCount = 0;
  				var _outCount = 0;
  				var _inCount = 0;
  				var _discardCount = 0;
  
  				this.max = function (n) {
  					if (typeof n === 'number') {
  						_max = n;
  						return this;
  					}
  					return _max;
  				};
  
  				this.size = function () {
  					return _list.length;
  				};
  
  				this.allocate = function () {
  					var item;
  					if (_list.length > 0) {
  						item = _list.shift();
  					} else {
  						_createCount++;
  						if (typeof _createFn === 'function') {
  							item = _createFn();
  						} else {
  							item = {};
  						}
  					}
  					_outCount++;
  					if (typeof _outFn === 'function') {
  						_outFn(item);
  					}
  					return item;
  				};
  
  				this.release = function (item) {
  					if (_list.length < _max) {
  						_inCount++;
  						if (typeof _inFn === 'function') {
  							_inFn(item);
  						}
  						_list.push(item);
  					} else {
  						_discardCount++;
  						if (typeof _discardFn === 'function') {
  							item = _discardFn(item);
  						}
  					}
  				};
  
  				this.toString = function () {
  					return ` +${_createCount} >${_outCount} <${_inCount} -${_discardCount} =${_list.length}/${_max}`;
  				};
  			}
  
  			/***/
  		},
  		/* 43 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = Solver;
  			module.exports.TimeStep = TimeStep;
  
  			var Settings = __webpack_require__(4);
  			var common = __webpack_require__(2);
  
  			var Vec2 = __webpack_require__(0);
  			var Math = __webpack_require__(1);
  
  			var Body = __webpack_require__(8);
  			var Contact = __webpack_require__(18);
  			var Joint = __webpack_require__(12);
  
  			var TimeOfImpact = __webpack_require__(33);
  			var TOIInput = TimeOfImpact.Input;
  			var TOIOutput = TimeOfImpact.Output;
  
  			var Distance = __webpack_require__(22);
  			var DistanceInput = Distance.Input;
  			var DistanceOutput = Distance.Output;
  			var DistanceProxy = Distance.Proxy;
  			var SimplexCache = Distance.Cache;
  
  			function TimeStep (dt) {
  				this.dt = 0; // time step
  				this.inv_dt = 0; // inverse time step (0 if dt == 0)
  				this.velocityIterations = 0;
  				this.positionIterations = 0;
  				this.warmStarting = false;
  				this.blockSolve = true;
  
  				// timestep ratio for variable timestep
  				this.inv_dt0 = 0.0;
  				this.dtRatio = 1; // dt * inv_dt0
  			}
  
  			TimeStep.prototype.reset = function (dt) {
  				if (this.dt > 0.0) {
  					this.inv_dt0 = this.inv_dt;
  				}
  				this.dt = dt;
  				this.inv_dt = dt == 0 ? 0 : 1 / dt;
  				this.dtRatio = dt * this.inv_dt0;
  			};
  
  			/**
               * Finds and solves islands. An island is a connected subset of the world.
               *
               * @param {World} world
               */
  			function Solver (world) {
  				this.m_world = world;
  				this.m_stack = [];
  				this.m_bodies = [];
  				this.m_contacts = [];
  				this.m_joints = [];
  			}
  
  			Solver.prototype.clear = function () {
  				this.m_stack.length = 0;
  				this.m_bodies.length = 0;
  				this.m_contacts.length = 0;
  				this.m_joints.length = 0;
  			};
  
  			Solver.prototype.addBody = function (body) {
  				_ASSERT && common.assert(body instanceof Body, 'Not a Body!', body);
  				this.m_bodies.push(body);
  				// why?
  				//  body.c_position.c.setZero();
  				//  body.c_position.a = 0;
  				//  body.c_velocity.v.setZero();
  				//  body.c_velocity.w = 0;
  			};
  
  			Solver.prototype.addContact = function (contact) {
  				_ASSERT && common.assert(contact instanceof Contact, 'Not a Contact!', contact);
  				this.m_contacts.push(contact);
  			};
  
  			Solver.prototype.addJoint = function (joint) {
  				_ASSERT && common.assert(joint instanceof Joint, 'Not a Joint!', joint);
  				this.m_joints.push(joint);
  			};
  
  			/**
               * @param {TimeStep} step
               */
  			Solver.prototype.solveWorld = function (step) {
  				var world = this.m_world;
  
  				// Clear all the island flags.
  				for (var b = world.m_bodyList; b; b = b.m_next) {
  					b.m_islandFlag = false;
  				}
  				for (var c = world.m_contactList; c; c = c.m_next) {
  					c.m_islandFlag = false;
  				}
  				for (var j = world.m_jointList; j; j = j.m_next) {
  					j.m_islandFlag = false;
  				}
  
  				// Build and simulate all awake islands.
  				var stack = this.m_stack;
  				var loop = -1;
  				for (var seed = world.m_bodyList; seed; seed = seed.m_next) {
  					loop++;
  					if (seed.m_islandFlag) {
  						continue;
  					}
  
  					if (seed.isAwake() == false || seed.isActive() == false) {
  						continue;
  					}
  
  					// The seed can be dynamic or kinematic.
  					if (seed.isStatic()) {
  						continue;
  					}
  
  					// Reset island and stack.
  					this.clear();
  
  					stack.push(seed);
  
  					seed.m_islandFlag = true;
  
  					// Perform a depth first search (DFS) on the constraint graph.
  					while (stack.length > 0) {
  						// Grab the next body off the stack and add it to the island.
  						var b = stack.pop();
  						_ASSERT && common.assert(b.isActive() == true);
  						this.addBody(b);
  
  						// Make sure the body is awake.
  						b.setAwake(true);
  
  						// To keep islands as small as possible, we don't
  						// propagate islands across static bodies.
  						if (b.isStatic()) {
  							continue;
  						}
  
  						// Search all contacts connected to this body.
  						for (var ce = b.m_contactList; ce; ce = ce.next) {
  							var contact = ce.contact;
  
  							// Has this contact already been added to an island?
  							if (contact.m_islandFlag) {
  								continue;
  							}
  
  							// Is this contact solid and touching?
  							if (contact.isEnabled() == false || contact.isTouching() == false) {
  								continue;
  							}
  
  							// Skip sensors.
  							var sensorA = contact.m_fixtureA.m_isSensor;
  							var sensorB = contact.m_fixtureB.m_isSensor;
  							if (sensorA || sensorB) {
  								continue;
  							}
  
  							this.addContact(contact);
  							contact.m_islandFlag = true;
  
  							var other = ce.other;
  
  							// Was the other body already added to this island?
  							if (other.m_islandFlag) {
  								continue;
  							}
  
  							// _ASSERT && common.assert(stack.length < world.m_bodyCount);
  							stack.push(other);
  							other.m_islandFlag = true;
  						}
  
  						// Search all joints connect to this body.
  						for (var je = b.m_jointList; je; je = je.next) {
  							if (je.joint.m_islandFlag == true) {
  								continue;
  							}
  
  							var other = je.other;
  
  							// Don't simulate joints connected to inactive bodies.
  							if (other.isActive() == false) {
  								continue;
  							}
  
  							this.addJoint(je.joint);
  							je.joint.m_islandFlag = true;
  
  							if (other.m_islandFlag) {
  								continue;
  							}
  
  							// _ASSERT && common.assert(stack.length < world.m_bodyCount);
  							stack.push(other);
  							other.m_islandFlag = true;
  						}
  					}
  
  					this.solveIsland(step);
  
  					// Post solve cleanup.
  					for (var i = 0; i < this.m_bodies.length; ++i) {
  						// Allow static bodies to participate in other islands.
  						// TODO: are they added at all?
  						var b = this.m_bodies[i];
  						if (b.isStatic()) {
  							b.m_islandFlag = false;
  						}
  					}
  				}
  			};
  
  			/**
               * @param {TimeStep} step
               */
  			Solver.prototype.solveIsland = function (step) {
  				// B2: Island Solve
  				var world = this.m_world;
  				var gravity = world.m_gravity;
  				var allowSleep = world.m_allowSleep;
  
  				var h = step.dt;
  
  				// Integrate velocities and apply damping. Initialize the body state.
  				for (var i = 0; i < this.m_bodies.length; ++i) {
  					var body = this.m_bodies[i];
  
  					var c = Vec2.clone(body.m_sweep.c);
  					var a = body.m_sweep.a;
  					var v = Vec2.clone(body.m_linearVelocity);
  					var w = body.m_angularVelocity;
  
  					// Store positions for continuous collision.
  					body.m_sweep.c0.set(body.m_sweep.c);
  					body.m_sweep.a0 = body.m_sweep.a;
  
  					if (body.isDynamic()) {
  						// Integrate velocities.
  						v.addMul(h * body.m_gravityScale, gravity);
  						v.addMul(h * body.m_invMass, body.m_force);
  						w += h * body.m_invI * body.m_torque;
  						/**
                           * <pre>
                           * Apply damping.
                           * ODE: dv/dt + c * v = 0
                           * Solution: v(t) = v0 * exp(-c * t)
                           * Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt)
                           * v2 = exp(-c * dt) * v1
                           * Pade approximation:
                           * v2 = v1 * 1 / (1 + c * dt)
                           * </pre>
                           */
  						v.mul(1.0 / (1.0 + h * body.m_linearDamping));
  						w *= 1.0 / (1.0 + h * body.m_angularDamping);
  					}
  
  					body.c_position.c = c;
  					body.c_position.a = a;
  					body.c_velocity.v = v;
  					body.c_velocity.w = w;
  				}
  
  				for (var i = 0; i < this.m_contacts.length; ++i) {
  					var contact = this.m_contacts[i];
  					contact.initConstraint(step);
  				}
  
  				_DEBUG && this.printBodies('M: ');
  
  				for (var i = 0; i < this.m_contacts.length; ++i) {
  					var contact = this.m_contacts[i];
  					contact.initVelocityConstraint(step);
  				}
  
  				_DEBUG && this.printBodies('R: ');
  
  				if (step.warmStarting) {
  					// Warm start.
  					for (var i = 0; i < this.m_contacts.length; ++i) {
  						var contact = this.m_contacts[i];
  						contact.warmStartConstraint(step);
  					}
  				}
  
  				_DEBUG && this.printBodies('Q: ');
  
  				for (var i = 0; i < this.m_joints.length; ++i) {
  					var joint = this.m_joints[i];
  					joint.initVelocityConstraints(step);
  				}
  
  				_DEBUG && this.printBodies('E: ');
  
  				// Solve velocity constraints
  				for (var i = 0; i < step.velocityIterations; ++i) {
  					for (var j = 0; j < this.m_joints.length; ++j) {
  						var joint = this.m_joints[j];
  						joint.solveVelocityConstraints(step);
  					}
  
  					for (var j = 0; j < this.m_contacts.length; ++j) {
  						var contact = this.m_contacts[j];
  						contact.solveVelocityConstraint(step);
  					}
  				}
  
  				_DEBUG && this.printBodies('D: ');
  
  				// Store impulses for warm starting
  				for (var i = 0; i < this.m_contacts.length; ++i) {
  					var contact = this.m_contacts[i];
  					contact.storeConstraintImpulses(step);
  				}
  
  				_DEBUG && this.printBodies('C: ');
  
  				// Integrate positions
  				for (var i = 0; i < this.m_bodies.length; ++i) {
  					var body = this.m_bodies[i];
  
  					var c = Vec2.clone(body.c_position.c);
  					var a = body.c_position.a;
  					var v = Vec2.clone(body.c_velocity.v);
  					var w = body.c_velocity.w;
  
  					// Check for large velocities
  					var translation = Vec2.mul(h, v);
  					if (Vec2.lengthSquared(translation) > Settings.maxTranslationSquared) {
  						var ratio = Settings.maxTranslation / translation.length();
  						v.mul(ratio);
  					}
  
  					var rotation = h * w;
  					if (rotation * rotation > Settings.maxRotationSquared) {
  						var ratio = Settings.maxRotation / Math.abs(rotation);
  						w *= ratio;
  					}
  
  					// Integrate
  					c.addMul(h, v);
  					a += h * w;
  
  					body.c_position.c.set(c);
  					body.c_position.a = a;
  					body.c_velocity.v.set(v);
  					body.c_velocity.w = w;
  				}
  
  				_DEBUG && this.printBodies('B: ');
  
  				// Solve position constraints
  				var positionSolved = false;
  				for (var i = 0; i < step.positionIterations; ++i) {
  					var minSeparation = 0.0;
  					for (var j = 0; j < this.m_contacts.length; ++j) {
  						var contact = this.m_contacts[j];
  						var separation = contact.solvePositionConstraint(step);
  						minSeparation = Math.min(minSeparation, separation);
  					}
  					// We can't expect minSpeparation >= -Settings.linearSlop because we don't
  					// push the separation above -Settings.linearSlop.
  					var contactsOkay = minSeparation >= -3.0 * Settings.linearSlop;
  
  					var jointsOkay = true;
  					for (var j = 0; j < this.m_joints.length; ++j) {
  						var joint = this.m_joints[j];
  						var jointOkay = joint.solvePositionConstraints(step);
  						jointsOkay = jointsOkay && jointOkay;
  					}
  
  					if (contactsOkay && jointsOkay) {
  						// Exit early if the position errors are small.
  						positionSolved = true;
  						break;
  					}
  				}
  
  				_DEBUG && this.printBodies('L: ');
  
  				// Copy state buffers back to the bodies
  				for (var i = 0; i < this.m_bodies.length; ++i) {
  					var body = this.m_bodies[i];
  
  					body.m_sweep.c.set(body.c_position.c);
  					body.m_sweep.a = body.c_position.a;
  					body.m_linearVelocity.set(body.c_velocity.v);
  					body.m_angularVelocity = body.c_velocity.w;
  					body.synchronizeTransform();
  				}
  
  				this.postSolveIsland();
  
  				if (allowSleep) {
  					var minSleepTime = Infinity;
  
  					var linTolSqr = Settings.linearSleepToleranceSqr;
  					var angTolSqr = Settings.angularSleepToleranceSqr;
  
  					for (var i = 0; i < this.m_bodies.length; ++i) {
  						var body = this.m_bodies[i];
  						if (body.isStatic()) {
  							continue;
  						}
  
  						if (body.m_autoSleepFlag == false || body.m_angularVelocity * body.m_angularVelocity > angTolSqr || Vec2.lengthSquared(body.m_linearVelocity) > linTolSqr) {
  							body.m_sleepTime = 0.0;
  							minSleepTime = 0.0;
  						} else {
  							body.m_sleepTime += h;
  							minSleepTime = Math.min(minSleepTime, body.m_sleepTime);
  						}
  					}
  
  					if (minSleepTime >= Settings.timeToSleep && positionSolved) {
  						for (var i = 0; i < this.m_bodies.length; ++i) {
  							var body = this.m_bodies[i];
  							body.setAwake(false);
  						}
  					}
  				}
  			};
  
  			Solver.prototype.printBodies = function (tag) {
  				for (var i = 0; i < this.m_bodies.length; ++i) {
  					var b = this.m_bodies[i];
  					common.debug(tag, b.c_position.a, b.c_position.c.x, b.c_position.c.y, b.c_velocity.w, b.c_velocity.v.x, b.c_velocity.v.y);
  				}
  			};
  
  			var s_subStep = new TimeStep(); // reuse
  
  			/**
               * Find TOI contacts and solve them.
               *
               * @param {TimeStep} step
               */
  			Solver.prototype.solveWorldTOI = function (step) {
  				var world = this.m_world;
  
  				if (world.m_stepComplete) {
  					for (var b = world.m_bodyList; b; b = b.m_next) {
  						b.m_islandFlag = false;
  						b.m_sweep.alpha0 = 0.0;
  					}
  
  					for (var c = world.m_contactList; c; c = c.m_next) {
  						// Invalidate TOI
  						c.m_toiFlag = false;
  						c.m_islandFlag = false;
  						c.m_toiCount = 0;
  						c.m_toi = 1.0;
  					}
  				}
  
  				// Find TOI events and solve them.
  				for (;;) {
  					// Find the first TOI.
  					var minContact = null; // Contact
  					var minAlpha = 1.0;
  
  					for (var c = world.m_contactList; c; c = c.m_next) {
  						// Is this contact disabled?
  						if (c.isEnabled() == false) {
  							continue;
  						}
  
  						// Prevent excessive sub-stepping.
  						if (c.m_toiCount > Settings.maxSubSteps) {
  							continue;
  						}
  
  						var alpha = 1.0;
  						if (c.m_toiFlag) {
  							// This contact has a valid cached TOI.
  							alpha = c.m_toi;
  						} else {
  							var fA = c.getFixtureA();
  							var fB = c.getFixtureB();
  
  							// Is there a sensor?
  							if (fA.isSensor() || fB.isSensor()) {
  								continue;
  							}
  
  							var bA = fA.getBody();
  							var bB = fB.getBody();
  
  							_ASSERT && common.assert(bA.isDynamic() || bB.isDynamic());
  
  							var activeA = bA.isAwake() && !bA.isStatic();
  							var activeB = bB.isAwake() && !bB.isStatic();
  
  							// Is at least one body active (awake and dynamic or kinematic)?
  							if (activeA == false && activeB == false) {
  								continue;
  							}
  
  							var collideA = bA.isBullet() || !bA.isDynamic();
  							var collideB = bB.isBullet() || !bB.isDynamic();
  
  							// Are these two non-bullet dynamic bodies?
  							if (collideA == false && collideB == false) {
  								continue;
  							}
  
  							// Compute the TOI for this contact.
  							// Put the sweeps onto the same time interval.
  							var alpha0 = bA.m_sweep.alpha0;
  
  							if (bA.m_sweep.alpha0 < bB.m_sweep.alpha0) {
  								alpha0 = bB.m_sweep.alpha0;
  								bA.m_sweep.advance(alpha0);
  							} else if (bB.m_sweep.alpha0 < bA.m_sweep.alpha0) {
  								alpha0 = bA.m_sweep.alpha0;
  								bB.m_sweep.advance(alpha0);
  							}
  
  							_ASSERT && common.assert(alpha0 < 1.0);
  
  							var indexA = c.getChildIndexA();
  							var indexB = c.getChildIndexB();
  
  							var sweepA = bA.m_sweep;
  							var sweepB = bB.m_sweep;
  
  							// Compute the time of impact in interval [0, minTOI]
  							var input = new TOIInput(); // TODO: reuse
  							input.proxyA.set(fA.getShape(), indexA);
  							input.proxyB.set(fB.getShape(), indexB);
  							input.sweepA.set(bA.m_sweep);
  							input.sweepB.set(bB.m_sweep);
  							input.tMax = 1.0;
  
  							var output = new TOIOutput(); // TODO: reuse
  							TimeOfImpact(output, input);
  
  							// Beta is the fraction of the remaining portion of the [time?].
  							var beta = output.t;
  							if (output.state == TOIOutput.e_touching) {
  								alpha = Math.min(alpha0 + (1.0 - alpha0) * beta, 1.0);
  							} else {
  								alpha = 1.0;
  							}
  
  							c.m_toi = alpha;
  							c.m_toiFlag = true;
  						}
  
  						if (alpha < minAlpha) {
  							// This is the minimum TOI found so far.
  							minContact = c;
  							minAlpha = alpha;
  						}
  					}
  
  					if (minContact == null || 1.0 - 10.0 * Math.EPSILON < minAlpha) {
  						// No more TOI events. Done!
  						world.m_stepComplete = true;
  						break;
  					}
  
  					// Advance the bodies to the TOI.
  					var fA = minContact.getFixtureA();
  					var fB = minContact.getFixtureB();
  					var bA = fA.getBody();
  					var bB = fB.getBody();
  
  					var backup1 = bA.m_sweep.clone();
  					var backup2 = bB.m_sweep.clone();
  
  					bA.advance(minAlpha);
  					bB.advance(minAlpha);
  
  					// The TOI contact likely has some new contact points.
  					minContact.update(world);
  					minContact.m_toiFlag = false;
  					++minContact.m_toiCount;
  
  					// Is the contact solid?
  					if (minContact.isEnabled() == false || minContact.isTouching() == false) {
  						// Restore the sweeps.
  						minContact.setEnabled(false);
  						bA.m_sweep.set(backup1);
  						bB.m_sweep.set(backup2);
  						bA.synchronizeTransform();
  						bB.synchronizeTransform();
  						continue;
  					}
  
  					bA.setAwake(true);
  					bB.setAwake(true);
  
  					// Build the island
  					this.clear();
  					this.addBody(bA);
  					this.addBody(bB);
  					this.addContact(minContact);
  
  					bA.m_islandFlag = true;
  					bB.m_islandFlag = true;
  					minContact.m_islandFlag = true;
  
  					// Get contacts on bodyA and bodyB.
  					var bodies = [bA, bB];
  					for (var i = 0; i < bodies.length; ++i) {
  						var body = bodies[i];
  						if (body.isDynamic()) {
  							for (var ce = body.m_contactList; ce; ce = ce.next) {
  								// if (this.m_bodyCount == this.m_bodyCapacity) { break; }
  								// if (this.m_contactCount == this.m_contactCapacity) { break; }
  
  								var contact = ce.contact;
  
  								// Has this contact already been added to the island?
  								if (contact.m_islandFlag) {
  									continue;
  								}
  
  								// Only add if either is static, kinematic or bullet.
  								var other = ce.other;
  								if (other.isDynamic() && !body.isBullet() && !other.isBullet()) {
  									continue;
  								}
  
  								// Skip sensors.
  								var sensorA = contact.m_fixtureA.m_isSensor;
  								var sensorB = contact.m_fixtureB.m_isSensor;
  								if (sensorA || sensorB) {
  									continue;
  								}
  
  								// Tentatively advance the body to the TOI.
  								var backup = other.m_sweep.clone();
  								if (other.m_islandFlag == false) {
  									other.advance(minAlpha);
  								}
  
  								// Update the contact points
  								contact.update(world);
  
  								// Was the contact disabled by the user?
  								// Are there contact points?
  								if (contact.isEnabled() == false || contact.isTouching() == false) {
  									other.m_sweep.set(backup);
  									other.synchronizeTransform();
  									continue;
  								}
  
  								// Add the contact to the island
  								contact.m_islandFlag = true;
  								this.addContact(contact);
  
  								// Has the other body already been added to the island?
  								if (other.m_islandFlag) {
  									continue;
  								}
  
  								// Add the other body to the island.
  								other.m_islandFlag = true;
  
  								if (!other.isStatic()) {
  									other.setAwake(true);
  								}
  
  								this.addBody(other);
  							}
  						}
  					}
  
  					s_subStep.reset((1.0 - minAlpha) * step.dt);
  					s_subStep.dtRatio = 1.0;
  					s_subStep.positionIterations = 20;
  					s_subStep.velocityIterations = step.velocityIterations;
  					s_subStep.warmStarting = false;
  
  					this.solveIslandTOI(s_subStep, bA, bB);
  
  					// Reset island flags and synchronize broad-phase proxies.
  					for (var i = 0; i < this.m_bodies.length; ++i) {
  						var body = this.m_bodies[i];
  						body.m_islandFlag = false;
  
  						if (!body.isDynamic()) {
  							continue;
  						}
  
  						body.synchronizeFixtures();
  
  						// Invalidate all contact TOIs on this displaced body.
  						for (var ce = body.m_contactList; ce; ce = ce.next) {
  							ce.contact.m_toiFlag = false;
  							ce.contact.m_islandFlag = false;
  						}
  					}
  
  					// Commit fixture proxy movements to the broad-phase so that new contacts
  					// are created.
  					// Also, some contacts can be destroyed.
  					world.findNewContacts();
  
  					if (world.m_subStepping) {
  						world.m_stepComplete = false;
  						break;
  					}
  				}
  
  				if (_DEBUG)
  					for (var b = world.m_bodyList; b; b = b.m_next) {
  						var c = b.m_sweep.c;
  						var a = b.m_sweep.a;
  						var v = b.m_linearVelocity;
  						var w = b.m_angularVelocity;
  					}
  			};
  
  			/**
               * @param {TimeStep} subStep
               * @param toiA
               * @param toiB
               */
  			Solver.prototype.solveIslandTOI = function (subStep, toiA, toiB) {
  				var world = this.m_world;
  
  				// Initialize the body state.
  				for (var i = 0; i < this.m_bodies.length; ++i) {
  					var body = this.m_bodies[i];
  					body.c_position.c.set(body.m_sweep.c);
  					body.c_position.a = body.m_sweep.a;
  					body.c_velocity.v.set(body.m_linearVelocity);
  					body.c_velocity.w = body.m_angularVelocity;
  				}
  
  				for (var i = 0; i < this.m_contacts.length; ++i) {
  					var contact = this.m_contacts[i];
  					contact.initConstraint(subStep);
  				}
  
  				// Solve position constraints.
  				for (var i = 0; i < subStep.positionIterations; ++i) {
  					var minSeparation = 0.0;
  					for (var j = 0; j < this.m_contacts.length; ++j) {
  						var contact = this.m_contacts[j];
  						var separation = contact.solvePositionConstraintTOI(subStep, toiA, toiB);
  						minSeparation = Math.min(minSeparation, separation);
  					}
  					// We can't expect minSpeparation >= -Settings.linearSlop because we don't
  					// push the separation above -Settings.linearSlop.
  					var contactsOkay = minSeparation >= -1.5 * Settings.linearSlop;
  					if (contactsOkay) {
  						break;
  					}
  				}
  
  				if (false) {
  					var cache, output, input, indexB, indexA, bB, bA, fB, fA, c, i;
  				}
  
  				// Leap of faith to new safe state.
  				toiA.m_sweep.c0.set(toiA.c_position.c);
  				toiA.m_sweep.a0 = toiA.c_position.a;
  				toiB.m_sweep.c0.set(toiB.c_position.c);
  				toiB.m_sweep.a0 = toiB.c_position.a;
  
  				// No warm starting is needed for TOI events because warm
  				// starting impulses were applied in the discrete solver.
  				for (var i = 0; i < this.m_contacts.length; ++i) {
  					var contact = this.m_contacts[i];
  					contact.initVelocityConstraint(subStep);
  				}
  
  				// Solve velocity constraints.
  				for (var i = 0; i < subStep.velocityIterations; ++i) {
  					for (var j = 0; j < this.m_contacts.length; ++j) {
  						var contact = this.m_contacts[j];
  						contact.solveVelocityConstraint(subStep);
  					}
  				}
  
  				// Don't store the TOI contact forces for warm starting
  				// because they can be quite large.
  
  				var h = subStep.dt;
  
  				// Integrate positions
  				for (var i = 0; i < this.m_bodies.length; ++i) {
  					var body = this.m_bodies[i];
  
  					var c = Vec2.clone(body.c_position.c);
  					var a = body.c_position.a;
  					var v = Vec2.clone(body.c_velocity.v);
  					var w = body.c_velocity.w;
  
  					// Check for large velocities
  					var translation = Vec2.mul(h, v);
  					if (Vec2.dot(translation, translation) > Settings.maxTranslationSquared) {
  						var ratio = Settings.maxTranslation / translation.length();
  						v.mul(ratio);
  					}
  
  					var rotation = h * w;
  					if (rotation * rotation > Settings.maxRotationSquared) {
  						var ratio = Settings.maxRotation / Math.abs(rotation);
  						w *= ratio;
  					}
  
  					// Integrate
  					c.addMul(h, v);
  					a += h * w;
  
  					body.c_position.c = c;
  					body.c_position.a = a;
  					body.c_velocity.v = v;
  					body.c_velocity.w = w;
  
  					// Sync bodies
  					body.m_sweep.c = c;
  					body.m_sweep.a = a;
  					body.m_linearVelocity = v;
  					body.m_angularVelocity = w;
  					body.synchronizeTransform();
  				}
  
  				this.postSolveIsland();
  			};
  
  			/**
               * Contact impulses for reporting. Impulses are used instead of forces because
               * sub-step forces may approach infinity for rigid body collisions. These match
               * up one-to-one with the contact points in Manifold.
               */
  			function ContactImpulse () {
  				this.normalImpulses = [];
  				this.tangentImpulses = [];
  			}
  
  			Solver.prototype.postSolveIsland = function () {
  				// TODO: report contact.v_points instead of new object?
  				var impulse = new ContactImpulse();
  				for (var c = 0; c < this.m_contacts.length; ++c) {
  					var contact = this.m_contacts[c];
  					for (var p = 0; p < contact.v_points.length; ++p) {
  						impulse.normalImpulses.push(contact.v_points[p].normalImpulse);
  						impulse.tangentImpulses.push(contact.v_points[p].tangentImpulse);
  					}
  					this.m_world.postSolve(contact, impulse);
  				}
  			};
  
  			/***/
  		},
  		/* 44 */
  		/***/ function (module, exports, __webpack_require__) {
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports.now = function () {
  				return Date.now();
  			};
  
  			module.exports.diff = function (time) {
  				return Date.now() - time;
  			};
  
  			/***/
  		},
  		/* 45 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = BoxShape;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var PolygonShape = __webpack_require__(21);
  
  			BoxShape._super = PolygonShape;
  			BoxShape.prototype = create(BoxShape._super.prototype);
  
  			BoxShape.TYPE = 'polygon';
  
  			/**
               * A rectangle polygon which extend PolygonShape.
               */
  			function BoxShape (hx, hy, center, angle) {
  				if (!(this instanceof BoxShape)) {
  					return new BoxShape(hx, hy, center, angle);
  				}
  
  				BoxShape._super.call(this);
  
  				this._setAsBox(hx, hy, center, angle);
  			}
  
  			/***/
  		},
  		/* 46 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Vec2 = __webpack_require__(0);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  			var Contact = __webpack_require__(18);
  			var Manifold = __webpack_require__(19);
  			var CircleShape = __webpack_require__(23);
  
  			Contact.addType(CircleShape.TYPE, CircleShape.TYPE, CircleCircleContact);
  
  			function CircleCircleContact (manifold, xfA, fixtureA, indexA, xfB, fixtureB, indexB) {
  				_ASSERT && common.assert(fixtureA.getType() == CircleShape.TYPE);
  				_ASSERT && common.assert(fixtureB.getType() == CircleShape.TYPE);
  				CollideCircles(manifold, fixtureA.getShape(), xfA, fixtureB.getShape(), xfB);
  			}
  
  			function CollideCircles (manifold, circleA, xfA, circleB, xfB) {
  				manifold.pointCount = 0;
  
  				var pA = Transform.mulVec2(xfA, circleA.m_p);
  				var pB = Transform.mulVec2(xfB, circleB.m_p);
  
  				var distSqr = Vec2.distanceSquared(pB, pA);
  				var rA = circleA.m_radius;
  				var rB = circleB.m_radius;
  				var radius = rA + rB;
  				if (distSqr > radius * radius) {
  					return;
  				}
  
  				manifold.type = Manifold.e_circles;
  				manifold.localPoint.set(circleA.m_p);
  				manifold.localNormal.setZero();
  				manifold.pointCount = 1;
  				manifold.points[0].localPoint.set(circleB.m_p);
  
  				// manifold.points[0].id.key = 0;
  				manifold.points[0].id.cf.indexA = 0;
  				manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  				manifold.points[0].id.cf.indexB = 0;
  				manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  			}
  
  			exports.CollideCircles = CollideCircles;
  
  			/***/
  		},
  		/* 47 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Vec2 = __webpack_require__(0);
  			var Rot = __webpack_require__(3);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  			var Contact = __webpack_require__(18);
  			var Manifold = __webpack_require__(19);
  			var EdgeShape = __webpack_require__(24);
  			var ChainShape = __webpack_require__(28);
  			var CircleShape = __webpack_require__(23);
  
  			Contact.addType(EdgeShape.TYPE, CircleShape.TYPE, EdgeCircleContact);
  			Contact.addType(ChainShape.TYPE, CircleShape.TYPE, ChainCircleContact);
  
  			function EdgeCircleContact (manifold, xfA, fixtureA, indexA, xfB, fixtureB, indexB) {
  				_ASSERT && common.assert(fixtureA.getType() == EdgeShape.TYPE);
  				_ASSERT && common.assert(fixtureB.getType() == CircleShape.TYPE);
  
  				var shapeA = fixtureA.getShape();
  				var shapeB = fixtureB.getShape();
  
  				CollideEdgeCircle(manifold, shapeA, xfA, shapeB, xfB);
  			}
  
  			function ChainCircleContact (manifold, xfA, fixtureA, indexA, xfB, fixtureB, indexB) {
  				_ASSERT && common.assert(fixtureA.getType() == ChainShape.TYPE);
  				_ASSERT && common.assert(fixtureB.getType() == CircleShape.TYPE);
  
  				var chain = fixtureA.getShape();
  				var edge = new EdgeShape();
  				chain.getChildEdge(edge, indexA);
  
  				var shapeA = edge;
  				var shapeB = fixtureB.getShape();
  
  				CollideEdgeCircle(manifold, shapeA, xfA, shapeB, xfB);
  			}
  
  			// Compute contact points for edge versus circle.
  			// This accounts for edge connectivity.
  			function CollideEdgeCircle (manifold, edgeA, xfA, circleB, xfB) {
  				manifold.pointCount = 0;
  
  				// Compute circle in frame of edge
  				var Q = Transform.mulTVec2(xfA, Transform.mulVec2(xfB, circleB.m_p));
  
  				var A = edgeA.m_vertex1;
  				var B = edgeA.m_vertex2;
  				var e = Vec2.sub(B, A);
  
  				// Barycentric coordinates
  				var u = Vec2.dot(e, Vec2.sub(B, Q));
  				var v = Vec2.dot(e, Vec2.sub(Q, A));
  
  				var radius = edgeA.m_radius + circleB.m_radius;
  
  				// Region A
  				if (v <= 0.0) {
  					var P = Vec2.clone(A);
  					var d = Vec2.sub(Q, P);
  					var dd = Vec2.dot(d, d);
  					if (dd > radius * radius) {
  						return;
  					}
  
  					// Is there an edge connected to A?
  					if (edgeA.m_hasVertex0) {
  						var A1 = edgeA.m_vertex0;
  						var B1 = A;
  						var e1 = Vec2.sub(B1, A1);
  						var u1 = Vec2.dot(e1, Vec2.sub(B1, Q));
  
  						// Is the circle in Region AB of the previous edge?
  						if (u1 > 0.0) {
  							return;
  						}
  					}
  
  					manifold.type = Manifold.e_circles;
  					manifold.localNormal.setZero();
  					manifold.localPoint.set(P);
  					manifold.pointCount = 1;
  					manifold.points[0].localPoint.set(circleB.m_p);
  
  					// manifold.points[0].id.key = 0;
  					manifold.points[0].id.cf.indexA = 0;
  					manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  					manifold.points[0].id.cf.indexB = 0;
  					manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  					return;
  				}
  
  				// Region B
  				if (u <= 0.0) {
  					var P = Vec2.clone(B);
  					var d = Vec2.sub(Q, P);
  					var dd = Vec2.dot(d, d);
  					if (dd > radius * radius) {
  						return;
  					}
  
  					// Is there an edge connected to B?
  					if (edgeA.m_hasVertex3) {
  						var B2 = edgeA.m_vertex3;
  						var A2 = B;
  						var e2 = Vec2.sub(B2, A2);
  						var v2 = Vec2.dot(e2, Vec2.sub(Q, A2));
  
  						// Is the circle in Region AB of the next edge?
  						if (v2 > 0.0) {
  							return;
  						}
  					}
  
  					manifold.type = Manifold.e_circles;
  					manifold.localNormal.setZero();
  					manifold.localPoint.set(P);
  					manifold.pointCount = 1;
  					manifold.points[0].localPoint.set(circleB.m_p);
  
  					// manifold.points[0].id.key = 0;
  					manifold.points[0].id.cf.indexA = 1;
  					manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  					manifold.points[0].id.cf.indexB = 0;
  					manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  					return;
  				}
  
  				// Region AB
  				var den = Vec2.dot(e, e);
  				_ASSERT && common.assert(den > 0.0);
  				var P = Vec2.combine(u / den, A, v / den, B);
  				var d = Vec2.sub(Q, P);
  				var dd = Vec2.dot(d, d);
  				if (dd > radius * radius) {
  					return;
  				}
  
  				var n = Vec2.neo(-e.y, e.x);
  				if (Vec2.dot(n, Vec2.sub(Q, A)) < 0.0) {
  					n.set(-n.x, -n.y);
  				}
  				n.normalize();
  
  				manifold.type = Manifold.e_faceA;
  				manifold.localNormal = n;
  				manifold.localPoint.set(A);
  				manifold.pointCount = 1;
  				manifold.points[0].localPoint.set(circleB.m_p);
  
  				// manifold.points[0].id.key = 0;
  				manifold.points[0].id.cf.indexA = 0;
  				manifold.points[0].id.cf.typeA = Manifold.e_face;
  				manifold.points[0].id.cf.indexB = 0;
  				manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  			}
  
  			/***/
  		},
  		/* 48 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Rot = __webpack_require__(3);
  			var Vec2 = __webpack_require__(0);
  			var AABB = __webpack_require__(17);
  			var Settings = __webpack_require__(4);
  			var Manifold = __webpack_require__(19);
  			var Contact = __webpack_require__(18);
  			var Shape = __webpack_require__(16);
  			var PolygonShape = __webpack_require__(21);
  
  			module.exports = CollidePolygons;
  
  			Contact.addType(PolygonShape.TYPE, PolygonShape.TYPE, PolygonContact);
  
  			function PolygonContact (manifold, xfA, fixtureA, indexA, xfB, fixtureB, indexB) {
  				_ASSERT && common.assert(fixtureA.getType() == PolygonShape.TYPE);
  				_ASSERT && common.assert(fixtureB.getType() == PolygonShape.TYPE);
  				CollidePolygons(manifold, fixtureA.getShape(), xfA, fixtureB.getShape(), xfB);
  			}
  
  			/**
               * Find the max separation between poly1 and poly2 using edge normals from
               * poly1.
               */
  			function FindMaxSeparation (poly1, xf1, poly2, xf2) {
  				var count1 = poly1.m_count;
  				var count2 = poly2.m_count;
  				var n1s = poly1.m_normals;
  				var v1s = poly1.m_vertices;
  				var v2s = poly2.m_vertices;
  				var xf = Transform.mulTXf(xf2, xf1);
  
  				var bestIndex = 0;
  				var maxSeparation = -Infinity;
  				for (var i = 0; i < count1; ++i) {
  					// Get poly1 normal in frame2.
  					var n = Rot.mulVec2(xf.q, n1s[i]);
  					var v1 = Transform.mulVec2(xf, v1s[i]);
  
  					// Find deepest point for normal i.
  					var si = Infinity;
  					for (var j = 0; j < count2; ++j) {
  						var sij = Vec2.dot(n, v2s[j]) - Vec2.dot(n, v1);
  						if (sij < si) {
  							si = sij;
  						}
  					}
  
  					if (si > maxSeparation) {
  						maxSeparation = si;
  						bestIndex = i;
  					}
  				}
  
  				// used to keep last FindMaxSeparation call values
  				FindMaxSeparation._maxSeparation = maxSeparation;
  				FindMaxSeparation._bestIndex = bestIndex;
  			}
  
  			/**
               * @param {ClipVertex[2]} c
               * @param {int} edge1
               */
  			function FindIncidentEdge (c, poly1, xf1, edge1, poly2, xf2) {
  				var normals1 = poly1.m_normals;
  
  				var count2 = poly2.m_count;
  				var vertices2 = poly2.m_vertices;
  				var normals2 = poly2.m_normals;
  
  				_ASSERT && common.assert(edge1 >= 0 && edge1 < poly1.m_count);
  
  				// Get the normal of the reference edge in poly2's frame.
  				var normal1 = Rot.mulT(xf2.q, Rot.mulVec2(xf1.q, normals1[edge1]));
  
  				// Find the incident edge on poly2.
  				var index = 0;
  				var minDot = Infinity;
  				for (var i = 0; i < count2; ++i) {
  					var dot = Vec2.dot(normal1, normals2[i]);
  					if (dot < minDot) {
  						minDot = dot;
  						index = i;
  					}
  				}
  
  				// Build the clip vertices for the incident edge.
  				var i1 = index;
  				var i2 = i1 + 1 < count2 ? i1 + 1 : 0;
  
  				c[0].v = Transform.mulVec2(xf2, vertices2[i1]);
  				c[0].id.cf.indexA = edge1;
  				c[0].id.cf.indexB = i1;
  				c[0].id.cf.typeA = Manifold.e_face;
  				c[0].id.cf.typeB = Manifold.e_vertex;
  
  				c[1].v = Transform.mulVec2(xf2, vertices2[i2]);
  				c[1].id.cf.indexA = edge1;
  				c[1].id.cf.indexB = i2;
  				c[1].id.cf.typeA = Manifold.e_face;
  				c[1].id.cf.typeB = Manifold.e_vertex;
  			}
  
  			/**
               *
               * Find edge normal of max separation on A - return if separating axis is found<br>
               * Find edge normal of max separation on B - return if separation axis is found<br>
               * Choose reference edge as min(minA, minB)<br>
               * Find incident edge<br>
               * Clip
               *
               * The normal points from 1 to 2
               */
  			function CollidePolygons (manifold, polyA, xfA, polyB, xfB) {
  				manifold.pointCount = 0;
  				var totalRadius = polyA.m_radius + polyB.m_radius;
  
  				FindMaxSeparation(polyA, xfA, polyB, xfB);
  				var edgeA = FindMaxSeparation._bestIndex;
  				var separationA = FindMaxSeparation._maxSeparation;
  				if (separationA > totalRadius) return;
  
  				FindMaxSeparation(polyB, xfB, polyA, xfA);
  				var edgeB = FindMaxSeparation._bestIndex;
  				var separationB = FindMaxSeparation._maxSeparation;
  				if (separationB > totalRadius) return;
  
  				var poly1; // reference polygon
  				var poly2; // incident polygon
  				var xf1;
  				var xf2;
  				var edge1; // reference edge
  				var flip;
  				var k_tol = 0.1 * Settings.linearSlop;
  
  				if (separationB > separationA + k_tol) {
  					poly1 = polyB;
  					poly2 = polyA;
  					xf1 = xfB;
  					xf2 = xfA;
  					edge1 = edgeB;
  					manifold.type = Manifold.e_faceB;
  					flip = 1;
  				} else {
  					poly1 = polyA;
  					poly2 = polyB;
  					xf1 = xfA;
  					xf2 = xfB;
  					edge1 = edgeA;
  					manifold.type = Manifold.e_faceA;
  					flip = 0;
  				}
  
  				var incidentEdge = [new Manifold.clipVertex(), new Manifold.clipVertex()];
  				FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
  
  				var count1 = poly1.m_count;
  				var vertices1 = poly1.m_vertices;
  
  				var iv1 = edge1;
  				var iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0;
  
  				var v11 = vertices1[iv1];
  				var v12 = vertices1[iv2];
  
  				var localTangent = Vec2.sub(v12, v11);
  				localTangent.normalize();
  
  				var localNormal = Vec2.cross(localTangent, 1.0);
  				var planePoint = Vec2.combine(0.5, v11, 0.5, v12);
  
  				var tangent = Rot.mulVec2(xf1.q, localTangent);
  				var normal = Vec2.cross(tangent, 1.0);
  
  				v11 = Transform.mulVec2(xf1, v11);
  				v12 = Transform.mulVec2(xf1, v12);
  
  				// Face offset.
  				var frontOffset = Vec2.dot(normal, v11);
  
  				// Side offsets, extended by polytope skin thickness.
  				var sideOffset1 = -Vec2.dot(tangent, v11) + totalRadius;
  				var sideOffset2 = Vec2.dot(tangent, v12) + totalRadius;
  
  				// Clip incident edge against extruded edge1 side edges.
  				var clipPoints1 = [new Manifold.clipVertex(), new Manifold.clipVertex()];
  				var clipPoints2 = [new Manifold.clipVertex(), new Manifold.clipVertex()];
  				var np;
  
  				// Clip to box side 1
  				np = Manifold.clipSegmentToLine(clipPoints1, incidentEdge, Vec2.neg(tangent), sideOffset1, iv1);
  
  				if (np < 2) {
  					return;
  				}
  
  				// Clip to negative box side 1
  				np = Manifold.clipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2);
  
  				if (np < 2) {
  					return;
  				}
  
  				// Now clipPoints2 contains the clipped points.
  				manifold.localNormal = localNormal;
  				manifold.localPoint = planePoint;
  
  				var pointCount = 0;
  				for (var i = 0; i < clipPoints2.length; ++i) {
  					var separation = Vec2.dot(normal, clipPoints2[i].v) - frontOffset;
  
  					if (separation <= totalRadius) {
  						var cp = manifold.points[pointCount]; // ManifoldPoint
  						cp.localPoint.set(Transform.mulTVec2(xf2, clipPoints2[i].v));
  						cp.id = clipPoints2[i].id;
  						if (flip) {
  							// Swap features
  							var cf = cp.id.cf; // ContactFeature
  							var indexA = cf.indexA;
  							var indexB = cf.indexB;
  							var typeA = cf.typeA;
  							var typeB = cf.typeB;
  							cf.indexA = indexB;
  							cf.indexB = indexA;
  							cf.typeA = typeB;
  							cf.typeB = typeA;
  						}
  						++pointCount;
  					}
  				}
  
  				manifold.pointCount = pointCount;
  			}
  
  			/***/
  		},
  		/* 49 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Rot = __webpack_require__(3);
  			var Vec2 = __webpack_require__(0);
  			var AABB = __webpack_require__(17);
  			var Settings = __webpack_require__(4);
  			var Manifold = __webpack_require__(19);
  			var Contact = __webpack_require__(18);
  			var Shape = __webpack_require__(16);
  			var CircleShape = __webpack_require__(23);
  			var PolygonShape = __webpack_require__(21);
  
  			Contact.addType(PolygonShape.TYPE, CircleShape.TYPE, PolygonCircleContact);
  
  			function PolygonCircleContact (manifold, xfA, fixtureA, indexA, xfB, fixtureB, indexB) {
  				_ASSERT && common.assert(fixtureA.getType() == PolygonShape.TYPE);
  				_ASSERT && common.assert(fixtureB.getType() == CircleShape.TYPE);
  				CollidePolygonCircle(manifold, fixtureA.getShape(), xfA, fixtureB.getShape(), xfB);
  			}
  
  			function CollidePolygonCircle (manifold, polygonA, xfA, circleB, xfB) {
  				manifold.pointCount = 0;
  
  				// Compute circle position in the frame of the polygon.
  				var c = Transform.mulVec2(xfB, circleB.m_p);
  				var cLocal = Transform.mulTVec2(xfA, c);
  
  				// Find the min separating edge.
  				var normalIndex = 0;
  				var separation = -Infinity;
  				var radius = polygonA.m_radius + circleB.m_radius;
  				var vertexCount = polygonA.m_count;
  				var vertices = polygonA.m_vertices;
  				var normals = polygonA.m_normals;
  
  				for (var i = 0; i < vertexCount; ++i) {
  					var s = Vec2.dot(normals[i], Vec2.sub(cLocal, vertices[i]));
  
  					if (s > radius) {
  						// Early out.
  						return;
  					}
  
  					if (s > separation) {
  						separation = s;
  						normalIndex = i;
  					}
  				}
  
  				// Vertices that subtend the incident face.
  				var vertIndex1 = normalIndex;
  				var vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
  				var v1 = vertices[vertIndex1];
  				var v2 = vertices[vertIndex2];
  
  				// If the center is inside the polygon ...
  				if (separation < Math.EPSILON) {
  					manifold.pointCount = 1;
  					manifold.type = Manifold.e_faceA;
  					manifold.localNormal.set(normals[normalIndex]);
  					manifold.localPoint.setCombine(0.5, v1, 0.5, v2);
  					manifold.points[0].localPoint = circleB.m_p;
  
  					// manifold.points[0].id.key = 0;
  					manifold.points[0].id.cf.indexA = 0;
  					manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  					manifold.points[0].id.cf.indexB = 0;
  					manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  					return;
  				}
  
  				// Compute barycentric coordinates
  				var u1 = Vec2.dot(Vec2.sub(cLocal, v1), Vec2.sub(v2, v1));
  				var u2 = Vec2.dot(Vec2.sub(cLocal, v2), Vec2.sub(v1, v2));
  				if (u1 <= 0.0) {
  					if (Vec2.distanceSquared(cLocal, v1) > radius * radius) {
  						return;
  					}
  
  					manifold.pointCount = 1;
  					manifold.type = Manifold.e_faceA;
  					manifold.localNormal.setCombine(1, cLocal, -1, v1);
  					manifold.localNormal.normalize();
  					manifold.localPoint = v1;
  					manifold.points[0].localPoint.set(circleB.m_p);
  
  					// manifold.points[0].id.key = 0;
  					manifold.points[0].id.cf.indexA = 0;
  					manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  					manifold.points[0].id.cf.indexB = 0;
  					manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  				} else if (u2 <= 0.0) {
  					if (Vec2.distanceSquared(cLocal, v2) > radius * radius) {
  						return;
  					}
  
  					manifold.pointCount = 1;
  					manifold.type = Manifold.e_faceA;
  					manifold.localNormal.setCombine(1, cLocal, -1, v2);
  					manifold.localNormal.normalize();
  					manifold.localPoint.set(v2);
  					manifold.points[0].localPoint.set(circleB.m_p);
  
  					// manifold.points[0].id.key = 0;
  					manifold.points[0].id.cf.indexA = 0;
  					manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  					manifold.points[0].id.cf.indexB = 0;
  					manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  				} else {
  					var faceCenter = Vec2.mid(v1, v2);
  					var separation = Vec2.dot(cLocal, normals[vertIndex1]) - Vec2.dot(faceCenter, normals[vertIndex1]);
  					if (separation > radius) {
  						return;
  					}
  
  					manifold.pointCount = 1;
  					manifold.type = Manifold.e_faceA;
  					manifold.localNormal.set(normals[vertIndex1]);
  					manifold.localPoint.set(faceCenter);
  					manifold.points[0].localPoint.set(circleB.m_p);
  
  					// manifold.points[0].id.key = 0;
  					manifold.points[0].id.cf.indexA = 0;
  					manifold.points[0].id.cf.typeA = Manifold.e_vertex;
  					manifold.points[0].id.cf.indexB = 0;
  					manifold.points[0].id.cf.typeB = Manifold.e_vertex;
  				}
  			}
  
  			/***/
  		},
  		/* 50 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			var common = __webpack_require__(2);
  			var create = __webpack_require__(6);
  			var Math = __webpack_require__(1);
  			var Transform = __webpack_require__(5);
  			var Vec2 = __webpack_require__(0);
  			var Rot = __webpack_require__(3);
  			var Settings = __webpack_require__(4);
  			var Shape = __webpack_require__(16);
  			var Contact = __webpack_require__(18);
  			var Manifold = __webpack_require__(19);
  			var EdgeShape = __webpack_require__(24);
  			var ChainShape = __webpack_require__(28);
  			var PolygonShape = __webpack_require__(21);
  
  			Contact.addType(EdgeShape.TYPE, PolygonShape.TYPE, EdgePolygonContact);
  			Contact.addType(ChainShape.TYPE, PolygonShape.TYPE, ChainPolygonContact);
  
  			function EdgePolygonContact (manifold, xfA, fA, indexA, xfB, fB, indexB) {
  				_ASSERT && common.assert(fA.getType() == EdgeShape.TYPE);
  				_ASSERT && common.assert(fB.getType() == PolygonShape.TYPE);
  
  				CollideEdgePolygon(manifold, fA.getShape(), xfA, fB.getShape(), xfB);
  			}
  
  			function ChainPolygonContact (manifold, xfA, fA, indexA, xfB, fB, indexB) {
  				_ASSERT && common.assert(fA.getType() == ChainShape.TYPE);
  				_ASSERT && common.assert(fB.getType() == PolygonShape.TYPE);
  
  				var chain = fA.getShape();
  				var edge = new EdgeShape();
  				chain.getChildEdge(edge, indexA);
  
  				CollideEdgePolygon(manifold, edge, xfA, fB.getShape(), xfB);
  			}
  
  			// EPAxis Type
  			var e_unknown = -1;
  			var e_edgeA = 1;
  			var e_edgeB = 2;
  
  			// VertexType unused?
  			var e_isolated = 0;
  			var e_concave = 1;
  			var e_convex = 2;
  
  			// This structure is used to keep track of the best separating axis.
  			function EPAxis () {
  				this.type; // Type
  				this.index;
  				this.separation;
  			}
  
  			// This holds polygon B expressed in frame A.
  			function TempPolygon () {
  				this.vertices = []; // Vec2[Settings.maxPolygonVertices]
  				this.normals = []; // Vec2[Settings.maxPolygonVertices];
  				this.count = 0;
  			}
  
  			// Reference face used for clipping
  			function ReferenceFace () {
  				this.i1, this.i2; // int
  				this.v1, this.v2; // v
  				this.normal = Vec2.zero();
  				this.sideNormal1 = Vec2.zero();
  				this.sideOffset1; // float
  				this.sideNormal2 = Vec2.zero();
  				this.sideOffset2; // float
  			}
  
  			// reused
  			var edgeAxis = new EPAxis();
  			var polygonAxis = new EPAxis();
  			var polygonBA = new TempPolygon();
  			var rf = new ReferenceFace();
  
  			/**
               * This function collides and edge and a polygon, taking into account edge
               * adjacency.
               */
  			function CollideEdgePolygon (manifold, edgeA, xfA, polygonB, xfB) {
  				// Algorithm:
  				// 1. Classify v1 and v2
  				// 2. Classify polygon centroid as front or back
  				// 3. Flip normal if necessary
  				// 4. Initialize normal range to [-pi, pi] about face normal
  				// 5. Adjust normal range according to adjacent edges
  				// 6. Visit each separating axes, only accept axes within the range
  				// 7. Return if _any_ axis indicates separation
  				// 8. Clip
  
  				var m_type1, m_type2; // VertexType unused?
  
  				var xf = Transform.mulTXf(xfA, xfB);
  
  				var centroidB = Transform.mulVec2(xf, polygonB.m_centroid);
  
  				var v0 = edgeA.m_vertex0;
  				var v1 = edgeA.m_vertex1;
  				var v2 = edgeA.m_vertex2;
  				var v3 = edgeA.m_vertex3;
  
  				var hasVertex0 = edgeA.m_hasVertex0;
  				var hasVertex3 = edgeA.m_hasVertex3;
  
  				var edge1 = Vec2.sub(v2, v1);
  				edge1.normalize();
  				var normal1 = Vec2.neo(edge1.y, -edge1.x);
  				var offset1 = Vec2.dot(normal1, Vec2.sub(centroidB, v1));
  				var offset0 = 0.0;
  				var offset2 = 0.0;
  				var convex1 = false;
  				var convex2 = false;
  
  				// Is there a preceding edge?
  				if (hasVertex0) {
  					var edge0 = Vec2.sub(v1, v0);
  					edge0.normalize();
  					var normal0 = Vec2.neo(edge0.y, -edge0.x);
  					convex1 = Vec2.cross(edge0, edge1) >= 0.0;
  					offset0 = Vec2.dot(normal0, centroidB) - Vec2.dot(normal0, v0);
  				}
  
  				// Is there a following edge?
  				if (hasVertex3) {
  					var edge2 = Vec2.sub(v3, v2);
  					edge2.normalize();
  					var normal2 = Vec2.neo(edge2.y, -edge2.x);
  					convex2 = Vec2.cross(edge1, edge2) > 0.0;
  					offset2 = Vec2.dot(normal2, centroidB) - Vec2.dot(normal2, v2);
  				}
  
  				var front;
  				var normal = Vec2.zero();
  				var lowerLimit = Vec2.zero();
  				var upperLimit = Vec2.zero();
  
  				// Determine front or back collision. Determine collision normal limits.
  				if (hasVertex0 && hasVertex3) {
  					if (convex1 && convex2) {
  						front = offset0 >= 0.0 || offset1 >= 0.0 || offset2 >= 0.0;
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.set(normal0);
  							upperLimit.set(normal2);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.setMul(-1, normal1);
  							upperLimit.setMul(-1, normal1);
  						}
  					} else if (convex1) {
  						front = offset0 >= 0.0 || (offset1 >= 0.0 && offset2 >= 0.0);
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.set(normal0);
  							upperLimit.set(normal1);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.setMul(-1, normal2);
  							upperLimit.setMul(-1, normal1);
  						}
  					} else if (convex2) {
  						front = offset2 >= 0.0 || (offset0 >= 0.0 && offset1 >= 0.0);
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.set(normal1);
  							upperLimit.set(normal2);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.setMul(-1, normal1);
  							upperLimit.setMul(-1, normal0);
  						}
  					} else {
  						front = offset0 >= 0.0 && offset1 >= 0.0 && offset2 >= 0.0;
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.set(normal1);
  							upperLimit.set(normal1);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.setMul(-1, normal2);
  							upperLimit.setMul(-1, normal0);
  						}
  					}
  				} else if (hasVertex0) {
  					if (convex1) {
  						front = offset0 >= 0.0 || offset1 >= 0.0;
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.set(normal0);
  							upperLimit.setMul(-1, normal1);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.set(normal1);
  							upperLimit.setMul(-1, normal1);
  						}
  					} else {
  						front = offset0 >= 0.0 && offset1 >= 0.0;
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.set(normal1);
  							upperLimit.setMul(-1, normal1);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.set(normal1);
  							upperLimit.setMul(-1, normal0);
  						}
  					}
  				} else if (hasVertex3) {
  					if (convex2) {
  						front = offset1 >= 0.0 || offset2 >= 0.0;
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.setMul(-1, normal1);
  							upperLimit.set(normal2);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.setMul(-1, normal1);
  							upperLimit.set(normal1);
  						}
  					} else {
  						front = offset1 >= 0.0 && offset2 >= 0.0;
  						if (front) {
  							normal.set(normal1);
  							lowerLimit.setMul(-1, normal1);
  							upperLimit.set(normal1);
  						} else {
  							normal.setMul(-1, normal1);
  							lowerLimit.setMul(-1, normal2);
  							upperLimit.set(normal1);
  						}
  					}
  				} else {
  					front = offset1 >= 0.0;
  					if (front) {
  						normal.set(normal1);
  						lowerLimit.setMul(-1, normal1);
  						upperLimit.setMul(-1, normal1);
  					} else {
  						normal.setMul(-1, normal1);
  						lowerLimit.set(normal1);
  						upperLimit.set(normal1);
  					}
  				}
  
  				// Get polygonB in frameA
  				polygonBA.count = polygonB.m_count;
  				for (var i = 0; i < polygonB.m_count; ++i) {
  					polygonBA.vertices[i] = Transform.mulVec2(xf, polygonB.m_vertices[i]);
  					polygonBA.normals[i] = Rot.mulVec2(xf.q, polygonB.m_normals[i]);
  				}
  
  				var radius = 2.0 * Settings.polygonRadius;
  
  				manifold.pointCount = 0;
  
  				{
  					// ComputeEdgeSeparation
  					edgeAxis.type = e_edgeA;
  					edgeAxis.index = front ? 0 : 1;
  					edgeAxis.separation = Infinity;
  
  					for (var i = 0; i < polygonBA.count; ++i) {
  						var s = Vec2.dot(normal, Vec2.sub(polygonBA.vertices[i], v1));
  						if (s < edgeAxis.separation) {
  							edgeAxis.separation = s;
  						}
  					}
  				}
  
  				// If no valid normal can be found than this edge should not collide.
  				if (edgeAxis.type == e_unknown) {
  					return;
  				}
  
  				if (edgeAxis.separation > radius) {
  					return;
  				}
  
  				{
  					// ComputePolygonSeparation
  					polygonAxis.type = e_unknown;
  					polygonAxis.index = -1;
  					polygonAxis.separation = -Infinity;
  
  					var perp = Vec2.neo(-normal.y, normal.x);
  
  					for (var i = 0; i < polygonBA.count; ++i) {
  						var n = Vec2.neg(polygonBA.normals[i]);
  
  						var s1 = Vec2.dot(n, Vec2.sub(polygonBA.vertices[i], v1));
  						var s2 = Vec2.dot(n, Vec2.sub(polygonBA.vertices[i], v2));
  						var s = Math.min(s1, s2);
  
  						if (s > radius) {
  							// No collision
  							polygonAxis.type = e_edgeB;
  							polygonAxis.index = i;
  							polygonAxis.separation = s;
  							break;
  						}
  
  						// Adjacency
  						if (Vec2.dot(n, perp) >= 0.0) {
  							if (Vec2.dot(Vec2.sub(n, upperLimit), normal) < -Settings.angularSlop) {
  								continue;
  							}
  						} else {
  							if (Vec2.dot(Vec2.sub(n, lowerLimit), normal) < -Settings.angularSlop) {
  								continue;
  							}
  						}
  
  						if (s > polygonAxis.separation) {
  							polygonAxis.type = e_edgeB;
  							polygonAxis.index = i;
  							polygonAxis.separation = s;
  						}
  					}
  				}
  
  				if (polygonAxis.type != e_unknown && polygonAxis.separation > radius) {
  					return;
  				}
  
  				// Use hysteresis for jitter reduction.
  				var k_relativeTol = 0.98;
  				var k_absoluteTol = 0.001;
  
  				var primaryAxis;
  				if (polygonAxis.type == e_unknown) {
  					primaryAxis = edgeAxis;
  				} else if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) {
  					primaryAxis = polygonAxis;
  				} else {
  					primaryAxis = edgeAxis;
  				}
  
  				var ie = [new Manifold.clipVertex(), new Manifold.clipVertex()];
  
  				if (primaryAxis.type == e_edgeA) {
  					manifold.type = Manifold.e_faceA;
  
  					// Search for the polygon normal that is most anti-parallel to the edge
  					// normal.
  					var bestIndex = 0;
  					var bestValue = Vec2.dot(normal, polygonBA.normals[0]);
  					for (var i = 1; i < polygonBA.count; ++i) {
  						var value = Vec2.dot(normal, polygonBA.normals[i]);
  						if (value < bestValue) {
  							bestValue = value;
  							bestIndex = i;
  						}
  					}
  
  					var i1 = bestIndex;
  					var i2 = i1 + 1 < polygonBA.count ? i1 + 1 : 0;
  
  					ie[0].v = polygonBA.vertices[i1];
  					ie[0].id.cf.indexA = 0;
  					ie[0].id.cf.indexB = i1;
  					ie[0].id.cf.typeA = Manifold.e_face;
  					ie[0].id.cf.typeB = Manifold.e_vertex;
  
  					ie[1].v = polygonBA.vertices[i2];
  					ie[1].id.cf.indexA = 0;
  					ie[1].id.cf.indexB = i2;
  					ie[1].id.cf.typeA = Manifold.e_face;
  					ie[1].id.cf.typeB = Manifold.e_vertex;
  
  					if (front) {
  						rf.i1 = 0;
  						rf.i2 = 1;
  						rf.v1 = v1;
  						rf.v2 = v2;
  						rf.normal.set(normal1);
  					} else {
  						rf.i1 = 1;
  						rf.i2 = 0;
  						rf.v1 = v2;
  						rf.v2 = v1;
  						rf.normal.setMul(-1, normal1);
  					}
  				} else {
  					manifold.type = Manifold.e_faceB;
  
  					ie[0].v = v1;
  					ie[0].id.cf.indexA = 0;
  					ie[0].id.cf.indexB = primaryAxis.index;
  					ie[0].id.cf.typeA = Manifold.e_vertex;
  					ie[0].id.cf.typeB = Manifold.e_face;
  
  					ie[1].v = v2;
  					ie[1].id.cf.indexA = 0;
  					ie[1].id.cf.indexB = primaryAxis.index;
  					ie[1].id.cf.typeA = Manifold.e_vertex;
  					ie[1].id.cf.typeB = Manifold.e_face;
  
  					rf.i1 = primaryAxis.index;
  					rf.i2 = rf.i1 + 1 < polygonBA.count ? rf.i1 + 1 : 0;
  					rf.v1 = polygonBA.vertices[rf.i1];
  					rf.v2 = polygonBA.vertices[rf.i2];
  					rf.normal.set(polygonBA.normals[rf.i1]);
  				}
  
  				rf.sideNormal1.set(rf.normal.y, -rf.normal.x);
  				rf.sideNormal2.setMul(-1, rf.sideNormal1);
  				rf.sideOffset1 = Vec2.dot(rf.sideNormal1, rf.v1);
  				rf.sideOffset2 = Vec2.dot(rf.sideNormal2, rf.v2);
  
  				// Clip incident edge against extruded edge1 side edges.
  				var clipPoints1 = [new Manifold.clipVertex(), new Manifold.clipVertex()];
  				var clipPoints2 = [new Manifold.clipVertex(), new Manifold.clipVertex()];
  
  				var np;
  
  				// Clip to box side 1
  				np = Manifold.clipSegmentToLine(clipPoints1, ie, rf.sideNormal1, rf.sideOffset1, rf.i1);
  
  				if (np < Settings.maxManifoldPoints) {
  					return;
  				}
  
  				// Clip to negative box side 1
  				np = Manifold.clipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2, rf.sideOffset2, rf.i2);
  
  				if (np < Settings.maxManifoldPoints) {
  					return;
  				}
  
  				// Now clipPoints2 contains the clipped points.
  				if (primaryAxis.type == e_edgeA) {
  					manifold.localNormal = Vec2.clone(rf.normal);
  					manifold.localPoint = Vec2.clone(rf.v1);
  				} else {
  					manifold.localNormal = Vec2.clone(polygonB.m_normals[rf.i1]);
  					manifold.localPoint = Vec2.clone(polygonB.m_vertices[rf.i1]);
  				}
  
  				var pointCount = 0;
  				for (var i = 0; i < Settings.maxManifoldPoints; ++i) {
  					var separation = Vec2.dot(rf.normal, Vec2.sub(clipPoints2[i].v, rf.v1));
  
  					if (separation <= radius) {
  						var cp = manifold.points[pointCount]; // ManifoldPoint
  
  						if (primaryAxis.type == e_edgeA) {
  							cp.localPoint = Transform.mulT(xf, clipPoints2[i].v);
  							cp.id = clipPoints2[i].id;
  						} else {
  							cp.localPoint = clipPoints2[i].v;
  							cp.id.cf.typeA = clipPoints2[i].id.cf.typeB;
  							cp.id.cf.typeB = clipPoints2[i].id.cf.typeA;
  							cp.id.cf.indexA = clipPoints2[i].id.cf.indexB;
  							cp.id.cf.indexB = clipPoints2[i].id.cf.indexA;
  						}
  
  						++pointCount;
  					}
  				}
  
  				manifold.pointCount = pointCount;
  			}
  
  			/***/
  		},
  		/* 51 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = DistanceJoint;
  
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			DistanceJoint.TYPE = 'distance-joint';
  			Joint.TYPES[DistanceJoint.TYPE] = DistanceJoint;
  
  			DistanceJoint._super = Joint;
  			DistanceJoint.prototype = create(DistanceJoint._super.prototype);
  
  			/**
               * @typedef {Object} DistanceJointDef
               *
               * Distance joint definition. This requires defining an anchor point on both
               * bodies and the non-zero length of the distance joint. The definition uses
               * local anchor points so that the initial configuration can violate the
               * constraint slightly. This helps when saving and loading a game. Warning: Do
               * not use a zero or short length.
               *
               * @prop {float} frequencyHz The mass-spring-damper frequency in Hertz. A value
               *       of 0 disables softness.
               * @prop {float} dampingRatio The damping ratio. 0 = no damping, 1 = critical
               *       damping.
               *
               * @prop {Vec2} def.localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} def.localAnchorB The local anchor point relative to bodyB's origin.
               * @prop {number} def.length Distance length.
               */
  
  			var DEFAULTS = {
  				frequencyHz: 0.0,
  				dampingRatio: 0.0
  			};
  
  			/**
               * A distance joint constrains two points on two bodies to remain at a fixed
               * distance from each other. You can view this as a massless, rigid rod.
               *
               * @param {DistanceJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               * @param {Vec2} anchorA Anchor A in global coordination.
               * @param {Vec2} anchorB Anchor B in global coordination.
               */
  			function DistanceJoint (def, bodyA, bodyB, anchorA, anchorB) {
  				if (!(this instanceof DistanceJoint)) {
  					return new DistanceJoint(def, bodyA, bodyB, anchorA, anchorB);
  				}
  
  				// order of constructor arguments is changed in v0.2
  				if (bodyB && anchorA && 'm_type' in anchorA && 'x' in bodyB && 'y' in bodyB) {
  					var temp = bodyB;
  					bodyB = anchorA;
  					anchorA = temp;
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = DistanceJoint.TYPE;
  
  				// Solver shared
  				this.m_localAnchorA = Vec2.clone(anchorA ? bodyA.getLocalPoint(anchorA) : def.localAnchorA || Vec2.zero());
  				this.m_localAnchorB = Vec2.clone(anchorB ? bodyB.getLocalPoint(anchorB) : def.localAnchorB || Vec2.zero());
  				this.m_length = Math.isFinite(def.length) ? def.length : Vec2.distance(bodyA.getWorldPoint(this.m_localAnchorA), bodyB.getWorldPoint(this.m_localAnchorB));
  				this.m_frequencyHz = def.frequencyHz;
  				this.m_dampingRatio = def.dampingRatio;
  				this.m_impulse = 0.0;
  				this.m_gamma = 0.0;
  				this.m_bias = 0.0;
  
  				// Solver temp
  				this.m_u; // Vec2
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA;
  				this.m_invMassB;
  				this.m_invIA;
  				this.m_invIB;
  				this.m_mass;
  
  				// 1-D constrained system
  				// m (v2 - v1) = lambda
  				// v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass.
  				// x2 = x1 + h * v2
  
  				// 1-D mass-damper-spring system
  				// m (v2 - v1) + h * d * v2 + h * k *
  
  				// C = norm(p2 - p1) - L
  				// u = (p2 - p1) / norm(p2 - p1)
  				// Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
  				// J = [-u -cross(r1, u) u cross(r2, u)]
  				// K = J * invM * JT
  				// = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
  			}
  
  			DistanceJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					frequencyHz: this.m_frequencyHz,
  					dampingRatio: this.m_dampingRatio,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					length: this.m_length,
  
  					impulse: this.m_impulse,
  					gamma: this.m_gamma,
  					bias: this.m_bias
  				};
  			};
  
  			DistanceJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new DistanceJoint(data);
  				return joint;
  			};
  
  			/**
               * @internal
               */
  			DistanceJoint.prototype._setAnchors = function (def) {
  				if (def.anchorA) {
  					this.m_localAnchorA.set(this.m_bodyA.getLocalPoint(def.anchorA));
  				} else if (def.localAnchorA) {
  					this.m_localAnchorA.set(def.localAnchorA);
  				}
  
  				if (def.anchorB) {
  					this.m_localAnchorB.set(this.m_bodyB.getLocalPoint(def.anchorB));
  				} else if (def.localAnchorB) {
  					this.m_localAnchorB.set(def.localAnchorB);
  				}
  
  				if (def.length > 0) {
  					this.m_length = +def.length;
  				} else if (def.length < 0) {
  					// don't change length
  				} else if (def.anchorA || def.anchorA || def.anchorA || def.anchorA) {
  					this.m_length = Vec2.distance(this.m_bodyA.getWorldPoint(this.m_localAnchorA), this.m_bodyB.getWorldPoint(this.m_localAnchorB));
  				}
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			DistanceJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			DistanceJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * Set/get the natural length. Manipulating the length can lead to non-physical
               * behavior when the frequency is zero.
               */
  			DistanceJoint.prototype.setLength = function (length) {
  				this.m_length = length;
  			};
  
  			DistanceJoint.prototype.getLength = function () {
  				return this.m_length;
  			};
  
  			DistanceJoint.prototype.setFrequency = function (hz) {
  				this.m_frequencyHz = hz;
  			};
  
  			DistanceJoint.prototype.getFrequency = function () {
  				return this.m_frequencyHz;
  			};
  
  			DistanceJoint.prototype.setDampingRatio = function (ratio) {
  				this.m_dampingRatio = ratio;
  			};
  
  			DistanceJoint.prototype.getDampingRatio = function () {
  				return this.m_dampingRatio;
  			};
  
  			DistanceJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			DistanceJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			DistanceJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(this.m_impulse, this.m_u).mul(inv_dt);
  			};
  
  			DistanceJoint.prototype.getReactionTorque = function (inv_dt) {
  				return 0.0;
  			};
  
  			DistanceJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				this.m_rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				this.m_rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  				this.m_u = Vec2.sub(Vec2.add(cB, this.m_rB), Vec2.add(cA, this.m_rA));
  
  				// Handle singularity.
  				var length = this.m_u.length();
  				if (length > Settings.linearSlop) {
  					this.m_u.mul(1.0 / length);
  				} else {
  					this.m_u.set(0.0, 0.0);
  				}
  
  				var crAu = Vec2.cross(this.m_rA, this.m_u);
  				var crBu = Vec2.cross(this.m_rB, this.m_u);
  				var invMass = this.m_invMassA + this.m_invIA * crAu * crAu + this.m_invMassB + this.m_invIB * crBu * crBu;
  
  				// Compute the effective mass matrix.
  				this.m_mass = invMass != 0.0 ? 1.0 / invMass : 0.0;
  
  				if (this.m_frequencyHz > 0.0) {
  					var C = length - this.m_length;
  
  					// Frequency
  					var omega = 2.0 * Math.PI * this.m_frequencyHz;
  
  					// Damping coefficient
  					var d = 2.0 * this.m_mass * this.m_dampingRatio * omega;
  
  					// Spring stiffness
  					var k = this.m_mass * omega * omega;
  
  					// magic formulas
  					var h = step.dt;
  					this.m_gamma = h * (d + h * k);
  					this.m_gamma = this.m_gamma != 0.0 ? 1.0 / this.m_gamma : 0.0;
  					this.m_bias = C * h * k * this.m_gamma;
  
  					invMass += this.m_gamma;
  					this.m_mass = invMass != 0.0 ? 1.0 / invMass : 0.0;
  				} else {
  					this.m_gamma = 0.0;
  					this.m_bias = 0.0;
  				}
  
  				if (step.warmStarting) {
  					// Scale the impulse to support a variable time step.
  					this.m_impulse *= step.dtRatio;
  
  					var P = Vec2.mul(this.m_impulse, this.m_u);
  
  					vA.subMul(this.m_invMassA, P);
  					wA -= this.m_invIA * Vec2.cross(this.m_rA, P);
  
  					vB.addMul(this.m_invMassB, P);
  					wB += this.m_invIB * Vec2.cross(this.m_rB, P);
  				} else {
  					this.m_impulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			DistanceJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				// Cdot = dot(u, v + cross(w, r))
  				var vpA = Vec2.add(vA, Vec2.cross(wA, this.m_rA));
  				var vpB = Vec2.add(vB, Vec2.cross(wB, this.m_rB));
  				var Cdot = Vec2.dot(this.m_u, vpB) - Vec2.dot(this.m_u, vpA);
  
  				var impulse = -this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse);
  				this.m_impulse += impulse;
  
  				var P = Vec2.mul(impulse, this.m_u);
  				vA.subMul(this.m_invMassA, P);
  				wA -= this.m_invIA * Vec2.cross(this.m_rA, P);
  				vB.addMul(this.m_invMassB, P);
  				wB += this.m_invIB * Vec2.cross(this.m_rB, P);
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			DistanceJoint.prototype.solvePositionConstraints = function (step) {
  				if (this.m_frequencyHz > 0.0) {
  					// There is no position correction for soft distance constraints.
  					return true;
  				}
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var rA = Rot.mulSub(qA, this.m_localAnchorA, this.m_localCenterA);
  				var rB = Rot.mulSub(qB, this.m_localAnchorB, this.m_localCenterB);
  				var u = Vec2.sub(Vec2.add(cB, rB), Vec2.add(cA, rA));
  
  				var length = u.normalize();
  				var C = length - this.m_length;
  				C = Math.clamp(C, -Settings.maxLinearCorrection, Settings.maxLinearCorrection);
  
  				var impulse = -this.m_mass * C;
  				var P = Vec2.mul(impulse, u);
  
  				cA.subMul(this.m_invMassA, P);
  				aA -= this.m_invIA * Vec2.cross(rA, P);
  				cB.addMul(this.m_invMassB, P);
  				aB += this.m_invIB * Vec2.cross(rB, P);
  
  				this.m_bodyA.c_position.c.set(cA);
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c.set(cB);
  				this.m_bodyB.c_position.a = aB;
  
  				return Math.abs(C) < Settings.linearSlop;
  			};
  
  			/***/
  		},
  		/* 52 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = FrictionJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			FrictionJoint.TYPE = 'friction-joint';
  			Joint.TYPES[FrictionJoint.TYPE] = FrictionJoint;
  
  			FrictionJoint._super = Joint;
  			FrictionJoint.prototype = create(FrictionJoint._super.prototype);
  
  			/**
               * @typedef {Object} FrictionJointDef
               *
               * Friction joint definition.
               *
               * @prop {float} maxForce The maximum friction force in N.
               * @prop {float} maxTorque The maximum friction torque in N-m.
               *
               * @prop {Vec2} localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} localAnchorB The local anchor point relative to bodyB's origin.
               */
  
  			var DEFAULTS = {
  				maxForce: 0.0,
  				maxTorque: 0.0
  			};
  
  			/**
               * Friction joint. This is used for top-down friction. It provides 2D
               * translational friction and angular friction.
               *
               * @param {FrictionJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               * @param {Vec2} anchor Anchor in global coordination.
               */
  			function FrictionJoint (def, bodyA, bodyB, anchor) {
  				if (!(this instanceof FrictionJoint)) {
  					return new FrictionJoint(def, bodyA, bodyB, anchor);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = FrictionJoint.TYPE;
  
  				this.m_localAnchorA = anchor ? bodyA.getLocalPoint(anchor) : def.localAnchorA || Vec2.zero();
  				this.m_localAnchorB = anchor ? bodyB.getLocalPoint(anchor) : def.localAnchorB || Vec2.zero();
  
  				// Solver shared
  				this.m_linearImpulse = Vec2.zero();
  				this.m_angularImpulse = 0.0;
  				this.m_maxForce = def.maxForce;
  				this.m_maxTorque = def.maxTorque;
  
  				// Solver temp
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				this.m_linearMass; // Mat22
  				this.m_angularMass; // float
  
  				// Point-to-point constraint
  				// Cdot = v2 - v1
  				// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
  				// J = [-I -r1_skew I r2_skew ]
  				// Identity used:
  				// w k % (rx i + ry j) = w * (-ry i + rx j)
  
  				// Angle constraint
  				// Cdot = w2 - w1
  				// J = [0 0 -1 0 0 1]
  				// K = invI1 + invI2
  			}
  
  			FrictionJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					maxForce: this.m_maxForce,
  					maxTorque: this.m_maxTorque,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB
  				};
  			};
  
  			FrictionJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new FrictionJoint(data);
  				return joint;
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			FrictionJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			FrictionJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * Set the maximum friction force in N.
               */
  			FrictionJoint.prototype.setMaxForce = function (force) {
  				_ASSERT && common.assert(Math.isFinite(force) && force >= 0.0);
  				this.m_maxForce = force;
  			};
  
  			/**
               * Get the maximum friction force in N.
               */
  			FrictionJoint.prototype.getMaxForce = function () {
  				return this.m_maxForce;
  			};
  
  			/**
               * Set the maximum friction torque in N*m.
               */
  			FrictionJoint.prototype.setMaxTorque = function (torque) {
  				_ASSERT && common.assert(Math.isFinite(torque) && torque >= 0.0);
  				this.m_maxTorque = torque;
  			};
  
  			/**
               * Get the maximum friction torque in N*m.
               */
  			FrictionJoint.prototype.getMaxTorque = function () {
  				return this.m_maxTorque;
  			};
  
  			FrictionJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			FrictionJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			FrictionJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(inv_dt, this.m_linearImpulse);
  			};
  
  			FrictionJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * this.m_angularImpulse;
  			};
  
  			FrictionJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				// Compute the effective mass matrix.
  				this.m_rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				this.m_rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				// J = [-I -r1_skew I r2_skew]
  				// [ 0 -1 0 1]
  				// r_skew = [-ry; rx]
  
  				// Matlab
  				// K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
  				// [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
  				// [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var K = new Mat22();
  				K.ex.x = mA + mB + iA * this.m_rA.y * this.m_rA.y + iB * this.m_rB.y * this.m_rB.y;
  				K.ex.y = -iA * this.m_rA.x * this.m_rA.y - iB * this.m_rB.x * this.m_rB.y;
  				K.ey.x = K.ex.y;
  				K.ey.y = mA + mB + iA * this.m_rA.x * this.m_rA.x + iB * this.m_rB.x * this.m_rB.x;
  
  				this.m_linearMass = K.getInverse();
  
  				this.m_angularMass = iA + iB;
  				if (this.m_angularMass > 0.0) {
  					this.m_angularMass = 1.0 / this.m_angularMass;
  				}
  
  				if (step.warmStarting) {
  					// Scale impulses to support a variable time step.
  					this.m_linearImpulse.mul(step.dtRatio);
  					this.m_angularImpulse *= step.dtRatio;
  
  					var P = Vec2.neo(this.m_linearImpulse.x, this.m_linearImpulse.y);
  
  					vA.subMul(mA, P);
  					wA -= iA * (Vec2.cross(this.m_rA, P) + this.m_angularImpulse);
  
  					vB.addMul(mB, P);
  					wB += iB * (Vec2.cross(this.m_rB, P) + this.m_angularImpulse);
  				} else {
  					this.m_linearImpulse.setZero();
  					this.m_angularImpulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			FrictionJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var h = step.dt; // float
  
  				// Solve angular friction
  				{
  					var Cdot = wB - wA; // float
  					var impulse = -this.m_angularMass * Cdot; // float
  
  					var oldImpulse = this.m_angularImpulse; // float
  					var maxImpulse = h * this.m_maxTorque; // float
  					this.m_angularImpulse = Math.clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse);
  					impulse = this.m_angularImpulse - oldImpulse;
  
  					wA -= iA * impulse;
  					wB += iB * impulse;
  				}
  
  				// Solve linear friction
  				{
  					var Cdot = Vec2.sub(Vec2.add(vB, Vec2.cross(wB, this.m_rB)), Vec2.add(vA, Vec2.cross(wA, this.m_rA))); // Vec2
  
  					var impulse = Vec2.neg(Mat22.mulVec2(this.m_linearMass, Cdot)); // Vec2
  					var oldImpulse = this.m_linearImpulse; // Vec2
  					this.m_linearImpulse.add(impulse);
  
  					var maxImpulse = h * this.m_maxForce; // float
  
  					if (this.m_linearImpulse.lengthSquared() > maxImpulse * maxImpulse) {
  						this.m_linearImpulse.normalize();
  						this.m_linearImpulse.mul(maxImpulse);
  					}
  
  					impulse = Vec2.sub(this.m_linearImpulse, oldImpulse);
  
  					vA.subMul(mA, impulse);
  					wA -= iA * Vec2.cross(this.m_rA, impulse);
  
  					vB.addMul(mB, impulse);
  					wB += iB * Vec2.cross(this.m_rB, impulse);
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			FrictionJoint.prototype.solvePositionConstraints = function (step) {
  				return true;
  			};
  
  			/***/
  		},
  		/* 53 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = GearJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			var RevoluteJoint = __webpack_require__(34);
  			var PrismaticJoint = __webpack_require__(35);
  
  			GearJoint.TYPE = 'gear-joint';
  			Joint.TYPES[GearJoint.TYPE] = GearJoint;
  
  			GearJoint._super = Joint;
  			GearJoint.prototype = create(GearJoint._super.prototype);
  
  			/**
               * @typedef {Object} GearJointDef
               *
               * Gear joint definition.
               *
               * @prop {float} ratio The gear ratio. See GearJoint for explanation.
               *
               * @prop {RevoluteJoint|PrismaticJoint} joint1 The first revolute/prismatic
               *          joint attached to the gear joint.
               * @prop {PrismaticJoint|RevoluteJoint} joint2 The second prismatic/revolute
               *          joint attached to the gear joint.
               */
  
  			var DEFAULTS = {
  				ratio: 1.0
  			};
  
  			/**
               * A gear joint is used to connect two joints together. Either joint can be a
               * revolute or prismatic joint. You specify a gear ratio to bind the motions
               * together: coordinate1 + ratio * coordinate2 = constant
               *
               * The ratio can be negative or positive. If one joint is a revolute joint and
               * the other joint is a prismatic joint, then the ratio will have units of
               * length or units of 1/length. Warning: You have to manually destroy the gear
               * joint if joint1 or joint2 is destroyed.
               *
               * This definition requires two existing revolute or prismatic joints (any
               * combination will work).
               *
               * @param {GearJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function GearJoint (def, bodyA, bodyB, joint1, joint2, ratio) {
  				if (!(this instanceof GearJoint)) {
  					return new GearJoint(def, bodyA, bodyB, joint1, joint2, ratio);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = GearJoint.TYPE;
  
  				_ASSERT && common.assert(joint1.m_type === RevoluteJoint.TYPE || joint1.m_type === PrismaticJoint.TYPE);
  				_ASSERT && common.assert(joint2.m_type === RevoluteJoint.TYPE || joint2.m_type === PrismaticJoint.TYPE);
  
  				this.m_joint1 = joint1 || def.joint1;
  				this.m_joint2 = joint2 || def.joint2;
  				this.m_ratio = Math.isFinite(ratio) ? ratio : def.ratio;
  
  				this.m_type1 = this.m_joint1.getType();
  				this.m_type2 = this.m_joint2.getType();
  
  				// joint1 connects body A to body C
  				// joint2 connects body B to body D
  
  				var coordinateA, coordinateB; // float
  
  				// TODO_ERIN there might be some problem with the joint edges in Joint.
  
  				this.m_bodyC = this.m_joint1.getBodyA();
  				this.m_bodyA = this.m_joint1.getBodyB();
  
  				// Get geometry of joint1
  				var xfA = this.m_bodyA.m_xf;
  				var aA = this.m_bodyA.m_sweep.a;
  				var xfC = this.m_bodyC.m_xf;
  				var aC = this.m_bodyC.m_sweep.a;
  
  				if (this.m_type1 === RevoluteJoint.TYPE) {
  					var revolute = this.m_joint1; // RevoluteJoint
  					this.m_localAnchorC = revolute.m_localAnchorA;
  					this.m_localAnchorA = revolute.m_localAnchorB;
  					this.m_referenceAngleA = revolute.m_referenceAngle;
  					this.m_localAxisC = Vec2.zero();
  
  					coordinateA = aA - aC - this.m_referenceAngleA;
  				} else {
  					var prismatic = this.m_joint1; // PrismaticJoint
  					this.m_localAnchorC = prismatic.m_localAnchorA;
  					this.m_localAnchorA = prismatic.m_localAnchorB;
  					this.m_referenceAngleA = prismatic.m_referenceAngle;
  					this.m_localAxisC = prismatic.m_localXAxisA;
  
  					var pC = this.m_localAnchorC;
  					var pA = Rot.mulTVec2(xfC.q, Vec2.add(Rot.mul(xfA.q, this.m_localAnchorA), Vec2.sub(xfA.p, xfC.p)));
  					coordinateA = Vec2.dot(pA, this.m_localAxisC) - Vec2.dot(pC, this.m_localAxisC);
  				}
  
  				this.m_bodyD = this.m_joint2.getBodyA();
  				this.m_bodyB = this.m_joint2.getBodyB();
  
  				// Get geometry of joint2
  				var xfB = this.m_bodyB.m_xf;
  				var aB = this.m_bodyB.m_sweep.a;
  				var xfD = this.m_bodyD.m_xf;
  				var aD = this.m_bodyD.m_sweep.a;
  
  				if (this.m_type2 === RevoluteJoint.TYPE) {
  					var revolute = this.m_joint2; // RevoluteJoint
  					this.m_localAnchorD = revolute.m_localAnchorA;
  					this.m_localAnchorB = revolute.m_localAnchorB;
  					this.m_referenceAngleB = revolute.m_referenceAngle;
  					this.m_localAxisD = Vec2.zero();
  
  					coordinateB = aB - aD - this.m_referenceAngleB;
  				} else {
  					var prismatic = this.m_joint2; // PrismaticJoint
  					this.m_localAnchorD = prismatic.m_localAnchorA;
  					this.m_localAnchorB = prismatic.m_localAnchorB;
  					this.m_referenceAngleB = prismatic.m_referenceAngle;
  					this.m_localAxisD = prismatic.m_localXAxisA;
  
  					var pD = this.m_localAnchorD;
  					var pB = Rot.mulTVec2(xfD.q, Vec2.add(Rot.mul(xfB.q, this.m_localAnchorB), Vec2.sub(xfB.p, xfD.p)));
  					coordinateB = Vec2.dot(pB, this.m_localAxisD) - Vec2.dot(pD, this.m_localAxisD);
  				}
  
  				this.m_constant = coordinateA + this.m_ratio * coordinateB;
  
  				this.m_impulse = 0.0;
  
  				// Solver temp
  				this.m_lcA, this.m_lcB, this.m_lcC, this.m_lcD; // Vec2
  				this.m_mA, this.m_mB, this.m_mC, this.m_mD; // float
  				this.m_iA, this.m_iB, this.m_iC, this.m_iD; // float
  				this.m_JvAC, this.m_JvBD; // Vec2
  				this.m_JwA, this.m_JwB, this.m_JwC, this.m_JwD; // float
  				this.m_mass; // float
  
  				// Gear Joint:
  				// C0 = (coordinate1 + ratio * coordinate2)_initial
  				// C = (coordinate1 + ratio * coordinate2) - C0 = 0
  				// J = [J1 ratio * J2]
  				// K = J * invM * JT
  				// = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T
  				//
  				// Revolute:
  				// coordinate = rotation
  				// Cdot = angularVelocity
  				// J = [0 0 1]
  				// K = J * invM * JT = invI
  				//
  				// Prismatic:
  				// coordinate = dot(p - pg, ug)
  				// Cdot = dot(v + cross(w, r), ug)
  				// J = [ug cross(r, ug)]
  				// K = J * invM * JT = invMass + invI * cross(r, ug)^2
  			}
  
  			GearJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					joint1: this.m_joint1,
  					joint2: this.m_joint2,
  					ratio: this.m_ratio,
  
  					_constant: this.m_constant
  				};
  			};
  
  			GearJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				data.joint1 = restore(Joint, data.joint1, world);
  				data.joint2 = restore(Joint, data.joint2, world);
  				var joint = new GearJoint(data);
  				if (data._constant) joint.m_constant = data._constant;
  				return joint;
  			};
  
  			/**
               * Get the first joint.
               */
  			GearJoint.prototype.getJoint1 = function () {
  				return this.m_joint1;
  			};
  
  			/**
               * Get the second joint.
               */
  			GearJoint.prototype.getJoint2 = function () {
  				return this.m_joint2;
  			};
  
  			/**
               * Set/Get the gear ratio.
               */
  			GearJoint.prototype.setRatio = function (ratio) {
  				_ASSERT && common.assert(Math.isFinite(ratio));
  				this.m_ratio = ratio;
  			};
  
  			GearJoint.prototype.getRatio = function () {
  				return this.m_ratio;
  			};
  
  			GearJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			GearJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			GearJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(this.m_impulse, this.m_JvAC).mul(inv_dt);
  			};
  
  			GearJoint.prototype.getReactionTorque = function (inv_dt) {
  				var L = this.m_impulse * this.m_JwA; // float
  				return inv_dt * L;
  			};
  
  			GearJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_lcA = this.m_bodyA.m_sweep.localCenter;
  				this.m_lcB = this.m_bodyB.m_sweep.localCenter;
  				this.m_lcC = this.m_bodyC.m_sweep.localCenter;
  				this.m_lcD = this.m_bodyD.m_sweep.localCenter;
  				this.m_mA = this.m_bodyA.m_invMass;
  				this.m_mB = this.m_bodyB.m_invMass;
  				this.m_mC = this.m_bodyC.m_invMass;
  				this.m_mD = this.m_bodyD.m_invMass;
  				this.m_iA = this.m_bodyA.m_invI;
  				this.m_iB = this.m_bodyB.m_invI;
  				this.m_iC = this.m_bodyC.m_invI;
  				this.m_iD = this.m_bodyD.m_invI;
  
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var aC = this.m_bodyC.c_position.a;
  				var vC = this.m_bodyC.c_velocity.v;
  				var wC = this.m_bodyC.c_velocity.w;
  
  				var aD = this.m_bodyD.c_position.a;
  				var vD = this.m_bodyD.c_velocity.v;
  				var wD = this.m_bodyD.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  				var qC = Rot.neo(aC);
  				var qD = Rot.neo(aD);
  
  				this.m_mass = 0.0;
  
  				if (this.m_type1 == RevoluteJoint.TYPE) {
  					this.m_JvAC = Vec2.zero();
  					this.m_JwA = 1.0;
  					this.m_JwC = 1.0;
  					this.m_mass += this.m_iA + this.m_iC;
  				} else {
  					var u = Rot.mulVec2(qC, this.m_localAxisC); // Vec2
  					var rC = Rot.mulSub(qC, this.m_localAnchorC, this.m_lcC); // Vec2
  					var rA = Rot.mulSub(qA, this.m_localAnchorA, this.m_lcA); // Vec2
  					this.m_JvAC = u;
  					this.m_JwC = Vec2.cross(rC, u);
  					this.m_JwA = Vec2.cross(rA, u);
  					this.m_mass += this.m_mC + this.m_mA + this.m_iC * this.m_JwC * this.m_JwC + this.m_iA * this.m_JwA * this.m_JwA;
  				}
  
  				if (this.m_type2 == RevoluteJoint.TYPE) {
  					this.m_JvBD = Vec2.zero();
  					this.m_JwB = this.m_ratio;
  					this.m_JwD = this.m_ratio;
  					this.m_mass += this.m_ratio * this.m_ratio * (this.m_iB + this.m_iD);
  				} else {
  					var u = Rot.mulVec2(qD, this.m_localAxisD); // Vec2
  					var rD = Rot.mulSub(qD, this.m_localAnchorD, this.m_lcD); // Vec2
  					var rB = Rot.mulSub(qB, this.m_localAnchorB, this.m_lcB); // Vec2
  					this.m_JvBD = Vec2.mul(this.m_ratio, u);
  					this.m_JwD = this.m_ratio * Vec2.cross(rD, u);
  					this.m_JwB = this.m_ratio * Vec2.cross(rB, u);
  					this.m_mass += this.m_ratio * this.m_ratio * (this.m_mD + this.m_mB) + this.m_iD * this.m_JwD * this.m_JwD + this.m_iB * this.m_JwB * this.m_JwB;
  				}
  
  				// Compute effective mass.
  				this.m_mass = this.m_mass > 0.0 ? 1.0 / this.m_mass : 0.0;
  
  				if (step.warmStarting) {
  					vA.addMul(this.m_mA * this.m_impulse, this.m_JvAC);
  					wA += this.m_iA * this.m_impulse * this.m_JwA;
  
  					vB.addMul(this.m_mB * this.m_impulse, this.m_JvBD);
  					wB += this.m_iB * this.m_impulse * this.m_JwB;
  
  					vC.subMul(this.m_mC * this.m_impulse, this.m_JvAC);
  					wC -= this.m_iC * this.m_impulse * this.m_JwC;
  
  					vD.subMul(this.m_mD * this.m_impulse, this.m_JvBD);
  					wD -= this.m_iD * this.m_impulse * this.m_JwD;
  				} else {
  					this.m_impulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  				this.m_bodyC.c_velocity.v.set(vC);
  				this.m_bodyC.c_velocity.w = wC;
  				this.m_bodyD.c_velocity.v.set(vD);
  				this.m_bodyD.c_velocity.w = wD;
  			};
  
  			GearJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  				var vC = this.m_bodyC.c_velocity.v;
  				var wC = this.m_bodyC.c_velocity.w;
  				var vD = this.m_bodyD.c_velocity.v;
  				var wD = this.m_bodyD.c_velocity.w;
  
  				var Cdot = Vec2.dot(this.m_JvAC, vA) - Vec2.dot(this.m_JvAC, vC) + Vec2.dot(this.m_JvBD, vB) - Vec2.dot(this.m_JvBD, vD); // float
  				Cdot += this.m_JwA * wA - this.m_JwC * wC + (this.m_JwB * wB - this.m_JwD * wD);
  
  				var impulse = -this.m_mass * Cdot; // float
  				this.m_impulse += impulse;
  
  				vA.addMul(this.m_mA * impulse, this.m_JvAC);
  				wA += this.m_iA * impulse * this.m_JwA;
  				vB.addMul(this.m_mB * impulse, this.m_JvBD);
  				wB += this.m_iB * impulse * this.m_JwB;
  				vC.subMul(this.m_mC * impulse, this.m_JvAC);
  				wC -= this.m_iC * impulse * this.m_JwC;
  				vD.subMul(this.m_mD * impulse, this.m_JvBD);
  				wD -= this.m_iD * impulse * this.m_JwD;
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  				this.m_bodyC.c_velocity.v.set(vC);
  				this.m_bodyC.c_velocity.w = wC;
  				this.m_bodyD.c_velocity.v.set(vD);
  				this.m_bodyD.c_velocity.w = wD;
  			};
  
  			GearJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var cC = this.m_bodyC.c_position.c;
  				var aC = this.m_bodyC.c_position.a;
  				var cD = this.m_bodyD.c_position.c;
  				var aD = this.m_bodyD.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  				var qC = Rot.neo(aC);
  				var qD = Rot.neo(aD);
  
  				var linearError = 0.0; // float
  
  				var coordinateA, coordinateB; // float
  
  				var JvAC, JvBD; // Vec2
  				var JwA, JwB, JwC, JwD; // float
  				var mass = 0.0; // float
  
  				if (this.m_type1 == RevoluteJoint.TYPE) {
  					JvAC = Vec2.zero();
  					JwA = 1.0;
  					JwC = 1.0;
  					mass += this.m_iA + this.m_iC;
  
  					coordinateA = aA - aC - this.m_referenceAngleA;
  				} else {
  					var u = Rot.mulVec2(qC, this.m_localAxisC); // Vec2
  					var rC = Rot.mulSub(qC, this.m_localAnchorC, this.m_lcC); // Vec2
  					var rA = Rot.mulSub(qA, this.m_localAnchorA, this.m_lcA); // Vec2
  					JvAC = u;
  					JwC = Vec2.cross(rC, u);
  					JwA = Vec2.cross(rA, u);
  					mass += this.m_mC + this.m_mA + this.m_iC * JwC * JwC + this.m_iA * JwA * JwA;
  
  					var pC = Vec2.sub(this.m_localAnchorC, this.m_lcC); // Vec2
  					var pA = Rot.mulTVec2(qC, Vec2.add(rA, Vec2.sub(cA, cC))); // Vec2
  					coordinateA = Vec2.dot(Vec2.sub(pA, pC), this.m_localAxisC);
  				}
  
  				if (this.m_type2 == RevoluteJoint.TYPE) {
  					JvBD = Vec2.zero();
  					JwB = this.m_ratio;
  					JwD = this.m_ratio;
  					mass += this.m_ratio * this.m_ratio * (this.m_iB + this.m_iD);
  
  					coordinateB = aB - aD - this.m_referenceAngleB;
  				} else {
  					var u = Rot.mulVec2(qD, this.m_localAxisD);
  					var rD = Rot.mulSub(qD, this.m_localAnchorD, this.m_lcD);
  					var rB = Rot.mulSub(qB, this.m_localAnchorB, this.m_lcB);
  					JvBD = Vec2.mul(this.m_ratio, u);
  					JwD = this.m_ratio * Vec2.cross(rD, u);
  					JwB = this.m_ratio * Vec2.cross(rB, u);
  					mass += this.m_ratio * this.m_ratio * (this.m_mD + this.m_mB) + this.m_iD * JwD * JwD + this.m_iB * JwB * JwB;
  
  					var pD = Vec2.sub(this.m_localAnchorD, this.m_lcD); // Vec2
  					var pB = Rot.mulTVec2(qD, Vec2.add(rB, Vec2.sub(cB, cD))); // Vec2
  					coordinateB = Vec2.dot(pB, this.m_localAxisD) - Vec2.dot(pD, this.m_localAxisD);
  				}
  
  				var C = coordinateA + this.m_ratio * coordinateB - this.m_constant; // float
  
  				var impulse = 0.0; // float
  				if (mass > 0.0) {
  					impulse = -C / mass;
  				}
  
  				cA.addMul(this.m_mA * impulse, JvAC);
  				aA += this.m_iA * impulse * JwA;
  				cB.addMul(this.m_mB * impulse, JvBD);
  				aB += this.m_iB * impulse * JwB;
  				cC.subMul(this.m_mC * impulse, JvAC);
  				aC -= this.m_iC * impulse * JwC;
  				cD.subMul(this.m_mD * impulse, JvBD);
  				aD -= this.m_iD * impulse * JwD;
  
  				this.m_bodyA.c_position.c.set(cA);
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c.set(cB);
  				this.m_bodyB.c_position.a = aB;
  				this.m_bodyC.c_position.c.set(cC);
  				this.m_bodyC.c_position.a = aC;
  				this.m_bodyD.c_position.c.set(cD);
  				this.m_bodyD.c_position.a = aD;
  
  				// TODO_ERIN not implemented
  				return linearError < Settings.linearSlop;
  			};
  
  			/***/
  		},
  		/* 54 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = MotorJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			MotorJoint.TYPE = 'motor-joint';
  			Joint.TYPES[MotorJoint.TYPE] = MotorJoint;
  
  			MotorJoint._super = Joint;
  			MotorJoint.prototype = create(MotorJoint._super.prototype);
  
  			/**
               * @typedef {Object} MotorJointDef
               *
               * Motor joint definition.
               *
               * @prop {float} angularOffset The bodyB angle minus bodyA angle in radians.
               * @prop {float} maxForce The maximum motor force in N.
               * @prop {float} maxTorque The maximum motor torque in N-m.
               * @prop {float} correctionFactor Position correction factor in the range [0,1].
               * @prop {Vec2} linearOffset Position of bodyB minus the position of bodyA, in
               *       bodyA's frame, in meters.
               */
  
  			var DEFAULTS = {
  				maxForce: 1.0,
  				maxTorque: 1.0,
  				correctionFactor: 0.3
  			};
  
  			/**
               * A motor joint is used to control the relative motion between two bodies. A
               * typical usage is to control the movement of a dynamic body with respect to
               * the ground.
               *
               * @param {MotorJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function MotorJoint (def, bodyA, bodyB) {
  				if (!(this instanceof MotorJoint)) {
  					return new MotorJoint(def, bodyA, bodyB);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = MotorJoint.TYPE;
  
  				this.m_linearOffset = def.linearOffset ? def.linearOffset : bodyA.getLocalPoint(bodyB.getPosition());
  
  				var angleA = bodyA.getAngle();
  				var angleB = bodyB.getAngle();
  				this.m_angularOffset = angleB - angleA;
  
  				this.m_linearImpulse = Vec2.zero();
  				this.m_angularImpulse = 0.0;
  
  				this.m_maxForce = def.maxForce;
  				this.m_maxTorque = def.maxTorque;
  				this.m_correctionFactor = def.correctionFactor;
  
  				// Solver temp
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_linearError; // Vec2
  				this.m_angularError; // float
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				this.m_linearMass; // Mat22
  				this.m_angularMass; // float
  
  				// Point-to-point constraint
  				// Cdot = v2 - v1
  				// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
  				// J = [-I -r1_skew I r2_skew ]
  				// Identity used:
  				// w k % (rx i + ry j) = w * (-ry i + rx j)
  
  				// Angle constraint
  				// Cdot = w2 - w1
  				// J = [0 0 -1 0 0 1]
  				// K = invI1 + invI2
  			}
  
  			MotorJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					linearOffset: this.m_linearOffset,
  					maxForce: this.m_maxForce,
  					maxTorque: this.m_maxTorque,
  					correctionFactor: this.m_correctionFactor,
  
  					_angularOffset: this.m_angularOffset
  				};
  			};
  
  			MotorJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new MotorJoint(data);
  				if (data._angularOffset) joint.m_angularOffset = data._angularOffset;
  				return joint;
  			};
  
  			/**
               * Set the maximum friction force in N.
               */
  			MotorJoint.prototype.setMaxForce = function (force) {
  				_ASSERT && common.assert(Math.isFinite(force) && force >= 0.0);
  				this.m_maxForce = force;
  			};
  
  			/**
               * Get the maximum friction force in N.
               */
  			MotorJoint.prototype.getMaxForce = function () {
  				return this.m_maxForce;
  			};
  
  			/**
               * Set the maximum friction torque in N*m.
               */
  			MotorJoint.prototype.setMaxTorque = function (torque) {
  				_ASSERT && common.assert(Math.isFinite(torque) && torque >= 0.0);
  				this.m_maxTorque = torque;
  			};
  
  			/**
               * Get the maximum friction torque in N*m.
               */
  			MotorJoint.prototype.getMaxTorque = function () {
  				return this.m_maxTorque;
  			};
  
  			/**
               * Set the position correction factor in the range [0,1].
               */
  			MotorJoint.prototype.setCorrectionFactor = function (factor) {
  				_ASSERT && common.assert(Math.isFinite(factor) && factor >= 0.0 && factor <= 1.0);
  				this.m_correctionFactor = factor;
  			};
  
  			/**
               * Get the position correction factor in the range [0,1].
               */
  			MotorJoint.prototype.getCorrectionFactor = function () {
  				return this.m_correctionFactor;
  			};
  
  			/**
               * Set/get the target linear offset, in frame A, in meters.
               */
  			MotorJoint.prototype.setLinearOffset = function (linearOffset) {
  				if (linearOffset.x != this.m_linearOffset.x || linearOffset.y != this.m_linearOffset.y) {
  					this.m_bodyA.setAwake(true);
  					this.m_bodyB.setAwake(true);
  					this.m_linearOffset = linearOffset;
  				}
  			};
  
  			MotorJoint.prototype.getLinearOffset = function () {
  				return this.m_linearOffset;
  			};
  
  			/**
               * Set/get the target angular offset, in radians.
               */
  			MotorJoint.prototype.setAngularOffset = function (angularOffset) {
  				if (angularOffset != this.m_angularOffset) {
  					this.m_bodyA.setAwake(true);
  					this.m_bodyB.setAwake(true);
  					this.m_angularOffset = angularOffset;
  				}
  			};
  
  			MotorJoint.prototype.getAngularOffset = function () {
  				return this.m_angularOffset;
  			};
  
  			MotorJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getPosition();
  			};
  
  			MotorJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getPosition();
  			};
  
  			MotorJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(inv_dt, this.m_linearImpulse);
  			};
  
  			MotorJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * this.m_angularImpulse;
  			};
  
  			MotorJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				// Compute the effective mass matrix.
  				this.m_rA = Rot.mulVec2(qA, Vec2.neg(this.m_localCenterA));
  				this.m_rB = Rot.mulVec2(qB, Vec2.neg(this.m_localCenterB));
  
  				// J = [-I -r1_skew I r2_skew]
  				// [ 0 -1 0 1]
  				// r_skew = [-ry; rx]
  
  				// Matlab
  				// K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
  				// [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
  				// [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB;
  				var iA = this.m_invIA;
  				var iB = this.m_invIB;
  
  				var K = new Mat22();
  				K.ex.x = mA + mB + iA * this.m_rA.y * this.m_rA.y + iB * this.m_rB.y * this.m_rB.y;
  				K.ex.y = -iA * this.m_rA.x * this.m_rA.y - iB * this.m_rB.x * this.m_rB.y;
  				K.ey.x = K.ex.y;
  				K.ey.y = mA + mB + iA * this.m_rA.x * this.m_rA.x + iB * this.m_rB.x * this.m_rB.x;
  
  				this.m_linearMass = K.getInverse();
  
  				this.m_angularMass = iA + iB;
  				if (this.m_angularMass > 0.0) {
  					this.m_angularMass = 1.0 / this.m_angularMass;
  				}
  
  				this.m_linearError = Vec2.zero();
  				this.m_linearError.addCombine(1, cB, 1, this.m_rB);
  				this.m_linearError.subCombine(1, cA, 1, this.m_rA);
  				this.m_linearError.sub(Rot.mulVec2(qA, this.m_linearOffset));
  
  				this.m_angularError = aB - aA - this.m_angularOffset;
  
  				if (step.warmStarting) {
  					// Scale impulses to support a variable time step.
  					this.m_linearImpulse.mul(step.dtRatio);
  					this.m_angularImpulse *= step.dtRatio;
  
  					var P = Vec2.neo(this.m_linearImpulse.x, this.m_linearImpulse.y);
  
  					vA.subMul(mA, P);
  					wA -= iA * (Vec2.cross(this.m_rA, P) + this.m_angularImpulse);
  
  					vB.addMul(mB, P);
  					wB += iB * (Vec2.cross(this.m_rB, P) + this.m_angularImpulse);
  				} else {
  					this.m_linearImpulse.setZero();
  					this.m_angularImpulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			MotorJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB;
  				var iA = this.m_invIA;
  				var iB = this.m_invIB;
  
  				var h = step.dt;
  				var inv_h = step.inv_dt;
  
  				// Solve angular friction
  				{
  					var Cdot = wB - wA + inv_h * this.m_correctionFactor * this.m_angularError;
  					var impulse = -this.m_angularMass * Cdot;
  
  					var oldImpulse = this.m_angularImpulse;
  					var maxImpulse = h * this.m_maxTorque;
  					this.m_angularImpulse = Math.clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse);
  					impulse = this.m_angularImpulse - oldImpulse;
  
  					wA -= iA * impulse;
  					wB += iB * impulse;
  				}
  
  				// Solve linear friction
  				{
  					var Cdot = Vec2.zero();
  					Cdot.addCombine(1, vB, 1, Vec2.cross(wB, this.m_rB));
  					Cdot.subCombine(1, vA, 1, Vec2.cross(wA, this.m_rA));
  					Cdot.addMul(inv_h * this.m_correctionFactor, this.m_linearError);
  
  					var impulse = Vec2.neg(Mat22.mulVec2(this.m_linearMass, Cdot));
  					var oldImpulse = Vec2.clone(this.m_linearImpulse);
  					this.m_linearImpulse.add(impulse);
  
  					var maxImpulse = h * this.m_maxForce;
  
  					this.m_linearImpulse.clamp(maxImpulse);
  
  					impulse = Vec2.sub(this.m_linearImpulse, oldImpulse);
  
  					vA.subMul(mA, impulse);
  					wA -= iA * Vec2.cross(this.m_rA, impulse);
  
  					vB.addMul(mB, impulse);
  					wB += iB * Vec2.cross(this.m_rB, impulse);
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			MotorJoint.prototype.solvePositionConstraints = function (step) {
  				return true;
  			};
  
  			/***/
  		},
  		/* 55 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = MouseJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			MouseJoint.TYPE = 'mouse-joint';
  			Joint.TYPES[MouseJoint.TYPE] = MouseJoint;
  
  			MouseJoint._super = Joint;
  			MouseJoint.prototype = create(MouseJoint._super.prototype);
  
  			/**
               * @typedef {Object} MouseJointDef
               *
               * Mouse joint definition. This requires a world target point, tuning
               * parameters, and the time step.
               *
               * @prop [maxForce = 0.0] The maximum constraint force that can be exerted to
               *       move the candidate body. Usually you will express as some multiple of
               *       the weight (multiplier * mass * gravity).
               * @prop [frequencyHz = 5.0] The response speed.
               * @prop [dampingRatio = 0.7] The damping ratio. 0 = no damping, 1 = critical
               *       damping.
               *
               * @prop {Vec2} target The initial world target point. This is assumed to
               *       coincide with the body anchor initially.
               */
  
  			var DEFAULTS = {
  				maxForce: 0.0,
  				frequencyHz: 5.0,
  				dampingRatio: 0.7
  			};
  
  			/**
               * A mouse joint is used to make a point on a body track a specified world
               * point. This a soft constraint with a maximum force. This allows the
               * constraint to stretch and without applying huge forces.
               *
               * NOTE: this joint is not documented in the manual because it was developed to
               * be used in the testbed. If you want to learn how to use the mouse joint, look
               * at the testbed.
               *
               * @param {MouseJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function MouseJoint (def, bodyA, bodyB, target) {
  				if (!(this instanceof MouseJoint)) {
  					return new MouseJoint(def, bodyA, bodyB, target);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = MouseJoint.TYPE;
  
  				_ASSERT && common.assert(Math.isFinite(def.maxForce) && def.maxForce >= 0.0);
  				_ASSERT && common.assert(Math.isFinite(def.frequencyHz) && def.frequencyHz >= 0.0);
  				_ASSERT && common.assert(Math.isFinite(def.dampingRatio) && def.dampingRatio >= 0.0);
  
  				this.m_targetA = target ? Vec2.clone(target) : def.target || Vec2.zero();
  				this.m_localAnchorB = Transform.mulTVec2(bodyB.getTransform(), this.m_targetA);
  
  				this.m_maxForce = def.maxForce;
  				this.m_impulse = Vec2.zero();
  
  				this.m_frequencyHz = def.frequencyHz;
  				this.m_dampingRatio = def.dampingRatio;
  
  				this.m_beta = 0.0;
  				this.m_gamma = 0.0;
  
  				// Solver temp
  				this.m_rB = Vec2.zero();
  				this.m_localCenterB = Vec2.zero();
  				this.m_invMassB = 0.0;
  				this.m_invIB = 0.0;
  				this.mass = new Mat22();
  				this.m_C = Vec2.zero();
  
  				// p = attached point, m = mouse point
  				// C = p - m
  				// Cdot = v
  				// = v + cross(w, r)
  				// J = [I r_skew]
  				// Identity used:
  				// w k % (rx i + ry j) = w * (-ry i + rx j)
  			}
  
  			MouseJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					target: this.m_targetA,
  					maxForce: this.m_maxForce,
  					frequencyHz: this.m_frequencyHz,
  					dampingRatio: this.m_dampingRatio,
  
  					_localAnchorB: this.m_localAnchorB
  				};
  			};
  
  			MouseJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				data.target = Vec2(data.target);
  				var joint = new MouseJoint(data);
  				if (data._localAnchorB) joint.m_localAnchorB = data._localAnchorB;
  				return joint;
  			};
  
  			/**
               * Use this to update the target point.
               */
  			MouseJoint.prototype.setTarget = function (target) {
  				if (this.m_bodyB.isAwake() == false) {
  					this.m_bodyB.setAwake(true);
  				}
  				this.m_targetA = Vec2.clone(target);
  			};
  
  			MouseJoint.prototype.getTarget = function () {
  				return this.m_targetA;
  			};
  
  			/**
               * Set/get the maximum force in Newtons.
               */
  			MouseJoint.prototype.setMaxForce = function (force) {
  				this.m_maxForce = force;
  			};
  
  			MouseJoint.getMaxForce = function () {
  				return this.m_maxForce;
  			};
  
  			/**
               * Set/get the frequency in Hertz.
               */
  			MouseJoint.prototype.setFrequency = function (hz) {
  				this.m_frequencyHz = hz;
  			};
  
  			MouseJoint.prototype.getFrequency = function () {
  				return this.m_frequencyHz;
  			};
  
  			/**
               * Set/get the damping ratio (dimensionless).
               */
  			MouseJoint.prototype.setDampingRatio = function (ratio) {
  				this.m_dampingRatio = ratio;
  			};
  
  			MouseJoint.prototype.getDampingRatio = function () {
  				return this.m_dampingRatio;
  			};
  
  			MouseJoint.prototype.getAnchorA = function () {
  				return Vec2.clone(this.m_targetA);
  			};
  
  			MouseJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			MouseJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(inv_dt, this.m_impulse);
  			};
  
  			MouseJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * 0.0;
  			};
  
  			MouseJoint.prototype.shiftOrigin = function (newOrigin) {
  				this.m_targetA.sub(newOrigin);
  			};
  
  			MouseJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var position = this.m_bodyB.c_position;
  				var velocity = this.m_bodyB.c_velocity;
  
  				var cB = position.c;
  				var aB = position.a;
  				var vB = velocity.v;
  				var wB = velocity.w;
  
  				var qB = Rot.neo(aB);
  
  				var mass = this.m_bodyB.getMass();
  
  				// Frequency
  				var omega = 2.0 * Math.PI * this.m_frequencyHz;
  
  				// Damping coefficient
  				var d = 2.0 * mass * this.m_dampingRatio * omega;
  
  				// Spring stiffness
  				var k = mass * (omega * omega);
  
  				// magic formulas
  				// gamma has units of inverse mass.
  				// beta has units of inverse time.
  				var h = step.dt;
  				_ASSERT && common.assert(d + h * k > Math.EPSILON);
  				this.m_gamma = h * (d + h * k);
  				if (this.m_gamma != 0.0) {
  					this.m_gamma = 1.0 / this.m_gamma;
  				}
  				this.m_beta = h * k * this.m_gamma;
  
  				// Compute the effective mass matrix.
  				this.m_rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				// K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) *
  				// invI2 * skew(r2)]
  				// = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y
  				// -r1.x*r1.y]
  				// [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
  				var K = new Mat22();
  				K.ex.x = this.m_invMassB + this.m_invIB * this.m_rB.y * this.m_rB.y + this.m_gamma;
  				K.ex.y = -this.m_invIB * this.m_rB.x * this.m_rB.y;
  				K.ey.x = K.ex.y;
  				K.ey.y = this.m_invMassB + this.m_invIB * this.m_rB.x * this.m_rB.x + this.m_gamma;
  
  				this.m_mass = K.getInverse();
  
  				this.m_C.set(cB);
  				this.m_C.addCombine(1, this.m_rB, -1, this.m_targetA);
  				this.m_C.mul(this.m_beta);
  
  				// Cheat with some damping
  				wB *= 0.98;
  
  				if (step.warmStarting) {
  					this.m_impulse.mul(step.dtRatio);
  					vB.addMul(this.m_invMassB, this.m_impulse);
  					wB += this.m_invIB * Vec2.cross(this.m_rB, this.m_impulse);
  				} else {
  					this.m_impulse.setZero();
  				}
  
  				velocity.v.set(vB);
  				velocity.w = wB;
  			};
  
  			MouseJoint.prototype.solveVelocityConstraints = function (step) {
  				var velocity = this.m_bodyB.c_velocity;
  				var vB = Vec2.clone(velocity.v);
  				var wB = velocity.w;
  
  				// Cdot = v + cross(w, r)
  
  				var Cdot = Vec2.cross(wB, this.m_rB);
  				Cdot.add(vB);
  
  				Cdot.addCombine(1, this.m_C, this.m_gamma, this.m_impulse);
  				Cdot.neg();
  
  				var impulse = Mat22.mulVec2(this.m_mass, Cdot);
  
  				var oldImpulse = Vec2.clone(this.m_impulse);
  				this.m_impulse.add(impulse);
  				var maxImpulse = step.dt * this.m_maxForce;
  				this.m_impulse.clamp(maxImpulse);
  				impulse = Vec2.sub(this.m_impulse, oldImpulse);
  
  				vB.addMul(this.m_invMassB, impulse);
  				wB += this.m_invIB * Vec2.cross(this.m_rB, impulse);
  
  				velocity.v.set(vB);
  				velocity.w = wB;
  			};
  
  			MouseJoint.prototype.solvePositionConstraints = function (step) {
  				return true;
  			};
  
  			/***/
  		},
  		/* 56 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = PulleyJoint;
  
  			var common = __webpack_require__(2);
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			PulleyJoint.TYPE = 'pulley-joint';
  			PulleyJoint.MIN_PULLEY_LENGTH = 2.0; // minPulleyLength
  			Joint.TYPES[PulleyJoint.TYPE] = PulleyJoint;
  
  			PulleyJoint._super = Joint;
  			PulleyJoint.prototype = create(PulleyJoint._super.prototype);
  
  			/**
               * @typedef {Object} PulleyJointDef
               *
               * Pulley joint definition. This requires two ground anchors, two dynamic body
               * anchor points, and a pulley ratio.
               *
               * @prop {Vec2} groundAnchorA The first ground anchor in world coordinates.
               *          This point never moves.
               * @prop {Vec2} groundAnchorB The second ground anchor in world coordinates.
               *          This point never moves.
               * @prop {Vec2} localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} localAnchorB The local anchor point relative to bodyB's origin.
               * @prop {float} ratio The pulley ratio, used to simulate a block-and-tackle.
               * @prop {float} lengthA The reference length for the segment attached to bodyA.
               * @prop {float} lengthB The reference length for the segment attached to bodyB.
               */
  			var PulleyJointDef = {
  				collideConnected: true
  			};
  
  			/**
               * The pulley joint is connected to two bodies and two fixed ground points. The
               * pulley supports a ratio such that: length1 + ratio * length2 <= constant
               *
               * Yes, the force transmitted is scaled by the ratio.
               *
               * Warning: the pulley joint can get a bit squirrelly by itself. They often work
               * better when combined with prismatic joints. You should also cover the the
               * anchor points with static shapes to prevent one side from going to zero
               * length.
               *
               * @param {PulleyJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function PulleyJoint (def, bodyA, bodyB, groundA, groundB, anchorA, anchorB, ratio) {
  				if (!(this instanceof PulleyJoint)) {
  					return new PulleyJoint(def, bodyA, bodyB, groundA, groundB, anchorA, anchorB, ratio);
  				}
  
  				def = options(def, PulleyJointDef);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = PulleyJoint.TYPE;
  				this.m_groundAnchorA = groundA || def.groundAnchorA || Vec2.neo(-1.0, 1.0);
  				this.m_groundAnchorB = groundB || def.groundAnchorB || Vec2.neo(1.0, 1.0);
  				this.m_localAnchorA = anchorA ? bodyA.getLocalPoint(anchorA) : def.localAnchorA || Vec2.neo(-1.0, 0.0);
  				this.m_localAnchorB = anchorB ? bodyB.getLocalPoint(anchorB) : def.localAnchorB || Vec2.neo(1.0, 0.0);
  				this.m_lengthA = Math.isFinite(def.lengthA) ? def.lengthA : Vec2.distance(anchorA, groundA);
  				this.m_lengthB = Math.isFinite(def.lengthB) ? def.lengthB : Vec2.distance(anchorB, groundB);
  				this.m_ratio = Math.isFinite(ratio) ? ratio : def.ratio;
  
  				_ASSERT && common.assert(ratio > Math.EPSILON);
  
  				this.m_constant = this.m_lengthA + this.m_ratio * this.m_lengthB;
  
  				this.m_impulse = 0.0;
  
  				// Solver temp
  				this.m_uA; // Vec2
  				this.m_uB; // Vec2
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				this.m_mass; // float
  
  				// Pulley:
  				// length1 = norm(p1 - s1)
  				// length2 = norm(p2 - s2)
  				// C0 = (length1 + ratio * length2)_initial
  				// C = C0 - (length1 + ratio * length2)
  				// u1 = (p1 - s1) / norm(p1 - s1)
  				// u2 = (p2 - s2) / norm(p2 - s2)
  				// Cdot = -dot(u1, v1 + cross(w1, r1)) - ratio * dot(u2, v2 + cross(w2, r2))
  				// J = -[u1 cross(r1, u1) ratio * u2 ratio * cross(r2, u2)]
  				// K = J * invM * JT
  				// = invMass1 + invI1 * cross(r1, u1)^2 + ratio^2 * (invMass2 + invI2 *
  				// cross(r2, u2)^2)
  			}
  
  			PulleyJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					groundAnchorA: this.m_groundAnchorA,
  					groundAnchorB: this.m_groundAnchorB,
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					lengthA: this.m_lengthA,
  					lengthB: this.m_lengthB,
  					ratio: this.m_ratio
  				};
  			};
  
  			PulleyJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new PulleyJoint(data);
  				return joint;
  			};
  
  			/**
               * Get the first ground anchor.
               */
  			PulleyJoint.prototype.getGroundAnchorA = function () {
  				return this.m_groundAnchorA;
  			};
  
  			/**
               * Get the second ground anchor.
               */
  			PulleyJoint.prototype.getGroundAnchorB = function () {
  				return this.m_groundAnchorB;
  			};
  
  			/**
               * Get the current length of the segment attached to bodyA.
               */
  			PulleyJoint.prototype.getLengthA = function () {
  				return this.m_lengthA;
  			};
  
  			/**
               * Get the current length of the segment attached to bodyB.
               */
  			PulleyJoint.prototype.getLengthB = function () {
  				return this.m_lengthB;
  			};
  
  			/**
               * Get the pulley ratio.
               */
  			PulleyJoint.prototype.getRatio = function () {
  				return this.m_ratio;
  			};
  
  			/**
               * Get the current length of the segment attached to bodyA.
               */
  			PulleyJoint.prototype.getCurrentLengthA = function () {
  				var p = this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  				var s = this.m_groundAnchorA;
  				return Vec2.distance(p, s);
  			};
  
  			/**
               * Get the current length of the segment attached to bodyB.
               */
  			PulleyJoint.prototype.getCurrentLengthB = function () {
  				var p = this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  				var s = this.m_groundAnchorB;
  				return Vec2.distance(p, s);
  			};
  
  			PulleyJoint.prototype.shiftOrigin = function (newOrigin) {
  				this.m_groundAnchorA.sub(newOrigin);
  				this.m_groundAnchorB.sub(newOrigin);
  			};
  
  			PulleyJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			PulleyJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			PulleyJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(this.m_impulse, this.m_uB).mul(inv_dt);
  			};
  
  			PulleyJoint.prototype.getReactionTorque = function (inv_dt) {
  				return 0.0;
  			};
  
  			PulleyJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				this.m_rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				this.m_rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				// Get the pulley axes.
  				this.m_uA = Vec2.sub(Vec2.add(cA, this.m_rA), this.m_groundAnchorA);
  				this.m_uB = Vec2.sub(Vec2.add(cB, this.m_rB), this.m_groundAnchorB);
  
  				var lengthA = this.m_uA.length();
  				var lengthB = this.m_uB.length();
  
  				if (lengthA > 10.0 * Settings.linearSlop) {
  					this.m_uA.mul(1.0 / lengthA);
  				} else {
  					this.m_uA.setZero();
  				}
  
  				if (lengthB > 10.0 * Settings.linearSlop) {
  					this.m_uB.mul(1.0 / lengthB);
  				} else {
  					this.m_uB.setZero();
  				}
  
  				// Compute effective mass.
  				var ruA = Vec2.cross(this.m_rA, this.m_uA); // float
  				var ruB = Vec2.cross(this.m_rB, this.m_uB); // float
  
  				var mA = this.m_invMassA + this.m_invIA * ruA * ruA; // float
  				var mB = this.m_invMassB + this.m_invIB * ruB * ruB; // float
  
  				this.m_mass = mA + this.m_ratio * this.m_ratio * mB;
  
  				if (this.m_mass > 0.0) {
  					this.m_mass = 1.0 / this.m_mass;
  				}
  
  				if (step.warmStarting) {
  					// Scale impulses to support variable time steps.
  					this.m_impulse *= step.dtRatio;
  
  					// Warm starting.
  					var PA = Vec2.mul(-this.m_impulse, this.m_uA);
  					var PB = Vec2.mul(-this.m_ratio * this.m_impulse, this.m_uB);
  
  					vA.addMul(this.m_invMassA, PA);
  					wA += this.m_invIA * Vec2.cross(this.m_rA, PA);
  
  					vB.addMul(this.m_invMassB, PB);
  					wB += this.m_invIB * Vec2.cross(this.m_rB, PB);
  				} else {
  					this.m_impulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			PulleyJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var vpA = Vec2.add(vA, Vec2.cross(wA, this.m_rA));
  				var vpB = Vec2.add(vB, Vec2.cross(wB, this.m_rB));
  
  				var Cdot = -Vec2.dot(this.m_uA, vpA) - this.m_ratio * Vec2.dot(this.m_uB, vpB); // float
  				var impulse = -this.m_mass * Cdot; // float
  				this.m_impulse += impulse;
  
  				var PA = Vec2.mul(-impulse, this.m_uA); // Vec2
  				var PB = Vec2.mul(-this.m_ratio * impulse, this.m_uB); // Vec2
  				vA.addMul(this.m_invMassA, PA);
  				wA += this.m_invIA * Vec2.cross(this.m_rA, PA);
  				vB.addMul(this.m_invMassB, PB);
  				wB += this.m_invIB * Vec2.cross(this.m_rB, PB);
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			PulleyJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				// Get the pulley axes.
  				var uA = Vec2.sub(Vec2.add(cA, this.m_rA), this.m_groundAnchorA);
  				var uB = Vec2.sub(Vec2.add(cB, this.m_rB), this.m_groundAnchorB);
  
  				var lengthA = uA.length();
  				var lengthB = uB.length();
  
  				if (lengthA > 10.0 * Settings.linearSlop) {
  					uA.mul(1.0 / lengthA);
  				} else {
  					uA.setZero();
  				}
  
  				if (lengthB > 10.0 * Settings.linearSlop) {
  					uB.mul(1.0 / lengthB);
  				} else {
  					uB.setZero();
  				}
  
  				// Compute effective mass.
  				var ruA = Vec2.cross(rA, uA);
  				var ruB = Vec2.cross(rB, uB);
  
  				var mA = this.m_invMassA + this.m_invIA * ruA * ruA; // float
  				var mB = this.m_invMassB + this.m_invIB * ruB * ruB; // float
  
  				var mass = mA + this.m_ratio * this.m_ratio * mB; // float
  
  				if (mass > 0.0) {
  					mass = 1.0 / mass;
  				}
  
  				var C = this.m_constant - lengthA - this.m_ratio * lengthB; // float
  				var linearError = Math.abs(C); // float
  
  				var impulse = -mass * C; // float
  
  				var PA = Vec2.mul(-impulse, uA); // Vec2
  				var PB = Vec2.mul(-this.m_ratio * impulse, uB); // Vec2
  
  				cA.addMul(this.m_invMassA, PA);
  				aA += this.m_invIA * Vec2.cross(rA, PA);
  				cB.addMul(this.m_invMassB, PB);
  				aB += this.m_invIB * Vec2.cross(rB, PB);
  
  				this.m_bodyA.c_position.c = cA;
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c = cB;
  				this.m_bodyB.c_position.a = aB;
  
  				return linearError < Settings.linearSlop;
  			};
  
  			/***/
  		},
  		/* 57 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = RopeJoint;
  
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			var inactiveLimit = 0;
  			var atLowerLimit = 1;
  			var atUpperLimit = 2;
  			var equalLimits = 3;
  
  			RopeJoint.TYPE = 'rope-joint';
  			Joint.TYPES[RopeJoint.TYPE] = RopeJoint;
  
  			RopeJoint._super = Joint;
  			RopeJoint.prototype = create(RopeJoint._super.prototype);
  
  			/**
               * @typedef {Object} RopeJointDef
               *
               * Rope joint definition. This requires two body anchor points and a maximum
               * lengths. Note: by default the connected objects will not collide. see
               * collideConnected in JointDef.
               *
               * @prop {float} maxLength The maximum length of the rope. Warning: this must be
               *       larger than linearSlop or the joint will have no effect.
               *
               * @prop {Vec2} def.localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} def.localAnchorB The local anchor point relative to bodyB's origin.
               */
  
  			var DEFAULTS = {
  				maxLength: 0.0
  			};
  
  			/**
               * A rope joint enforces a maximum distance between two points on two bodies. It
               * has no other effect.
               *
               * Warning: if you attempt to change the maximum length during the simulation
               * you will get some non-physical behavior.
               *
               * A model that would allow you to dynamically modify the length would have some
               * sponginess, so I chose not to implement it that way. See DistanceJoint if you
               * want to dynamically control length.
               *
               * @param {RopeJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function RopeJoint (def, bodyA, bodyB, anchor) {
  				if (!(this instanceof RopeJoint)) {
  					return new RopeJoint(def, bodyA, bodyB, anchor);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = RopeJoint.TYPE;
  				this.m_localAnchorA = anchor ? bodyA.getLocalPoint(anchor) : def.localAnchorA || Vec2.neo(-1.0, 0.0);
  				this.m_localAnchorB = anchor ? bodyB.getLocalPoint(anchor) : def.localAnchorB || Vec2.neo(1.0, 0.0);
  
  				this.m_maxLength = def.maxLength;
  
  				this.m_mass = 0.0;
  				this.m_impulse = 0.0;
  				this.m_length = 0.0;
  				this.m_state = inactiveLimit;
  
  				// Solver temp
  				this.m_u; // Vec2
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				this.m_mass; // float
  
  				// Limit:
  				// C = norm(pB - pA) - L
  				// u = (pB - pA) / norm(pB - pA)
  				// Cdot = dot(u, vB + cross(wB, rB) - vA - cross(wA, rA))
  				// J = [-u -cross(rA, u) u cross(rB, u)]
  				// K = J * invM * JT
  				// = invMassA + invIA * cross(rA, u)^2 + invMassB + invIB * cross(rB, u)^2
  			}
  
  			RopeJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					maxLength: this.m_maxLength
  				};
  			};
  
  			RopeJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new RopeJoint(data);
  				return joint;
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			RopeJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			RopeJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * Set/Get the maximum length of the rope.
               */
  			RopeJoint.prototype.setMaxLength = function (length) {
  				this.m_maxLength = length;
  			};
  
  			RopeJoint.prototype.getMaxLength = function () {
  				return this.m_maxLength;
  			};
  
  			RopeJoint.prototype.getLimitState = function () {
  				// TODO LimitState
  				return this.m_state;
  			};
  
  			RopeJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			RopeJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			RopeJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.mul(this.m_impulse, this.m_u).mul(inv_dt);
  			};
  
  			RopeJoint.prototype.getReactionTorque = function (inv_dt) {
  				return 0.0;
  			};
  
  			RopeJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				this.m_rA = Rot.mulSub(qA, this.m_localAnchorA, this.m_localCenterA);
  				this.m_rB = Rot.mulSub(qB, this.m_localAnchorB, this.m_localCenterB);
  				this.m_u = Vec2.zero();
  				this.m_u.addCombine(1, cB, 1, this.m_rB);
  				this.m_u.subCombine(1, cA, 1, this.m_rA); // Vec2
  
  				this.m_length = this.m_u.length();
  
  				var C = this.m_length - this.m_maxLength; // float
  				if (C > 0.0) {
  					this.m_state = atUpperLimit;
  				} else {
  					this.m_state = inactiveLimit;
  				}
  
  				if (this.m_length > Settings.linearSlop) {
  					this.m_u.mul(1.0 / this.m_length);
  				} else {
  					this.m_u.setZero();
  					this.m_mass = 0.0;
  					this.m_impulse = 0.0;
  					return;
  				}
  
  				// Compute effective mass.
  				var crA = Vec2.cross(this.m_rA, this.m_u); // float
  				var crB = Vec2.cross(this.m_rB, this.m_u); // float
  				var invMass = this.m_invMassA + this.m_invIA * crA * crA + this.m_invMassB + this.m_invIB * crB * crB; // float
  
  				this.m_mass = invMass != 0.0 ? 1.0 / invMass : 0.0;
  
  				if (step.warmStarting) {
  					// Scale the impulse to support a variable time step.
  					this.m_impulse *= step.dtRatio;
  
  					var P = Vec2.mul(this.m_impulse, this.m_u);
  
  					vA.subMul(this.m_invMassA, P);
  					wA -= this.m_invIA * Vec2.cross(this.m_rA, P);
  
  					vB.addMul(this.m_invMassB, P);
  					wB += this.m_invIB * Vec2.cross(this.m_rB, P);
  				} else {
  					this.m_impulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			RopeJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				// Cdot = dot(u, v + cross(w, r))
  				var vpA = Vec2.addCross(vA, wA, this.m_rA); // Vec2
  				var vpB = Vec2.addCross(vB, wB, this.m_rB); // Vec2
  				var C = this.m_length - this.m_maxLength; // float
  				var Cdot = Vec2.dot(this.m_u, Vec2.sub(vpB, vpA)); // float
  
  				// Predictive constraint.
  				if (C < 0.0) {
  					Cdot += step.inv_dt * C;
  				}
  
  				var impulse = -this.m_mass * Cdot; // float
  				var oldImpulse = this.m_impulse; // float
  				this.m_impulse = Math.min(0.0, this.m_impulse + impulse);
  				impulse = this.m_impulse - oldImpulse;
  
  				var P = Vec2.mul(impulse, this.m_u); // Vec2
  				vA.subMul(this.m_invMassA, P);
  				wA -= this.m_invIA * Vec2.cross(this.m_rA, P);
  				vB.addMul(this.m_invMassB, P);
  				wB += this.m_invIB * Vec2.cross(this.m_rB, P);
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			RopeJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c; // Vec2
  				var aA = this.m_bodyA.c_position.a; // float
  				var cB = this.m_bodyB.c_position.c; // Vec2
  				var aB = this.m_bodyB.c_position.a; // float
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var rA = Rot.mulSub(qA, this.m_localAnchorA, this.m_localCenterA);
  				var rB = Rot.mulSub(qB, this.m_localAnchorB, this.m_localCenterB);
  				var u = Vec2.zero();
  				u.addCombine(1, cB, 1, rB);
  				u.subCombine(1, cA, 1, rA); // Vec2
  
  				var length = u.normalize(); // float
  				var C = length - this.m_maxLength; // float
  
  				C = Math.clamp(C, 0.0, Settings.maxLinearCorrection);
  
  				var impulse = -this.m_mass * C; // float
  				var P = Vec2.mul(impulse, u); // Vec2
  
  				cA.subMul(this.m_invMassA, P);
  				aA -= this.m_invIA * Vec2.cross(rA, P);
  				cB.addMul(this.m_invMassB, P);
  				aB += this.m_invIB * Vec2.cross(rB, P);
  
  				this.m_bodyA.c_position.c.set(cA);
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c.set(cB);
  				this.m_bodyB.c_position.a = aB;
  
  				return length - this.m_maxLength < Settings.linearSlop;
  			};
  
  			/***/
  		},
  		/* 58 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = WeldJoint;
  
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			WeldJoint.TYPE = 'weld-joint';
  			Joint.TYPES[WeldJoint.TYPE] = WeldJoint;
  
  			WeldJoint._super = Joint;
  			WeldJoint.prototype = create(WeldJoint._super.prototype);
  
  			/**
               * @typedef {Object} WeldJointDef
               *
               * Weld joint definition. You need to specify local anchor points where they are
               * attached and the relative body angle. The position of the anchor points is
               * important for computing the reaction torque.
               *
               * @prop {float} frequencyHz The mass-spring-damper frequency in Hertz. Rotation
               *       only. Disable softness with a value of 0.
               * @prop {float} dampingRatio The damping ratio. 0 = no damping, 1 = critical
               *       damping.
               *
               * @prop {Vec2} localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} localAnchorB The local anchor point relative to bodyB's origin.
               * @prop {float} referenceAngle The bodyB angle minus bodyA angle in the
               *       reference state (radians).
               */
  			var DEFAULTS = {
  				frequencyHz: 0.0,
  				dampingRatio: 0.0
  			};
  
  			/**
               * A weld joint essentially glues two bodies together. A weld joint may distort
               * somewhat because the island constraint solver is approximate.
               *
               * @param {WeldJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function WeldJoint (def, bodyA, bodyB, anchor) {
  				if (!(this instanceof WeldJoint)) {
  					return new WeldJoint(def, bodyA, bodyB, anchor);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = WeldJoint.TYPE;
  
  				this.m_localAnchorA = anchor ? bodyA.getLocalPoint(anchor) : def.localAnchorA || Vec2.zero();
  				this.m_localAnchorB = anchor ? bodyB.getLocalPoint(anchor) : def.localAnchorB || Vec2.zero();
  				this.m_referenceAngle = Math.isFinite(def.referenceAngle) ? def.referenceAngle : bodyB.getAngle() - bodyA.getAngle();
  
  				this.m_frequencyHz = def.frequencyHz;
  				this.m_dampingRatio = def.dampingRatio;
  
  				this.m_impulse = Vec3();
  
  				this.m_bias = 0.0;
  				this.m_gamma = 0.0;
  
  				// Solver temp
  				this.m_rA; // Vec2
  				this.m_rB; // Vec2
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  				this.m_mass = new Mat33();
  
  				// Point-to-point constraint
  				// C = p2 - p1
  				// Cdot = v2 - v1
  				// / = v2 + cross(w2, r2) - v1 - cross(w1, r1)
  				// J = [-I -r1_skew I r2_skew ]
  				// Identity used:
  				// w k % (rx i + ry j) = w * (-ry i + rx j)
  
  				// Angle constraint
  				// C = angle2 - angle1 - referenceAngle
  				// Cdot = w2 - w1
  				// J = [0 0 -1 0 0 1]
  				// K = invI1 + invI2
  			}
  
  			WeldJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					frequencyHz: this.m_frequencyHz,
  					dampingRatio: this.m_dampingRatio,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					referenceAngle: this.m_referenceAngle
  				};
  			};
  
  			WeldJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new WeldJoint(data);
  				return joint;
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			WeldJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			WeldJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * Get the reference angle.
               */
  			WeldJoint.prototype.getReferenceAngle = function () {
  				return this.m_referenceAngle;
  			};
  
  			/**
               * Set/get frequency in Hz.
               */
  			WeldJoint.prototype.setFrequency = function (hz) {
  				this.m_frequencyHz = hz;
  			};
  
  			WeldJoint.prototype.getFrequency = function () {
  				return this.m_frequencyHz;
  			};
  
  			/**
               * Set/get damping ratio.
               */
  			WeldJoint.prototype.setDampingRatio = function (ratio) {
  				this.m_dampingRatio = ratio;
  			};
  
  			WeldJoint.prototype.getDampingRatio = function () {
  				return this.m_dampingRatio;
  			};
  
  			WeldJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			WeldJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			WeldJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.neo(this.m_impulse.x, this.m_impulse.y).mul(inv_dt);
  			};
  
  			WeldJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * this.m_impulse.z;
  			};
  
  			WeldJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				this.m_rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				this.m_rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				// J = [-I -r1_skew I r2_skew]
  				// [ 0 -1 0 1]
  				// r_skew = [-ry; rx]
  
  				// Matlab
  				// K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
  				// [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
  				// [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var K = new Mat33();
  				K.ex.x = mA + mB + this.m_rA.y * this.m_rA.y * iA + this.m_rB.y * this.m_rB.y * iB;
  				K.ey.x = -this.m_rA.y * this.m_rA.x * iA - this.m_rB.y * this.m_rB.x * iB;
  				K.ez.x = -this.m_rA.y * iA - this.m_rB.y * iB;
  				K.ex.y = K.ey.x;
  				K.ey.y = mA + mB + this.m_rA.x * this.m_rA.x * iA + this.m_rB.x * this.m_rB.x * iB;
  				K.ez.y = this.m_rA.x * iA + this.m_rB.x * iB;
  				K.ex.z = K.ez.x;
  				K.ey.z = K.ez.y;
  				K.ez.z = iA + iB;
  
  				if (this.m_frequencyHz > 0.0) {
  					K.getInverse22(this.m_mass);
  
  					var invM = iA + iB; // float
  					var m = invM > 0.0 ? 1.0 / invM : 0.0; // float
  
  					var C = aB - aA - this.m_referenceAngle; // float
  
  					// Frequency
  					var omega = 2.0 * Math.PI * this.m_frequencyHz; // float
  
  					// Damping coefficient
  					var d = 2.0 * m * this.m_dampingRatio * omega; // float
  
  					// Spring stiffness
  					var k = m * omega * omega; // float
  
  					// magic formulas
  					var h = step.dt; // float
  					this.m_gamma = h * (d + h * k);
  					this.m_gamma = this.m_gamma != 0.0 ? 1.0 / this.m_gamma : 0.0;
  					this.m_bias = C * h * k * this.m_gamma;
  
  					invM += this.m_gamma;
  					this.m_mass.ez.z = invM != 0.0 ? 1.0 / invM : 0.0;
  				} else if (K.ez.z == 0.0) {
  					K.getInverse22(this.m_mass);
  					this.m_gamma = 0.0;
  					this.m_bias = 0.0;
  				} else {
  					K.getSymInverse33(this.m_mass);
  					this.m_gamma = 0.0;
  					this.m_bias = 0.0;
  				}
  
  				if (step.warmStarting) {
  					// Scale impulses to support a variable time step.
  					this.m_impulse.mul(step.dtRatio);
  
  					var P = Vec2.neo(this.m_impulse.x, this.m_impulse.y);
  
  					vA.subMul(mA, P);
  					wA -= iA * (Vec2.cross(this.m_rA, P) + this.m_impulse.z);
  
  					vB.addMul(mB, P);
  					wB += iB * (Vec2.cross(this.m_rB, P) + this.m_impulse.z);
  				} else {
  					this.m_impulse.setZero();
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			WeldJoint.prototype.solveVelocityConstraints = function (step) {
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				if (this.m_frequencyHz > 0.0) {
  					var Cdot2 = wB - wA; // float
  
  					var impulse2 = -this.m_mass.ez.z * (Cdot2 + this.m_bias + this.m_gamma * this.m_impulse.z); // float
  					this.m_impulse.z += impulse2;
  
  					wA -= iA * impulse2;
  					wB += iB * impulse2;
  
  					var Cdot1 = Vec2.zero();
  					Cdot1.addCombine(1, vB, 1, Vec2.cross(wB, this.m_rB));
  					Cdot1.subCombine(1, vA, 1, Vec2.cross(wA, this.m_rA)); // Vec2
  
  					var impulse1 = Vec2.neg(Mat33.mulVec2(this.m_mass, Cdot1)); // Vec2
  					this.m_impulse.x += impulse1.x;
  					this.m_impulse.y += impulse1.y;
  
  					var P = Vec2.clone(impulse1); // Vec2
  
  					vA.subMul(mA, P);
  					wA -= iA * Vec2.cross(this.m_rA, P);
  
  					vB.addMul(mB, P);
  					wB += iB * Vec2.cross(this.m_rB, P);
  				} else {
  					var Cdot1 = Vec2.zero();
  					Cdot1.addCombine(1, vB, 1, Vec2.cross(wB, this.m_rB));
  					Cdot1.subCombine(1, vA, 1, Vec2.cross(wA, this.m_rA)); // Vec2
  					var Cdot2 = wB - wA; // float
  					var Cdot = Vec3(Cdot1.x, Cdot1.y, Cdot2); // Vec3
  
  					var impulse = Vec3.neg(Mat33.mulVec3(this.m_mass, Cdot)); // Vec3
  					this.m_impulse.add(impulse);
  
  					var P = Vec2.neo(impulse.x, impulse.y);
  
  					vA.subMul(mA, P);
  					wA -= iA * (Vec2.cross(this.m_rA, P) + impulse.z);
  
  					vB.addMul(mB, P);
  					wB += iB * (Vec2.cross(this.m_rB, P) + impulse.z);
  				}
  
  				this.m_bodyA.c_velocity.v = vA;
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v = vB;
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			WeldJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  
  				var positionError, angularError; // float
  
  				var K = new Mat33();
  				K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB;
  				K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB;
  				K.ez.x = -rA.y * iA - rB.y * iB;
  				K.ex.y = K.ey.x;
  				K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB;
  				K.ez.y = rA.x * iA + rB.x * iB;
  				K.ex.z = K.ez.x;
  				K.ey.z = K.ez.y;
  				K.ez.z = iA + iB;
  
  				if (this.m_frequencyHz > 0.0) {
  					var C1 = Vec2.zero();
  					C1.addCombine(1, cB, 1, rB);
  					C1.subCombine(1, cA, 1, rA); // Vec2
  
  					positionError = C1.length();
  					angularError = 0.0;
  
  					var P = Vec2.neg(K.solve22(C1)); // Vec2
  
  					cA.subMul(mA, P);
  					aA -= iA * Vec2.cross(rA, P);
  
  					cB.addMul(mB, P);
  					aB += iB * Vec2.cross(rB, P);
  				} else {
  					var C1 = Vec2.zero();
  					C1.addCombine(1, cB, 1, rB);
  					C1.subCombine(1, cA, 1, rA);
  
  					var C2 = aB - aA - this.m_referenceAngle; // float
  
  					positionError = C1.length();
  					angularError = Math.abs(C2);
  
  					var C = Vec3(C1.x, C1.y, C2);
  
  					var impulse = Vec3();
  					if (K.ez.z > 0.0) {
  						impulse = Vec3.neg(K.solve33(C));
  					} else {
  						var impulse2 = Vec2.neg(K.solve22(C1));
  						impulse.set(impulse2.x, impulse2.y, 0.0);
  					}
  
  					var P = Vec2.neo(impulse.x, impulse.y);
  
  					cA.subMul(mA, P);
  					aA -= iA * (Vec2.cross(rA, P) + impulse.z);
  
  					cB.addMul(mB, P);
  					aB += iB * (Vec2.cross(rB, P) + impulse.z);
  				}
  
  				this.m_bodyA.c_position.c = cA;
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c = cB;
  				this.m_bodyB.c_position.a = aB;
  
  				return positionError <= Settings.linearSlop && angularError <= Settings.angularSlop;
  			};
  
  			/***/
  		},
  		/* 59 */
  		/***/ function (module, exports, __webpack_require__) {
  			/*
               * Copyright (c) 2016-2018 Ali Shakiba http://shakiba.me/planck.js
               * Copyright (c) 2006-2011 Erin Catto  http://www.box2d.org
               *
               * This software is provided 'as-is', without any express or implied
               * warranty.  In no event will the authors be held liable for any damages
               * arising from the use of this software.
               * Permission is granted to anyone to use this software for any purpose,
               * including commercial applications, and to alter it and redistribute it
               * freely, subject to the following restrictions:
               * 1. The origin of this software must not be misrepresented; you must not
               * claim that you wrote the original software. If you use this software
               * in a product, an acknowledgment in the product documentation would be
               * appreciated but is not required.
               * 2. Altered source versions must be plainly marked as such, and must not be
               * misrepresented as being the original software.
               * 3. This notice may not be removed or altered from any source distribution.
               */
  
  			var _DEBUG = false ? undefined : false;
  			var _ASSERT = false ? undefined : false;
  
  			module.exports = WheelJoint;
  
  			var options = __webpack_require__(7);
  			var create = __webpack_require__(6);
  			var Settings = __webpack_require__(4);
  
  			var Math = __webpack_require__(1);
  			var Vec2 = __webpack_require__(0);
  			var Vec3 = __webpack_require__(11);
  			var Mat22 = __webpack_require__(10);
  			var Mat33 = __webpack_require__(15);
  			var Rot = __webpack_require__(3);
  			var Sweep = __webpack_require__(9);
  			var Transform = __webpack_require__(5);
  			var Velocity = __webpack_require__(13);
  			var Position = __webpack_require__(14);
  
  			var Joint = __webpack_require__(12);
  			var Body = __webpack_require__(8);
  
  			WheelJoint.TYPE = 'wheel-joint';
  			Joint.TYPES[WheelJoint.TYPE] = WheelJoint;
  
  			WheelJoint._super = Joint;
  			WheelJoint.prototype = create(WheelJoint._super.prototype);
  
  			/**
               * @typedef {Object} WheelJointDef
               *
               * Wheel joint definition. This requires defining a line of motion using an axis
               * and an anchor point. The definition uses local anchor points and a local axis
               * so that the initial configuration can violate the constraint slightly. The
               * joint translation is zero when the local anchor points coincide in world
               * space. Using local anchors and a local axis helps when saving and loading a
               * game.
               *
               * @prop {boolean} enableMotor Enable/disable the joint motor.
               * @prop {float} maxMotorTorque The maximum motor torque, usually in N-m.
               * @prop {float} motorSpeed The desired motor speed in radians per second.
               * @prop {float} frequencyHz Suspension frequency, zero indicates no suspension.
               * @prop {float} dampingRatio Suspension damping ratio, one indicates critical
               *       damping.
               *
               * @prop {Vec2} localAnchorA The local anchor point relative to bodyA's origin.
               * @prop {Vec2} localAnchorB The local anchor point relative to bodyB's origin.
               * @prop {Vec2} localAxisA The local translation axis in bodyA.
               */
  			var DEFAULTS = {
  				enableMotor: false,
  				maxMotorTorque: 0.0,
  				motorSpeed: 0.0,
  				frequencyHz: 2.0,
  				dampingRatio: 0.7
  			};
  
  			/**
               * A wheel joint. This joint provides two degrees of freedom: translation along
               * an axis fixed in bodyA and rotation in the plane. In other words, it is a
               * point to line constraint with a rotational motor and a linear spring/damper.
               * This joint is designed for vehicle suspensions.
               *
               * @param {WheelJointDef} def
               * @param {Body} bodyA
               * @param {Body} bodyB
               */
  			function WheelJoint (def, bodyA, bodyB, anchor, axis) {
  				if (!(this instanceof WheelJoint)) {
  					return new WheelJoint(def, bodyA, bodyB, anchor, axis);
  				}
  
  				def = options(def, DEFAULTS);
  				Joint.call(this, def, bodyA, bodyB);
  				bodyA = this.m_bodyA;
  				bodyB = this.m_bodyB;
  
  				this.m_type = WheelJoint.TYPE;
  
  				this.m_localAnchorA = Vec2.clone(anchor ? bodyA.getLocalPoint(anchor) : def.localAnchorA || Vec2.zero());
  				this.m_localAnchorB = Vec2.clone(anchor ? bodyB.getLocalPoint(anchor) : def.localAnchorB || Vec2.zero());
  				this.m_localXAxisA = Vec2.clone(axis ? bodyA.getLocalVector(axis) : def.localAxisA || def.localAxis || Vec2.neo(1.0, 0.0));
  				this.m_localYAxisA = Vec2.cross(1.0, this.m_localXAxisA);
  
  				this.m_mass = 0.0;
  				this.m_impulse = 0.0;
  				this.m_motorMass = 0.0;
  				this.m_motorImpulse = 0.0;
  				this.m_springMass = 0.0;
  				this.m_springImpulse = 0.0;
  
  				this.m_maxMotorTorque = def.maxMotorTorque;
  				this.m_motorSpeed = def.motorSpeed;
  				this.m_enableMotor = def.enableMotor;
  
  				this.m_frequencyHz = def.frequencyHz;
  				this.m_dampingRatio = def.dampingRatio;
  
  				this.m_bias = 0.0;
  				this.m_gamma = 0.0;
  
  				// Solver temp
  				this.m_localCenterA; // Vec2
  				this.m_localCenterB; // Vec2
  				this.m_invMassA; // float
  				this.m_invMassB; // float
  				this.m_invIA; // float
  				this.m_invIB; // float
  
  				this.m_ax = Vec2.zero();
  				this.m_ay = Vec2.zero(); // Vec2
  				this.m_sAx;
  				this.m_sBx; // float
  				this.m_sAy;
  				this.m_sBy; // float
  
  				// Linear constraint (point-to-line)
  				// d = pB - pA = xB + rB - xA - rA
  				// C = dot(ay, d)
  				// Cdot = dot(d, cross(wA, ay)) + dot(ay, vB + cross(wB, rB) - vA - cross(wA,
  				// rA))
  				// = -dot(ay, vA) - dot(cross(d + rA, ay), wA) + dot(ay, vB) + dot(cross(rB,
  				// ay), vB)
  				// J = [-ay, -cross(d + rA, ay), ay, cross(rB, ay)]
  
  				// Spring linear constraint
  				// C = dot(ax, d)
  				// Cdot = = -dot(ax, vA) - dot(cross(d + rA, ax), wA) + dot(ax, vB) +
  				// dot(cross(rB, ax), vB)
  				// J = [-ax -cross(d+rA, ax) ax cross(rB, ax)]
  
  				// Motor rotational constraint
  				// Cdot = wB - wA
  				// J = [0 0 -1 0 0 1]
  			}
  
  			WheelJoint.prototype._serialize = function () {
  				return {
  					type: this.m_type,
  					bodyA: this.m_bodyA,
  					bodyB: this.m_bodyB,
  					collideConnected: this.m_collideConnected,
  
  					enableMotor: this.m_enableMotor,
  					maxMotorTorque: this.m_maxMotorTorque,
  					motorSpeed: this.m_motorSpeed,
  					frequencyHz: this.m_frequencyHz,
  					dampingRatio: this.m_dampingRatio,
  
  					localAnchorA: this.m_localAnchorA,
  					localAnchorB: this.m_localAnchorB,
  					localAxisA: this.m_localXAxisA
  				};
  			};
  
  			WheelJoint._deserialize = function (data, world, restore) {
  				data.bodyA = restore(Body, data.bodyA, world);
  				data.bodyB = restore(Body, data.bodyB, world);
  				var joint = new WheelJoint(data);
  				return joint;
  			};
  
  			/**
               * @internal
               */
  			WheelJoint.prototype._setAnchors = function (def) {
  				if (def.anchorA) {
  					this.m_localAnchorA.set(this.m_bodyA.getLocalPoint(def.anchorA));
  				} else if (def.localAnchorA) {
  					this.m_localAnchorA.set(def.localAnchorA);
  				}
  
  				if (def.anchorB) {
  					this.m_localAnchorB.set(this.m_bodyB.getLocalPoint(def.anchorB));
  				} else if (def.localAnchorB) {
  					this.m_localAnchorB.set(def.localAnchorB);
  				}
  
  				if (def.localAxisA) {
  					this.m_localXAxisA.set(def.localAxisA);
  					this.m_localYAxisA.set(Vec2.cross(1.0, def.localAxisA));
  				}
  			};
  
  			/**
               * The local anchor point relative to bodyA's origin.
               */
  			WheelJoint.prototype.getLocalAnchorA = function () {
  				return this.m_localAnchorA;
  			};
  
  			/**
               * The local anchor point relative to bodyB's origin.
               */
  			WheelJoint.prototype.getLocalAnchorB = function () {
  				return this.m_localAnchorB;
  			};
  
  			/**
               * The local joint axis relative to bodyA.
               */
  			WheelJoint.prototype.getLocalAxisA = function () {
  				return this.m_localXAxisA;
  			};
  
  			/**
               * Get the current joint translation, usually in meters.
               */
  			WheelJoint.prototype.getJointTranslation = function () {
  				var bA = this.m_bodyA;
  				var bB = this.m_bodyB;
  
  				var pA = bA.getWorldPoint(this.m_localAnchorA); // Vec2
  				var pB = bB.getWorldPoint(this.m_localAnchorB); // Vec2
  				var d = Vec2.sub(pB, pA); // Vec2
  				var axis = bA.getWorldVector(this.m_localXAxisA); // Vec2
  
  				var translation = Vec2.dot(d, axis); // float
  				return translation;
  			};
  
  			/**
               * Get the current joint translation speed, usually in meters per second.
               */
  			WheelJoint.prototype.getJointSpeed = function () {
  				var wA = this.m_bodyA.m_angularVelocity;
  				var wB = this.m_bodyB.m_angularVelocity;
  				return wB - wA;
  			};
  
  			/**
               * Is the joint motor enabled?
               */
  			WheelJoint.prototype.isMotorEnabled = function () {
  				return this.m_enableMotor;
  			};
  
  			/**
               * Enable/disable the joint motor.
               */
  			WheelJoint.prototype.enableMotor = function (flag) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_enableMotor = flag;
  			};
  
  			/**
               * Set the motor speed, usually in radians per second.
               */
  			WheelJoint.prototype.setMotorSpeed = function (speed) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_motorSpeed = speed;
  			};
  
  			/**
               * Get the motor speed, usually in radians per second.
               */
  			WheelJoint.prototype.getMotorSpeed = function () {
  				return this.m_motorSpeed;
  			};
  
  			/**
               * Set/Get the maximum motor force, usually in N-m.
               */
  			WheelJoint.prototype.setMaxMotorTorque = function (torque) {
  				this.m_bodyA.setAwake(true);
  				this.m_bodyB.setAwake(true);
  				this.m_maxMotorTorque = torque;
  			};
  
  			WheelJoint.prototype.getMaxMotorTorque = function () {
  				return this.m_maxMotorTorque;
  			};
  
  			/**
               * Get the current motor torque given the inverse time step, usually in N-m.
               */
  			WheelJoint.prototype.getMotorTorque = function (inv_dt) {
  				return inv_dt * this.m_motorImpulse;
  			};
  
  			/**
               * Set/Get the spring frequency in hertz. Setting the frequency to zero disables
               * the spring.
               */
  			WheelJoint.prototype.setSpringFrequencyHz = function (hz) {
  				this.m_frequencyHz = hz;
  			};
  
  			WheelJoint.prototype.getSpringFrequencyHz = function () {
  				return this.m_frequencyHz;
  			};
  
  			/**
               * Set/Get the spring damping ratio
               */
  			WheelJoint.prototype.setSpringDampingRatio = function (ratio) {
  				this.m_dampingRatio = ratio;
  			};
  
  			WheelJoint.prototype.getSpringDampingRatio = function () {
  				return this.m_dampingRatio;
  			};
  
  			WheelJoint.prototype.getAnchorA = function () {
  				return this.m_bodyA.getWorldPoint(this.m_localAnchorA);
  			};
  
  			WheelJoint.prototype.getAnchorB = function () {
  				return this.m_bodyB.getWorldPoint(this.m_localAnchorB);
  			};
  
  			WheelJoint.prototype.getReactionForce = function (inv_dt) {
  				return Vec2.combine(this.m_impulse, this.m_ay, this.m_springImpulse, this.m_ax).mul(inv_dt);
  			};
  
  			WheelJoint.prototype.getReactionTorque = function (inv_dt) {
  				return inv_dt * this.m_motorImpulse;
  			};
  
  			WheelJoint.prototype.initVelocityConstraints = function (step) {
  				this.m_localCenterA = this.m_bodyA.m_sweep.localCenter;
  				this.m_localCenterB = this.m_bodyB.m_sweep.localCenter;
  				this.m_invMassA = this.m_bodyA.m_invMass;
  				this.m_invMassB = this.m_bodyB.m_invMass;
  				this.m_invIA = this.m_bodyA.m_invI;
  				this.m_invIB = this.m_bodyB.m_invI;
  
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				// Compute the effective masses.
  				var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  				var d = Vec2.zero();
  				d.addCombine(1, cB, 1, rB);
  				d.subCombine(1, cA, 1, rA); // Vec2
  
  				// Point to line constraint
  				{
  					this.m_ay = Rot.mulVec2(qA, this.m_localYAxisA);
  					this.m_sAy = Vec2.cross(Vec2.add(d, rA), this.m_ay);
  					this.m_sBy = Vec2.cross(rB, this.m_ay);
  
  					this.m_mass = mA + mB + iA * this.m_sAy * this.m_sAy + iB * this.m_sBy * this.m_sBy;
  
  					if (this.m_mass > 0.0) {
  						this.m_mass = 1.0 / this.m_mass;
  					}
  				}
  
  				// Spring constraint
  				this.m_springMass = 0.0;
  				this.m_bias = 0.0;
  				this.m_gamma = 0.0;
  				if (this.m_frequencyHz > 0.0) {
  					this.m_ax = Rot.mulVec2(qA, this.m_localXAxisA);
  					this.m_sAx = Vec2.cross(Vec2.add(d, rA), this.m_ax);
  					this.m_sBx = Vec2.cross(rB, this.m_ax);
  
  					var invMass = mA + mB + iA * this.m_sAx * this.m_sAx + iB * this.m_sBx * this.m_sBx; // float
  
  					if (invMass > 0.0) {
  						this.m_springMass = 1.0 / invMass;
  
  						var C = Vec2.dot(d, this.m_ax); // float
  
  						// Frequency
  						var omega = 2.0 * Math.PI * this.m_frequencyHz; // float
  
  						// Damping coefficient
  						var d = 2.0 * this.m_springMass * this.m_dampingRatio * omega; // float
  
  						// Spring stiffness
  						var k = this.m_springMass * omega * omega; // float
  
  						// magic formulas
  						var h = step.dt; // float
  						this.m_gamma = h * (d + h * k);
  						if (this.m_gamma > 0.0) {
  							this.m_gamma = 1.0 / this.m_gamma;
  						}
  
  						this.m_bias = C * h * k * this.m_gamma;
  
  						this.m_springMass = invMass + this.m_gamma;
  						if (this.m_springMass > 0.0) {
  							this.m_springMass = 1.0 / this.m_springMass;
  						}
  					}
  				} else {
  					this.m_springImpulse = 0.0;
  				}
  
  				// Rotational motor
  				if (this.m_enableMotor) {
  					this.m_motorMass = iA + iB;
  					if (this.m_motorMass > 0.0) {
  						this.m_motorMass = 1.0 / this.m_motorMass;
  					}
  				} else {
  					this.m_motorMass = 0.0;
  					this.m_motorImpulse = 0.0;
  				}
  
  				if (step.warmStarting) {
  					// Account for variable time step.
  					this.m_impulse *= step.dtRatio;
  					this.m_springImpulse *= step.dtRatio;
  					this.m_motorImpulse *= step.dtRatio;
  
  					var P = Vec2.combine(this.m_impulse, this.m_ay, this.m_springImpulse, this.m_ax);
  					var LA = this.m_impulse * this.m_sAy + this.m_springImpulse * this.m_sAx + this.m_motorImpulse;
  					var LB = this.m_impulse * this.m_sBy + this.m_springImpulse * this.m_sBx + this.m_motorImpulse;
  
  					vA.subMul(this.m_invMassA, P);
  					wA -= this.m_invIA * LA;
  
  					vB.addMul(this.m_invMassB, P);
  					wB += this.m_invIB * LB;
  				} else {
  					this.m_impulse = 0.0;
  					this.m_springImpulse = 0.0;
  					this.m_motorImpulse = 0.0;
  				}
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			WheelJoint.prototype.solveVelocityConstraints = function (step) {
  				var mA = this.m_invMassA;
  				var mB = this.m_invMassB; // float
  				var iA = this.m_invIA;
  				var iB = this.m_invIB; // float
  
  				var vA = this.m_bodyA.c_velocity.v;
  				var wA = this.m_bodyA.c_velocity.w;
  				var vB = this.m_bodyB.c_velocity.v;
  				var wB = this.m_bodyB.c_velocity.w;
  
  				// Solve spring constraint
  				{
  					var Cdot = Vec2.dot(this.m_ax, vB) - Vec2.dot(this.m_ax, vA) + this.m_sBx * wB - this.m_sAx * wA; // float
  					var impulse = -this.m_springMass * (Cdot + this.m_bias + this.m_gamma * this.m_springImpulse); // float
  					this.m_springImpulse += impulse;
  
  					var P = Vec2.mul(impulse, this.m_ax); // Vec2
  					var LA = impulse * this.m_sAx; // float
  					var LB = impulse * this.m_sBx; // float
  
  					vA.subMul(mA, P);
  					wA -= iA * LA;
  
  					vB.addMul(mB, P);
  					wB += iB * LB;
  				}
  
  				// Solve rotational motor constraint
  				{
  					var Cdot = wB - wA - this.m_motorSpeed; // float
  					var impulse = -this.m_motorMass * Cdot; // float
  
  					var oldImpulse = this.m_motorImpulse; // float
  					var maxImpulse = step.dt * this.m_maxMotorTorque; // float
  					this.m_motorImpulse = Math.clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse);
  					impulse = this.m_motorImpulse - oldImpulse;
  
  					wA -= iA * impulse;
  					wB += iB * impulse;
  				}
  
  				// Solve point to line constraint
  				{
  					var Cdot = Vec2.dot(this.m_ay, vB) - Vec2.dot(this.m_ay, vA) + this.m_sBy * wB - this.m_sAy * wA; // float
  					var impulse = -this.m_mass * Cdot; // float
  					this.m_impulse += impulse;
  
  					var P = Vec2.mul(impulse, this.m_ay); // Vec2
  					var LA = impulse * this.m_sAy; // float
  					var LB = impulse * this.m_sBy; // float
  
  					vA.subMul(mA, P);
  					wA -= iA * LA;
  
  					vB.addMul(mB, P);
  					wB += iB * LB;
  				}
  
  				this.m_bodyA.c_velocity.v.set(vA);
  				this.m_bodyA.c_velocity.w = wA;
  				this.m_bodyB.c_velocity.v.set(vB);
  				this.m_bodyB.c_velocity.w = wB;
  			};
  
  			WheelJoint.prototype.solvePositionConstraints = function (step) {
  				var cA = this.m_bodyA.c_position.c;
  				var aA = this.m_bodyA.c_position.a;
  				var cB = this.m_bodyB.c_position.c;
  				var aB = this.m_bodyB.c_position.a;
  
  				var qA = Rot.neo(aA);
  				var qB = Rot.neo(aB);
  
  				var rA = Rot.mulVec2(qA, Vec2.sub(this.m_localAnchorA, this.m_localCenterA));
  				var rB = Rot.mulVec2(qB, Vec2.sub(this.m_localAnchorB, this.m_localCenterB));
  				var d = Vec2.zero();
  				d.addCombine(1, cB, 1, rB);
  				d.subCombine(1, cA, 1, rA);
  
  				var ay = Rot.mulVec2(qA, this.m_localYAxisA);
  
  				var sAy = Vec2.cross(Vec2.add(d, rA), ay); // float
  				var sBy = Vec2.cross(rB, ay); // float
  
  				var C = Vec2.dot(d, ay); // float
  
  				var k = this.m_invMassA + this.m_invMassB + this.m_invIA * this.m_sAy * this.m_sAy + this.m_invIB * this.m_sBy * this.m_sBy; // float
  
  				var impulse; // float
  				if (k != 0.0) {
  					impulse = -C / k;
  				} else {
  					impulse = 0.0;
  				}
  
  				var P = Vec2.mul(impulse, ay); // Vec2
  				var LA = impulse * sAy; // float
  				var LB = impulse * sBy; // float
  
  				cA.subMul(this.m_invMassA, P);
  				aA -= this.m_invIA * LA;
  				cB.addMul(this.m_invMassB, P);
  				aB += this.m_invIB * LB;
  
  				this.m_bodyA.c_position.c.set(cA);
  				this.m_bodyA.c_position.a = aA;
  				this.m_bodyB.c_position.c.set(cB);
  				this.m_bodyB.c_position.a = aB;
  
  				return Math.abs(C) <= Settings.linearSlop;
  			};
  
  			/***/
  		}
  		/******/
  	]
  );
  // # sourceMappingURL=planck.js.map
  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  	module.exports = planck;
  }
  