diff --git a/package-lock.json b/package-lock.json index afe7258..47d27a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -594,6 +594,172 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -632,6 +798,679 @@ } } }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + }, + "dependencies": { + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + } + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -897,6 +1736,16 @@ "pako": "~1.0.5" } }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, "buffer": { "version": "4.9.1", "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -932,11 +1781,6 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, - "bulma": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/bulma/-/bulma-0.7.2.tgz", - "integrity": "sha512-6JHEu8U/1xsyOst/El5ImLcZIiE2JFXgvrz8GGWbnDLwTNRPJzdAM0aoUM1Ns0avALcVb6KZz9NhzmU53dGDcQ==" - }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -998,6 +1842,12 @@ "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30000928", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000928.tgz", + "integrity": "sha512-aSpMWRXL6ZXNnzm8hgE4QDLibG5pVJ2Ujzsuj3icazlIkxXkPXtL+BWnMx6FBkWmkZgBHGUxPZQvrbRw2ZTxhg==", + "dev": true + }, "canvas": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.1.0.tgz", @@ -1266,6 +2116,15 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", @@ -1451,6 +2310,12 @@ } } }, + "core-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz", + "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1724,6 +2589,15 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -1857,6 +2731,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.3.103", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.103.tgz", + "integrity": "sha512-tObPqGmY9X8MUM8i3MEimYmbnLLf05/QV5gPlkR8MQ3Uj8G8B2govE1U4cQcBYtv3ymck9Y8cIOu4waoiykMZQ==", + "dev": true + }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -2089,6 +2969,62 @@ } } }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "express": { "version": "4.16.4", "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", @@ -2254,6 +3190,13 @@ "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", "dev": true }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -2348,6 +3291,16 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true, + "requires": { + "for-in": "^1.0.1" + } + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -2387,6 +3340,12 @@ "minipass": "^2.2.1" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -2985,6 +3944,44 @@ "path-is-absolute": "^1.0.0" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -3012,6 +4009,12 @@ "integrity": "sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==", "dev": true }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, "globby": { "version": "6.1.0", "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -3149,6 +4152,16 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -3415,6 +4428,15 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -3525,6 +4547,23 @@ } } }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -3537,6 +4576,15 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -3607,6 +4655,20 @@ "isobject": "^3.0.1" } }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -3767,6 +4829,15 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -3824,6 +4895,13 @@ "object-visit": "^1.0.0" } }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true, + "optional": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -4306,6 +5384,17 @@ "es-abstract": "^1.5.1" } }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -4398,6 +5487,17 @@ "os-tmpdir": "^1.0.0" } }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -4485,6 +5585,37 @@ "pbkdf2": "^3.0.3" } }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", @@ -4663,6 +5794,13 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, "pretty-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", @@ -4827,6 +5965,27 @@ "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", "dev": true }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "optional": true + } + } + }, "randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", @@ -4944,6 +6103,33 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -5017,6 +6203,15 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5761,6 +6956,12 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -5803,6 +7004,12 @@ "repeat-string": "^1.6.1" } }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -6001,6 +7208,12 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", @@ -6049,6 +7262,15 @@ "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", "dev": true }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 1d3f594..11bb9bb 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "canvas": "^2.1.0" }, "devDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.7.0", "copy-webpack-plugin": "^4.6.0", "css-loader": "^1.0.1", "html-loader": "^0.5.5", @@ -18,10 +20,16 @@ "webpack-cli": "^3.1.2", "webpack-dev-server": "^3.1.10" }, + "babel": { + "presets": [ + "env" + ] + }, + "sideEffects": false, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "display": "webpack-dev-server -d", - "train": "node --max-old-space-size=16192 scripts/train | tee outputs/train_$(date +\"%Y-%m-%d_%H-%M-%S\").log" + "train": "./node_modules/.bin/babel-node --max-old-space-size=16192 scripts/train | tee outputs/train_$(date +\"%Y-%m-%d_%H-%M-%S\").log" }, "repository": { "type": "git", diff --git a/scripts/train.js b/scripts/train.js index fe98c98..06d6e61 100644 --- a/scripts/train.js +++ b/scripts/train.js @@ -1,4 +1,4 @@ -var config = require('../src/js/config') +const { config } = require('../src/js/config'); const { HeadlessGame } = require('../src/js/game') diff --git a/src/index.js b/src/index.js index 45dcde7..091459f 100644 --- a/src/index.js +++ b/src/index.js @@ -4,4 +4,4 @@ window.config = require('./js/config') window.chooseQoute = chooseQoute window.Game = Game -module.exports = {Game} +export {Game} diff --git a/src/js/charts.js b/src/js/charts.js deleted file mode 100644 index 78d48bc..0000000 --- a/src/js/charts.js +++ /dev/null @@ -1,104 +0,0 @@ -var Charts = function () { - this.__constructor.apply(this, arguments); -} - -Charts.prototype.__constructor = function () {} - -Charts.prototype.collect = function (agents, n, chunkSize) { - if (n === undefined) n = 1 - if (chunkSize === undefined) chunkSize = 1 - var data = {} - - // collect data - var keys = Object.keys(agents[0].infos[0]) - for (const key of keys) { - if (key === 'x') continue - data[key] = [] - for (let i = 0; i < agents.length; i += n) { - const infos = agents[i].infos; - // var borderColor = "hsl("+agents[i].walkerhue+",45%,"+(100-15*agents[i].walker.health/config.walker_health)+"%)"; - // build dataset - var dataset = { - label: 'Agent ' + i, - data: [], - fill: false, - // borderColor - } - for (const info of infos) { - // a datapoint - dataset.data.push({ - x: info['x'], - y: info[key] - }) - } - - // take means? - var leftOver = dataset.data % chunkSize - dataset.data = _.chunk(dataset.data, 4) - .map(c => ({ - x: _.mean(_.map(c, 'x')), - y: _.mean(_.map(c, 'y')) - })) - if (leftOver) dataset.data.pop() - - data[key].push(dataset) - } - } - for (let i = 0; i < agents.length; i++) { - agents[i].infos = [] // empty it - } - - return data -} - -Charts.prototype.init = function (agents) { - - var data = this.collect(agents, 1, 10) - var div = document.getElementById('charts'); - - // make charts - this.charts = [] - for (const key in data) { - var canvas = document.createElement("canvas"); - div.appendChild(canvas) - var ctx = canvas.getContext('2d'); - var lineChart = new Chart(ctx, { - type: 'scatter', - data: { - datasets: data[key] - }, - options: { - title: { - text: key, - display: true - }, - scales: { - xAxes: [{ - type: 'linear', - position: 'bottom' - }] - } - } - }); - this.charts.push(lineChart) - } - -} - -Charts.prototype.update = function (agents) { - var data = this.collect(agents, 1, 10) - var maxLen = 10000 - for (const chart of this.charts) { - var newDatasets = data[chart.config.options.title.text] - chart.data.datasets.forEach((dataset) => { - var dat = newDatasets.filter(d => d.label == dataset.label)[0].data - dataset.data.push(...dat); - if (dataset.data.length > maxLen) dataset.data.splice(0, dataset.data.length - maxLen) - }); - chart.update(); - } -} - -module.exports = { - Charts -} diff --git a/src/js/config.js b/src/js/config.js index 104b333..02858a8 100644 --- a/src/js/config.js +++ b/src/js/config.js @@ -1,7 +1,7 @@ -module.exports = { +let config = { time_step: 60, simulation_fps: 60, - draw_fps: 30, + draw_fps: 0, velocity_iterations: 8, position_iterations: 3, max_zoom_factor: 130, @@ -15,3 +15,4 @@ module.exports = { min_leg_delta: 0, action_repeat: 4 }; +export {config} diff --git a/src/js/ddpg/ddpg.js b/src/js/ddpg/ddpg.js index c9622f9..366b3b1 100644 --- a/src/js/ddpg/ddpg.js +++ b/src/js/ddpg/ddpg.js @@ -314,7 +314,7 @@ class DDPG { } } -module.exports = { +export { logTfMemory, DDPG } diff --git a/src/js/ddpg/ddpg_agent.js b/src/js/ddpg/ddpg_agent.js index 53bfe7a..f0541f5 100644 --- a/src/js/ddpg/ddpg_agent.js +++ b/src/js/ddpg/ddpg_agent.js @@ -1,21 +1,19 @@ -const { - tf -} = require('./tf_import') -const AdaptiveParamNoiseSpec = require('./noise') -const PrioritizedMemory = require('./prioritized_memory') -const { +import { tf } from './tf_import' +import { AdaptiveParamNoiseSpec } from './noise'; +import { PrioritizedMemory } from './prioritized_memory'; +import { Actor, Critic, copyFromSave, copyModel -} = require('./models') -const { +} from './models' +import { DDPG, logTfMemory -} = require('./ddpg') -const { +} from './ddpg' +import { mean -} = require('../utils') +} from '../utils' function setMetric(name, value) { @@ -302,4 +300,4 @@ class DDPGAgent { }; -module.exports = DDPGAgent +export { DDPGAgent } diff --git a/src/js/ddpg/models.js b/src/js/ddpg/models.js index a47295d..56d29c7 100644 --- a/src/js/ddpg/models.js +++ b/src/js/ddpg/models.js @@ -270,7 +270,7 @@ class Critic { } }; -module.exports = { +export { Actor, Critic, copyFromSave, diff --git a/src/js/ddpg/noise.js b/src/js/ddpg/noise.js index 3e09098..48d28f6 100644 --- a/src/js/ddpg/noise.js +++ b/src/js/ddpg/noise.js @@ -39,4 +39,4 @@ class AdaptiveParamNoiseSpec { } }; -module.exports = AdaptiveParamNoiseSpec +export { AdaptiveParamNoiseSpec } diff --git a/src/js/ddpg/prioritized_memory.js b/src/js/ddpg/prioritized_memory.js index b03f283..9df64c7 100644 --- a/src/js/ddpg/prioritized_memory.js +++ b/src/js/ddpg/prioritized_memory.js @@ -237,4 +237,4 @@ for (let i=1; i < 64; i++){ } */ -module.exports = PrioritizedMemory +export { PrioritizedMemory } diff --git a/src/js/ddpg/tf_import.js b/src/js/ddpg/tf_import.js index 0603373..46190b7 100644 --- a/src/js/ddpg/tf_import.js +++ b/src/js/ddpg/tf_import.js @@ -1,9 +1,11 @@ -const tf = require('@tensorflow/tfjs') +import * as tf from '@tensorflow/tfjs'; if (typeof WEB === "undefined") { // Load the binding (note you may have to press enter in the terminal for some reason) + // import tfjsNodeGpu from '@tensorflow/tfjs-node-gpu'; + // import tfjsNode from '@tensorflow/tfjs-node'; // seem to need this as well for save? require('@tensorflow/tfjs-node-gpu'); require('@tensorflow/tfjs-node'); // seem to need this as well for save? } -module.exports = { +export { tf } diff --git a/src/js/floor.js b/src/js/floor.js index a1136a2..e394e19 100644 --- a/src/js/floor.js +++ b/src/js/floor.js @@ -1,4 +1,4 @@ -var b2 = require('../vendor/jsbox2d') +import { b2 } from '../vendor/jsbox2d'; function createFloor(world, max_floor_tiles) { var body_def = new b2.BodyDef(); @@ -32,4 +32,4 @@ function createFloor(world, max_floor_tiles) { return body; } -module.exports = createFloor +export { createFloor } diff --git a/src/js/game.js b/src/js/game.js index 832fcce..80abcd6 100644 --- a/src/js/game.js +++ b/src/js/game.js @@ -1,19 +1,16 @@ -const config = require('./config') -const { - Charts -} = require('./charts') -const { +import config from './config'; +import { tf -} = require('./ddpg//tf_import') -const { +} from './ddpg//tf_import' +import { randi -} = require('./utils') -const b2 = require('../vendor/jsbox2d') -const createFloor = require('./floor.js') -const DDPGAgent = require('./ddpg/ddpg_agent') -const { +} from './utils' +import { b2 } from '../vendor/jsbox2d'; +import { createFloor } from './floor.js'; +import {DDPGAgent} from './ddpg/ddpg_agent'; +import { Walker -} = require('./walker') +} from './walker' chooseQoute = function () { @@ -145,7 +142,7 @@ class Game extends HeadlessGame { } } -module.exports = { +export { Game, chooseQoute, HeadlessGame diff --git a/src/js/renderer.js b/src/js/renderer.js index 71179f6..3598ef5 100644 --- a/src/js/renderer.js +++ b/src/js/renderer.js @@ -181,6 +181,6 @@ class Renderer { return zoom; } } -module.exports = { +export { Renderer } diff --git a/src/js/utils.js b/src/js/utils.js index 4c5b3d4..63f28d3 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -35,7 +35,7 @@ function mean(array) { } -module.exports = { +export { deg2rad, randf, randi, diff --git a/src/js/walker.js b/src/js/walker.js index c5d1f7c..89fa191 100644 --- a/src/js/walker.js +++ b/src/js/walker.js @@ -1,14 +1,14 @@ // walker has fixed shapes and structures // shape definitions are in the constructor -const b2 = require('../vendor/jsbox2d') -const { +import { b2 } from '../vendor/jsbox2d'; +import { randf, deg2rad, clamp -} = require('./utils.js') -const { +} from './utils.js' +import { Renderer -} = require('./renderer') +} from './renderer' const STRENGTH = 2.2 const SPEED = 15 @@ -762,7 +762,7 @@ class Walker { } } -module.exports = { +export { Walker, randf } diff --git a/src/vendor/jsbox2d.js b/src/vendor/jsbox2d.js index e6aa5ad..7adefc1 100644 --- a/src/vendor/jsbox2d.js +++ b/src/vendor/jsbox2d.js @@ -1,2844 +1,2878 @@ /** https://github.com/kripken/box2d.js v2.3.1 */ -(function () { - var performance = { - now: function () { - return +new Date() +var performance = { + now: function () { + return +new Date() + } +} +Function.prototype._extend = function (parent) { + this.prototype.parent = parent; + for (var x in parent.prototype) { + if (!this.prototype[x]) { + this.prototype[x] = parent.prototype[x] } } - Function.prototype._extend = function (parent) { - this.prototype.parent = parent; - for (var x in parent.prototype) { - if (!this.prototype[x]) { - this.prototype[x] = parent.prototype[x] - } - } - }; - Function.prototype._implement = function (parent) { - return this._extend(parent) - }; - var b2Profiler = (function () { +}; +Function.prototype._implement = function (parent) { + return this._extend(parent) +}; +var b2Profiler = (function () { - function profileStruct(name, parent) { - this.name = name; - this.parent = parent; - this.children = {}; - this.startTime = 0; - this.elapsedTime = 0; - this.totalTime = 0; + function profileStruct(name, parent) { + this.name = name; + this.parent = parent; + this.children = {}; + this.startTime = 0; + this.elapsedTime = 0; + this.totalTime = 0; + this.running = false; + this.childrenCount = 0 + } + profileStruct.prototype = { + start: function () { + this.startTime = performance.now(); + this.running = true + }, + stop: function (reset) { + if (!this.running) { + return + } this.running = false; - this.childrenCount = 0 - } - profileStruct.prototype = { - start: function () { - this.startTime = performance.now(); - this.running = true - }, - stop: function (reset) { - if (!this.running) { - return - } - this.running = false; - this.elapsedTime += performance.now() - this.startTime; - if (reset) { - this.start() - } - for (var x in this.children) { - this.children[x].stop() - } - }, - reset: function (dontRun) { - if (!dontRun) { - this.running = true; - this.totalTime += this.elapsedTime; - this.start() - } - this.elapsedTime = 0; - for (var x in this.children) { - this.children[x].reset(true) - } + this.elapsedTime += performance.now() - this.startTime; + if (reset) { + this.start() } - }; - var profiles = []; - var root = new profileStruct("root"); - - function create(name, parent) { - if (!profiles) { - throw new Error("late profile creation not allowed") - } - var s = new profileStruct(name, parent || "root"); - profiles.push(s); - return s - } - - function destroy(profile) { - profile.childrenCount--; - delete profile.children[profile.name] - } - - function recursiveParentCheck(node, profile) { - if (node.name === profile.parent) { - return node - } - for (var x in node.children) { - var n; - if (n = recursiveParentCheck(node.children[x], profile)) { - return n - } - } - return null - } - - function init() { - while (profiles.length) { - var p = profiles.pop(); - if (!(p.parentNode = recursiveParentCheck(root, p))) { - profiles.unshift(p) - } else { - p.parentNode.children[p.name] = p; - p.parentNode.childrenCount++ - } - } - profiles = null - } - - function resetAll() { - root.reset(true) - } - return { - create: create, - destroy: destroy, - init: init, - reset: resetAll, - profileRoot: root - } - }()); - "use strict"; - var b2_maxFloat = Number.MAX_VALUE; - var b2_epsilon = 2.220446049250313e-16; - var b2_pi = Math.PI; - var b2_maxManifoldPoints = 2; - var b2_maxPolygonVertices = 8; - var b2_aabbExtension = 0.1; - var b2_aabbMultiplier = 2; - var b2_linearSlop = 0.005; - var b2_angularSlop = (2 / 180 * b2_pi); - var b2_polygonRadius = (2 * b2_linearSlop); - var b2_maxSubSteps = 8; - var b2_maxTOIContacts = 32; - var b2_velocityThreshold = 1; - var b2_maxLinearCorrection = 0.2; - var b2_maxAngularCorrection = (8 / 180 * b2_pi); - var b2_maxTranslation = 2; - var b2_maxTranslationSquared = (b2_maxTranslation * b2_maxTranslation); - var b2_maxRotation = (0.5 * b2_pi); - var b2_maxRotationSquared = (b2_maxRotation * b2_maxRotation); - var b2_baumgarte = 0.2; - var b2_toiBaugarte = 0.75; - var b2_timeToSleep = 0.5; - var b2_linearSleepTolerance = 0.01; - var b2_angularSleepTolerance = (2 / 180 * b2_pi); - - function b2Version(ma, mi, re) { - this.major = ma; - this.minor = mi; - this.revision = re - } - b2Version.prototype = { - toString: function () { - return this.major + "." + this.minor + "." + this.revision - } - }; - var b2_version = new b2Version(2, 3, 1); - "use strict"; - - function b2IsValid(x) { - return isFinite(x) && !isNaN(x) - } - var sqrtf = Math.sqrt; - var atan2f = Math.atan2; - var sinf = Math.sin; - var cosf = Math.cos; - var floorf = Math.floor; - var ceilf = Math.ceil; - var b2Sqrt = sqrtf; - var b2Atan2 = atan2f; - - function b2InvSqrt(x) { - return 1 / sqrtf(x) - } - - function b2Vec2(x, y) { - if (typeof (x) !== "undefined") { - this.x = x; - this.y = y - } else { - this.x = this.y = 0 - } - } - b2Vec2.prototype = { - Clone: function () { - return new b2Vec2(this.x, this.y) - }, - SetZero: function () { - this.x = 0; - this.y = 0; - return this - }, - Set: function (x_, y_) { - this.x = x_; - this.y = y_; - return this - }, - Assign: function (l) { - this.x = l.x; - this.y = l.y; - return this - }, - Negate: function () { - var v = new b2Vec2(); - v.Set(-this.x, -this.y); - return v - }, - get_i: function (i) { - switch (i) { - case 0: - return this.x; - case 1: - return this.y + for (var x in this.children) { + this.children[x].stop() } }, - set_i: function (i, v) { - switch (i) { - case 0: - return this.x = v; - case 1: - return this.y = v + reset: function (dontRun) { + if (!dontRun) { + this.running = true; + this.totalTime += this.elapsedTime; + this.start() } - }, - Add: function (v) { - this.x += v.x; - this.y += v.y; - return this - }, - Subtract: function (v) { - this.x -= v.x; - this.y -= v.y; - return this - }, - Multiply: function (a) { - this.x *= a; - this.y *= a; - return this - }, - Length: function () { - return b2Sqrt(this.x * this.x + this.y * this.y) - }, - LengthSquared: function () { - return this.x * this.x + this.y * this.y - }, - Normalize: function () { - var length = this.Length(); - if (length < b2_epsilon) { - return 0 - } - var invLength = 1 / length; - this.x *= invLength; - this.y *= invLength; - return length - }, - IsValid: function () { - return b2IsValid(this.x) && b2IsValid(this.y) - }, - Skew: function () { - return new b2Vec2(-this.y, this.x) - }, - _serialize: function (out) { - var obj = out || []; - obj[0] = this.x; - obj[1] = this.y; - return obj - }, - _deserialize: function (data) { - this.x = data[0]; - this.y = data[1] - } - }; - b2Vec2.Add = function (a, b) { - return new b2Vec2(a.x + b.x, a.y + b.y) - }; - b2Vec2.Subtract = function (a, b) { - return new b2Vec2(a.x - b.x, a.y - b.y) - }; - b2Vec2.Equals = function (a, b) { - return a.x == b.x && a.y == b.y - }; - b2Vec2.Multiply = function (s, a) { - return new b2Vec2(s * a.x, s * a.y) - }; - b2Vec2.Negate = function (a) { - return new b2Vec2(-a.x, -a.y) - }; - - function b2Vec3(x, y, z) { - if (typeof (x) !== "undefined") { - this.x = x; - this.y = y; - this.z = z - } - } - b2Vec3.prototype = { - Clone: function () { - return new b2Vec3(this.x, this.y, this.z) - }, - SetZero: function () { - this.x = 0; - this.y = 0; - this.z = 0 - }, - Set: function (x_, y_, z_) { - this.x = x_; - this.y = y_; - this.z = z_ - }, - Negate: function () { - var v = new b2Vec3(); - v.Set(-this.x, -this.y, -this.z); - return v - }, - Add: function (v) { - this.x += v.x; - this.y += v.y; - this.z += v.z - }, - Subtract: function (v) { - this.x -= v.x; - this.y -= v.y; - this.z -= v.z - }, - Multiply: function (s) { - this.x *= s; - this.y *= s; - this.z *= s - }, - x: 0, - y: 0, - z: 0 - }; - b2Vec3.Multiply = function (s, a) { - return new b2Vec3(s * a.x, s * a.y, s * a.z) - }; - b2Vec3.Add = function (a, b) { - return new b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z) - }; - b2Vec3.Subtract = function (a, b) { - return new b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z) - }; - - function b2Mat22(c1, c2) { - this.ex = c1 ? c1.Clone() : new b2Vec2(); - this.ey = c2 ? c2.Clone() : new b2Vec2() - } - b2Mat22.prototype = { - Set: function (c1, c2) { - this.ex.Assign(c1); - this.ey.Assign(c2) - }, - Assign: function (mat) { - this.ex.Assign(mat.ex); - this.ey.Assign(mat.ey) - }, - SetIdentity: function () { - this.ex.x = 1; - this.ey.x = 0; - this.ex.y = 0; - this.ey.y = 1 - }, - SetZero: function () { - this.ex.x = 0; - this.ey.x = 0; - this.ex.y = 0; - this.ey.y = 0 - }, - GetInverse: function () { - var a = this.ex.x, - b = this.ey.x, - c = this.ex.y, - d = this.ey.y; - var B = new b2Mat22(); - var det = a * d - b * c; - if (det != 0) { - det = 1 / det - } - B.ex.x = det * d; - B.ey.x = -det * b; - B.ex.y = -det * c; - B.ey.y = det * a; - return B - }, - Solve: function (b) { - var a11 = this.ex.x, - a12 = this.ey.x, - a21 = this.ex.y, - a22 = this.ey.y; - var det = a11 * a22 - a12 * a21; - if (det != 0) { - det = 1 / det - } - var x = new b2Vec2(); - x.x = det * (a22 * b.x - a12 * b.y); - x.y = det * (a11 * b.y - a21 * b.x); - return x - } - }; - b2Mat22.Add = function (A, B) { - return new b2Mat22(b2Vec2.Add(A.ex, B.ex), b2Vec2.Add(A.ey, B.ey)) - }; - - function b2Mat33(c1, c2, c3) { - this.ex = c1 ? c1.Clone() : new b2Vec3(); - this.ey = c2 ? c2.Clone() : new b2Vec3(); - this.ez = c3 ? c3.Clone() : new b2Vec3() - } - b2Mat33.prototype = { - SetZero: function () { - this.ex.SetZero(); - this.ey.SetZero(); - this.ez.SetZero() - }, - Solve33: function (b) { - var det = b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, this.ez)); - if (det != 0) { - det = 1 / det - } - var x = new b2Vec3(); - x.x = det * b2Dot_v3_v3(b, b2Cross_v3_v3(this.ey, this.ez)); - x.y = det * b2Dot_v3_v3(this.ex, b2Cross_v3_v3(b, this.ez)); - x.z = det * b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, b)); - return x - }, - Solve22: function (b) { - var a11 = this.ex.x, - a12 = this.ey.x, - a21 = this.ex.y, - a22 = this.ey.y; - var det = a11 * a22 - a12 * a21; - if (det != 0) { - det = 1 / det - } - var x = new b2Vec2(); - x.x = det * (a22 * b.x - a12 * b.y); - x.y = det * (a11 * b.y - a21 * b.x); - return x - }, - GetInverse22: function (M) { - var a = this.ex.x, - b = this.ey.x, - c = this.ex.y, - d = this.ey.y; - var det = a * d - b * c; - if (det != 0) { - det = 1 / det - } - M.ex.x = det * d; - M.ey.x = -det * b; - M.ex.z = 0; - M.ex.y = -det * c; - M.ey.y = det * a; - M.ey.z = 0; - M.ez.x = 0; - M.ez.y = 0; - M.ez.z = 0 - }, - GetSymInverse33: function (M) { - var det = b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, this.ez)); - if (det != 0) { - det = 1 / det - } - var a11 = this.ex.x, - a12 = this.ey.x, - a13 = this.ez.x; - var a22 = this.ey.y, - 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) - } - }; - - function b2Rot(angle, c) { - if (typeof (c) !== "undefined") { - this.s = angle; - this.c = c - } else { - if (typeof (angle) !== "undefined") { - this.Set(angle) + this.elapsedTime = 0; + for (var x in this.children) { + this.children[x].reset(true) } } - } - b2Rot.prototype = { - Clone: function () { - return new b2Rot(this.s, this.c) - }, - Assign: function (l) { - this.s = l.s; - this.c = l.c - }, - Set: function (x) { - this.s = sinf(x); - this.c = cosf(x) - }, - SetIdentity: function () { - this.s = 0; - this.c = 1 - }, - GetAngle: function () { - return b2Atan2(this.s, this.c) - }, - GetXAxis: function () { - return new b2Vec2(this.c, this.s) - }, - GetYAxis: function () { - return new b2Vec2(-this.s, this.c) - }, - s: 0, - c: 1 }; + var profiles = []; + var root = new profileStruct("root"); - function b2Transform(position, rotation) { - this.p = new b2Vec2(); - this.q = new b2Rot(); - if (position) { - this.p.Assign(position); - this.q.Assign(rotation) + function create(name, parent) { + if (!profiles) { + throw new Error("late profile creation not allowed") } + var s = new profileStruct(name, parent || "root"); + profiles.push(s); + return s } - b2Transform.prototype = { - Clone: function () { - var xf = new b2Transform(this.p, this.q); - return xf - }, - Assign: function (xf) { - this.p.Assign(xf.p); - this.q.Assign(xf.q) - }, - SetIdentity: function () { - this.p.SetZero(); - this.q.SetIdentity() - }, - Set: function (position, angle) { - this.p.Assign(position); - this.q.Set(angle) + + function destroy(profile) { + profile.childrenCount--; + delete profile.children[profile.name] + } + + function recursiveParentCheck(node, profile) { + if (node.name === profile.parent) { + return node } - }; - - function b2Sweep() { - this.localCenter = new b2Vec2(); - this.c0 = new b2Vec2(); - this.c = new b2Vec2() - } - b2Sweep.prototype = { - Assign: function (sweep) { - this.localCenter.Assign(sweep.localCenter); - this.c0.Assign(sweep.c0); - this.c.Assign(sweep.c); - this.a = sweep.a; - this.a0 = sweep.a0; - this.alpha0 = sweep.alpha0 - }, - Clone: function () { - var sweep = new b2Sweep(); - sweep.localCenter.Assign(this.localCenter); - sweep.c0.Assign(this.c0); - sweep.c.Assign(this.c); - sweep.a = this.a; - sweep.a0 = this.a0; - sweep.alpha0 = this.alpha0; - return sweep - }, - GetTransform: function (xf, beta) { - xf.p.x = ((1 - beta) * this.c0.x) + (beta * this.c.x); - xf.p.y = ((1 - beta) * this.c0.y) + (beta * this.c.y); - var angle = (1 - beta) * this.a0 + beta * this.a; - xf.q.Set(angle); - xf.p.x -= xf.q.c * this.localCenter.x - xf.q.s * this.localCenter.y; - xf.p.y -= xf.q.s * this.localCenter.x + xf.q.c * this.localCenter.y - }, - Advance: function (alpha) { - var beta = (alpha - this.alpha0) / (1 - this.alpha0); - this.c0.Add(b2Vec2.Multiply(beta, b2Vec2.Subtract(this.c, this.c0))); - this.a0 += beta * (this.a - this.a0); - this.alpha0 = alpha - }, - Normalize: function () { - var twoPi = 2 * b2_pi; - var d = twoPi * floorf(this.a0 / twoPi); - this.a0 -= d; - this.a -= d - }, - a0: 0, - a: 0, - alpha0: 0 - }; - - function b2Dot_v2_v2(a, b) { - return a.x * b.x + a.y * b.y - } - - function b2Cross_v2_v2(a, b) { - return a.x * b.y - a.y * b.x - } - - function b2Cross_v2_f(a, s) { - return new b2Vec2(s * a.y, -s * a.x) - } - - function b2Cross_f_v2(s, a) { - return new b2Vec2(-s * a.y, s * a.x) - } - - function b2Mul_m22_v2(A, v) { - return new b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y) - } - - function b2MulT_m22_v2(A, v) { - return new b2Vec2(b2Dot_v2_v2(v, A.ex), b2Dot_v2_v2(v, A.ey)) - } - - function b2Distance(a, b) { - var c = b2Vec2.Subtract(a, b); - return c.Length() - } - - function b2DistanceSquared(a, b) { - var c = b2Vec2.Subtract(a, b); - return b2Dot_v2_v2(c, c) - } - - function b2Dot_v3_v3(a, b) { - return a.x * b.x + a.y * b.y + a.z * b.z - } - - function b2Cross_v3_v3(a, b) { - return new b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x) - } - - function b2Mul_m22_m22(A, B) { - return new b2Mat22(b2Mul_m22_v2(A, B.ex), b2Mul_m22_v2(A, B.ey)) - } - - function b2MulT_m22_m22(A, B) { - var c1 = new b2Vec2(b2Dot_v2_v2(A.ex, B.ex), b2Dot_v2_v2(A.ey, B.ex)); - var c2 = new b2Vec2(b2Dot_v2_v2(A.ex, B.ey), b2Dot_v2_v2(A.ey, B.ey)); - return new b2Mat22(c1, c2) - } - - function b2Mul_m33_v3(A, v) { - return b2Vec3.Add(b2Vec3.Add(b2Vec3.Multiply(v.x, A.ex), b2Vec3.Multiply(v.y, A.ey)), b2Vec3.Multiply(v.z, A.ez)) - } - - function b2Mul22_m33_v2(A, v) { - return new b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y) - } - - function b2Mul_r_r(q, r) { - var qr = new b2Rot(); - qr.s = q.s * r.c + q.c * r.s; - qr.c = q.c * r.c - q.s * r.s; - return qr - } - - function b2MulT_r_r(q, r) { - var qr = new b2Rot(); - qr.s = q.c * r.s - q.s * r.c; - qr.c = q.c * r.c + q.s * r.s; - return qr - } - - function b2Mul_r_v2(q, v) { - return new b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y) - } - - function b2MulT_r_v2(q, v) { - return new b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y) - } - - function b2Mul_t_v2(T, v) { - return new b2Vec2((T.q.c * v.x - T.q.s * v.y) + T.p.x, (T.q.s * v.x + T.q.c * v.y) + T.p.y) - } - - function b2MulT_t_v2(T, v) { - var px = v.x - T.p.x; - var py = v.y - T.p.y; - var x = (T.q.c * px + T.q.s * py); - var y = (-T.q.s * px + T.q.c * py); - return new b2Vec2(x, y) - } - - function b2Mul_t_t(A, B) { - var C = new b2Transform(); - C.q = b2Mul_r_r(A.q, B.q); - C.p = b2Vec2.Add(b2Mul_r_v2(A.q, B.p), A.p); - return C - } - - function b2MulT_t_t(A, B) { - var C = new b2Transform(); - C.q = b2MulT_r_r(A.q, B.q); - var tvx = B.p.x - A.p.x; - var tvy = B.p.y - A.p.y; - C.p.x = A.q.c * tvx + A.q.s * tvy; - C.p.y = -A.q.s * tvx + A.q.c * tvy; - return C - } - var b2Abs = Math.abs; - - function b2Abs_v2(a) { - return new b2Vec2(b2Abs(a.x), b2Abs(a.y)) - } - - function b2Abs_m22(A) { - return new b2Mat22(b2Abs_v2(A.ex), b2Abs_v2(A.ey)) - } - var b2Min = Math.min; - - function b2Min_v2(a, b) { - return new b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)) - } - var b2Max = Math.max; - - function b2Max_v2(a, b) { - return new b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)) - } - - function b2Clamp(a, low, high) { - return b2Max(low, b2Min(a, high)) - } - - function b2Clamp_v2(a, low, high) { - return b2Max_v2(low, b2Min_v2(a, high)) - } - - function b2NextPowerOfTwo(x) { - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return x + 1 - } - - function b2IsPowerOfTwo(x) { - var result = x > 0 && (x & (x - 1)) == 0; - return result - } - var RAND_LIMIT = 32767; - - function b2RandomFloat(lo, hi) { - var r = Math.random(); - if (typeof (lo) !== "undefined") { - r = (hi - lo) * r + lo - } else { - r = 2 * r - 1 - } - return r - } - "use strict"; - - function b2Color(r, g, b) { - this.r = r || 0; - this.g = g || 0; - this.b = b || 0 - } - b2Color.prototype = { - Set: function (r, g, b) { - this.r = r; - this.g = g; - this.b = b - } - }; - - function b2Draw() {} - b2Draw.prototype = { - SetFlags: function (flags) { - this.m_drawFlags = flags - }, - GetFlags: function () { - return this.m_drawFlags - }, - AppendFlags: function (flags) { - this.m_drawFlags |= flags - }, - ClearFlags: function (flags) { - this.m_drawFlags &= ~flags - }, - ToggleFlags: function (flags) { - this.m_drawFlags ^= flags - }, - DrawPolygon: function (vertices, vertexCount, color) {}, - DrawSolidPolygon: function (vertices, vertexCount, color) {}, - DrawCircle: function (center, radius, color) {}, - DrawSolidCircle: function (center, radius, axis, color) {}, - DrawSegment: function (p1, p2, color) {}, - DrawTransform: function (xf) {}, - m_drawFlags: 0 - }; - b2Draw.e_shapeBit = 1; - b2Draw.e_jointBit = 2; - b2Draw.e_aabbBit = 4; - b2Draw.e_centerOfMassBit = 8; - b2Draw.e_contactPoints = 16; - b2Draw.e_contactNormals = 32; - b2Draw.e_contactImpulses = 64; - b2Draw.e_frictionImpulses = 128; - b2Draw.e_statistics = 256; - b2Draw.e_profile = 512; - b2Draw.e_pairBit = 1024; - - "use strict"; - function b2Timer() { - this.Reset() - } - b2Timer.prototype = { - Reset: function () { - this.m_start = performance.now() - }, - GetMilliseconds: function () { - return performance.now() - this.m_start - } - }; - "use strict"; - - function b2MassData() { - this.mass = 0; - this.center = new b2Vec2(); - this.I = 0 - } - - function b2Shape() { - this.m_type = 0; - this.m_radius = 0 - } - b2Shape.prototype = { - Clone: function () {}, - GetType: function () { - return this.m_type - }, - GetChildCount: function () {}, - TestPoint: function (xf, p) {}, - RayCast: function (output, input, transform, childIndex) {}, - ComputeAABB: function (aabb, xf, childIndex) {}, - ComputeMass: function (massData, density) {}, - _serialize: function (out) { - var obj = out || {}; - obj.m_type = this.m_type; - obj.m_radius = this.m_radius; - return obj - }, - _deserialize: function (data) { - this.m_radius = data.m_radius - } - }; - b2Shape.e_circle = 0; - b2Shape.e_edge = 1; - b2Shape.e_polygon = 2; - b2Shape.e_chain = 3; - b2Shape.e_typeCount = 4; - "use strict"; - - function b2CircleShape() { - this.parent.call(this); - this.m_type = b2Shape.e_circle; - this.m_radius = 0; - this.m_p = new b2Vec2(); - Object.seal(this) - } - b2CircleShape.prototype = { - Clone: function () { - var shape = new b2CircleShape(); - shape.m_radius = this.m_radius; - shape.m_p = this.m_p.Clone(); - return shape - }, - GetChildCount: function () { - return 1 - }, - TestPoint: function (transform, p) { - var center = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); - var d = b2Vec2.Subtract(p, center); - return b2Dot_v2_v2(d, d) <= this.m_radius * this.m_radius - }, - RayCast: function (output, input, transform, childIndex) { - var position = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); - var s = b2Vec2.Subtract(input.p1, position); - var b = b2Dot_v2_v2(s, s) - this.m_radius * this.m_radius; - var r = b2Vec2.Subtract(input.p2, input.p1); - var c = b2Dot_v2_v2(s, r); - var rr = b2Dot_v2_v2(r, r); - var sigma = c * c - rr * b; - if (sigma < 0 || rr < b2_epsilon) { - return false + for (var x in node.children) { + var n; + if (n = recursiveParentCheck(node.children[x], profile)) { + return n } - var a = -(c + b2Sqrt(sigma)); - if (0 <= a && a <= input.maxFraction * rr) { - a /= rr; - output.fraction = a; - output.normal = b2Vec2.Add(s, b2Vec2.Multiply(a, r)); - output.normal.Normalize(); - return true - } - return false - }, - ComputeAABB: function (aabb, transform, childIndex) { - var px = transform.p.x + (transform.q.c * this.m_p.x - transform.q.s * this.m_p.y); - var py = transform.p.y + (transform.q.s * this.m_p.x + transform.q.c * this.m_p.y); - aabb.lowerBound.x = px - this.m_radius; - aabb.lowerBound.y = py - this.m_radius; - aabb.upperBound.x = px + this.m_radius; - aabb.upperBound.y = py + this.m_radius - }, - ComputeMass: function (massData, density) { - massData.mass = density * b2_pi * this.m_radius * this.m_radius; - massData.center = this.m_p; - massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + b2Dot_v2_v2(this.m_p, this.m_p)) - }, - GetSupport: function (d) { - return 0 - }, - GetSupportVertex: function (d) { - return this.m_p - }, - GetVertexCount: function () { - return 1 - }, - GetVertex: function (index) { - return this.m_p - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.m_p = this.m_p._serialize(); - return obj - }, - _deserialize: function (data) { - this.parent.prototype._deserialize.call(this, data); - this.m_p._deserialize(data.m_p) } - }; - b2CircleShape._extend(b2Shape); - "use strict"; - - function b2EdgeShape() { - this.parent.call(this); - this.m_type = b2Shape.e_edge; - this.m_radius = b2_polygonRadius; - this.m_vertex0 = new b2Vec2(); - this.m_vertex1 = new b2Vec2(); - this.m_vertex2 = new b2Vec2(); - this.m_vertex3 = new b2Vec2(); - this.m_hasVertex0 = false; - this.m_hasVertex3 = false; - Object.seal(this) + return null } - b2EdgeShape.prototype = { - Set: function (v1, v2) { - this.m_vertex1.Assign(v1); - this.m_vertex2.Assign(v2); - this.m_hasVertex0 = false; - this.m_hasVertex3 = false - }, - Clone: function () { - var shape = new b2EdgeShape(); - shape.m_vertex0 = this.m_vertex0.Clone(); - shape.m_vertex1 = this.m_vertex1.Clone(); - shape.m_vertex2 = this.m_vertex2.Clone(); - shape.m_vertex3 = this.m_vertex3.Clone(); - shape.m_hasVertex0 = this.m_hasVertex0; - shape.m_hasVertex3 = this.m_hasVertex3; - return shape - }, - GetChildCount: function () { - return 1 - }, - TestPoint: function (transform, p) { - return false - }, - RayCast: function (output, input, xf, childIndex) { - var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); - var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); - var d = b2Vec2.Subtract(p2, p1); - var v1 = this.m_vertex1; - var v2 = this.m_vertex2; - var e = b2Vec2.Subtract(v2, v1); - var normal = new b2Vec2(e.y, -e.x); - normal.Normalize(); - var numerator = b2Dot_v2_v2(normal, b2Vec2.Subtract(v1, p1)); - var denominator = b2Dot_v2_v2(normal, d); - if (denominator == 0) { - return false - } - var t = numerator / denominator; - if (t < 0 || input.maxFraction < t) { - return false - } - var q = b2Vec2.Add(p1, b2Vec2.Multiply(t, d)); - var r = b2Vec2.Subtract(v2, v1); - var rr = b2Dot_v2_v2(r, r); - if (rr == 0) { - return false - } - var s = b2Dot_v2_v2(b2Vec2.Subtract(q, v1), r) / rr; - if (s < 0 || 1 < s) { - return false - } - output.fraction = t; - if (numerator > 0) { - output.normal = b2Mul_r_v2(xf.q, normal).Negate() + + function init() { + while (profiles.length) { + var p = profiles.pop(); + if (!(p.parentNode = recursiveParentCheck(root, p))) { + profiles.unshift(p) } else { - output.normal = b2Mul_r_v2(xf.q, normal) - } - return true - }, - ComputeAABB: function (aabb, xf, childIndex) { - var v1x = (xf.q.c * this.m_vertex1.x - xf.q.s * this.m_vertex1.y) + xf.p.x; - var v1y = (xf.q.s * this.m_vertex1.x + xf.q.c * this.m_vertex1.y) + xf.p.y; - var v2x = (xf.q.c * this.m_vertex2.x - xf.q.s * this.m_vertex2.y) + xf.p.x; - var v2y = (xf.q.s * this.m_vertex2.x + xf.q.c * this.m_vertex2.y) + xf.p.y; - var lowerx = b2Min(v1x, v2x); - var lowery = b2Min(v1y, v2y); - var upperx = b2Max(v1x, v2x); - var uppery = b2Max(v1y, v2y); - aabb.lowerBound.x = lowerx - this.m_radius; - aabb.lowerBound.y = lowery - this.m_radius; - aabb.upperBound.x = upperx + this.m_radius; - aabb.upperBound.y = uppery + this.m_radius - }, - ComputeMass: function (massData, density) { - massData.mass = 0; - massData.center = b2Vec2.Multiply(0.5, b2Vec2.Add(this.m_vertex1, this.m_vertex2)); - massData.I = 0 - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.m_vertex1 = this.m_vertex1._serialize(); - obj.m_vertex2 = this.m_vertex2._serialize(); - obj.m_hasVertex0 = this.m_hasVertex0; - if (this.m_hasVertex0) { - obj.m_vertex0 = this.m_vertex0._serialize() - } - obj.m_hasVertex3 = this.m_hasVertex3; - if (this.m_hasVertex3) { - obj.m_vertex3 = this.m_vertex3._serialize() - } - return obj - }, - _deserialize: function (data) { - this.parent.prototype._deserialize.call(this, data); - this.m_vertex1._deserialize(data.m_vertex1); - this.m_vertex2._deserialize(data.m_vertex2); - this.m_hasVertex0 = data.m_hasVertex0; - if (this.m_hasVertex0) { - this.m_vertex0._deserialize(data.m_vertex0) - } - this.m_hasVertex3 = data.m_hasVertex3; - if (this.m_hasVertex3) { - this.m_vertex3._deserialize(data.m_vertex3) + p.parentNode.children[p.name] = p; + p.parentNode.childrenCount++ } } - }; - b2EdgeShape._extend(b2Shape); - "use strict"; + profiles = null + } - function b2ChainShape() { - this.parent.call(this); - this.m_type = b2Shape.e_chain; - this.m_radius = b2_polygonRadius; - this.m_vertices = null; - this.m_count = 0; - this.m_prevVertex = new b2Vec2(); - this.m_nextVertex = new b2Vec2(); + function resetAll() { + root.reset(true) + } + return { + create: create, + destroy: destroy, + init: init, + reset: resetAll, + profileRoot: root + } +}()); +"use strict"; +var b2_maxFloat = Number.MAX_VALUE; +var b2_epsilon = 2.220446049250313e-16; +var b2_pi = Math.PI; +var b2_maxManifoldPoints = 2; +var b2_maxPolygonVertices = 8; +var b2_aabbExtension = 0.1; +var b2_aabbMultiplier = 2; +var b2_linearSlop = 0.005; +var b2_angularSlop = (2 / 180 * b2_pi); +var b2_polygonRadius = (2 * b2_linearSlop); +var b2_maxSubSteps = 8; +var b2_maxTOIContacts = 32; +var b2_velocityThreshold = 1; +var b2_maxLinearCorrection = 0.2; +var b2_maxAngularCorrection = (8 / 180 * b2_pi); +var b2_maxTranslation = 2; +var b2_maxTranslationSquared = (b2_maxTranslation * b2_maxTranslation); +var b2_maxRotation = (0.5 * b2_pi); +var b2_maxRotationSquared = (b2_maxRotation * b2_maxRotation); +var b2_baumgarte = 0.2; +var b2_toiBaugarte = 0.75; +var b2_timeToSleep = 0.5; +var b2_linearSleepTolerance = 0.01; +var b2_angularSleepTolerance = (2 / 180 * b2_pi); + +function b2Version(ma, mi, re) { + this.major = ma; + this.minor = mi; + this.revision = re +} +b2Version.prototype = { + toString: function () { + return this.major + "." + this.minor + "." + this.revision + } +}; +var b2_version = new b2Version(2, 3, 1); +"use strict"; + +function b2IsValid(x) { + return isFinite(x) && !isNaN(x) +} +var sqrtf = Math.sqrt; +var atan2f = Math.atan2; +var sinf = Math.sin; +var cosf = Math.cos; +var floorf = Math.floor; +var ceilf = Math.ceil; +var b2Sqrt = sqrtf; +var b2Atan2 = atan2f; + +function b2InvSqrt(x) { + return 1 / sqrtf(x) +} + +function b2Vec2(x, y) { + if (typeof (x) !== "undefined") { + this.x = x; + this.y = y + } else { + this.x = this.y = 0 + } +} +b2Vec2.prototype = { + Clone: function () { + return new b2Vec2(this.x, this.y) + }, + SetZero: function () { + this.x = 0; + this.y = 0; + return this + }, + Set: function (x_, y_) { + this.x = x_; + this.y = y_; + return this + }, + Assign: function (l) { + this.x = l.x; + this.y = l.y; + return this + }, + Negate: function () { + var v = new b2Vec2(); + v.Set(-this.x, -this.y); + return v + }, + get_i: function (i) { + switch (i) { + case 0: + return this.x; + case 1: + return this.y + } + }, + set_i: function (i, v) { + switch (i) { + case 0: + return this.x = v; + case 1: + return this.y = v + } + }, + Add: function (v) { + this.x += v.x; + this.y += v.y; + return this + }, + Subtract: function (v) { + this.x -= v.x; + this.y -= v.y; + return this + }, + Multiply: function (a) { + this.x *= a; + this.y *= a; + return this + }, + Length: function () { + return b2Sqrt(this.x * this.x + this.y * this.y) + }, + LengthSquared: function () { + return this.x * this.x + this.y * this.y + }, + Normalize: function () { + var length = this.Length(); + if (length < b2_epsilon) { + return 0 + } + var invLength = 1 / length; + this.x *= invLength; + this.y *= invLength; + return length + }, + IsValid: function () { + return b2IsValid(this.x) && b2IsValid(this.y) + }, + Skew: function () { + return new b2Vec2(-this.y, this.x) + }, + _serialize: function (out) { + var obj = out || []; + obj[0] = this.x; + obj[1] = this.y; + return obj + }, + _deserialize: function (data) { + this.x = data[0]; + this.y = data[1] + } +}; +b2Vec2.Add = function (a, b) { + return new b2Vec2(a.x + b.x, a.y + b.y) +}; +b2Vec2.Subtract = function (a, b) { + return new b2Vec2(a.x - b.x, a.y - b.y) +}; +b2Vec2.Equals = function (a, b) { + return a.x == b.x && a.y == b.y +}; +b2Vec2.Multiply = function (s, a) { + return new b2Vec2(s * a.x, s * a.y) +}; +b2Vec2.Negate = function (a) { + return new b2Vec2(-a.x, -a.y) +}; + +function b2Vec3(x, y, z) { + if (typeof (x) !== "undefined") { + this.x = x; + this.y = y; + this.z = z + } +} +b2Vec3.prototype = { + Clone: function () { + return new b2Vec3(this.x, this.y, this.z) + }, + SetZero: function () { + this.x = 0; + this.y = 0; + this.z = 0 + }, + Set: function (x_, y_, z_) { + this.x = x_; + this.y = y_; + this.z = z_ + }, + Negate: function () { + var v = new b2Vec3(); + v.Set(-this.x, -this.y, -this.z); + return v + }, + Add: function (v) { + this.x += v.x; + this.y += v.y; + this.z += v.z + }, + Subtract: function (v) { + this.x -= v.x; + this.y -= v.y; + this.z -= v.z + }, + Multiply: function (s) { + this.x *= s; + this.y *= s; + this.z *= s + }, + x: 0, + y: 0, + z: 0 +}; +b2Vec3.Multiply = function (s, a) { + return new b2Vec3(s * a.x, s * a.y, s * a.z) +}; +b2Vec3.Add = function (a, b) { + return new b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z) +}; +b2Vec3.Subtract = function (a, b) { + return new b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z) +}; + +function b2Mat22(c1, c2) { + this.ex = c1 ? c1.Clone() : new b2Vec2(); + this.ey = c2 ? c2.Clone() : new b2Vec2() +} +b2Mat22.prototype = { + Set: function (c1, c2) { + this.ex.Assign(c1); + this.ey.Assign(c2) + }, + Assign: function (mat) { + this.ex.Assign(mat.ex); + this.ey.Assign(mat.ey) + }, + SetIdentity: function () { + this.ex.x = 1; + this.ey.x = 0; + this.ex.y = 0; + this.ey.y = 1 + }, + SetZero: function () { + this.ex.x = 0; + this.ey.x = 0; + this.ex.y = 0; + this.ey.y = 0 + }, + GetInverse: function () { + var a = this.ex.x, + b = this.ey.x, + c = this.ex.y, + d = this.ey.y; + var B = new b2Mat22(); + var det = a * d - b * c; + if (det != 0) { + det = 1 / det + } + B.ex.x = det * d; + B.ey.x = -det * b; + B.ex.y = -det * c; + B.ey.y = det * a; + return B + }, + Solve: function (b) { + var a11 = this.ex.x, + a12 = this.ey.x, + a21 = this.ex.y, + a22 = this.ey.y; + var det = a11 * a22 - a12 * a21; + if (det != 0) { + det = 1 / det + } + var x = new b2Vec2(); + x.x = det * (a22 * b.x - a12 * b.y); + x.y = det * (a11 * b.y - a21 * b.x); + return x + } +}; +b2Mat22.Add = function (A, B) { + return new b2Mat22(b2Vec2.Add(A.ex, B.ex), b2Vec2.Add(A.ey, B.ey)) +}; + +function b2Mat33(c1, c2, c3) { + this.ex = c1 ? c1.Clone() : new b2Vec3(); + this.ey = c2 ? c2.Clone() : new b2Vec3(); + this.ez = c3 ? c3.Clone() : new b2Vec3() +} +b2Mat33.prototype = { + SetZero: function () { + this.ex.SetZero(); + this.ey.SetZero(); + this.ez.SetZero() + }, + Solve33: function (b) { + var det = b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, this.ez)); + if (det != 0) { + det = 1 / det + } + var x = new b2Vec3(); + x.x = det * b2Dot_v3_v3(b, b2Cross_v3_v3(this.ey, this.ez)); + x.y = det * b2Dot_v3_v3(this.ex, b2Cross_v3_v3(b, this.ez)); + x.z = det * b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, b)); + return x + }, + Solve22: function (b) { + var a11 = this.ex.x, + a12 = this.ey.x, + a21 = this.ex.y, + a22 = this.ey.y; + var det = a11 * a22 - a12 * a21; + if (det != 0) { + det = 1 / det + } + var x = new b2Vec2(); + x.x = det * (a22 * b.x - a12 * b.y); + x.y = det * (a11 * b.y - a21 * b.x); + return x + }, + GetInverse22: function (M) { + var a = this.ex.x, + b = this.ey.x, + c = this.ex.y, + d = this.ey.y; + var det = a * d - b * c; + if (det != 0) { + det = 1 / det + } + M.ex.x = det * d; + M.ey.x = -det * b; + M.ex.z = 0; + M.ex.y = -det * c; + M.ey.y = det * a; + M.ey.z = 0; + M.ez.x = 0; + M.ez.y = 0; + M.ez.z = 0 + }, + GetSymInverse33: function (M) { + var det = b2Dot_v3_v3(this.ex, b2Cross_v3_v3(this.ey, this.ez)); + if (det != 0) { + det = 1 / det + } + var a11 = this.ex.x, + a12 = this.ey.x, + a13 = this.ez.x; + var a22 = this.ey.y, + 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) + } +}; + +function b2Rot(angle, c) { + if (typeof (c) !== "undefined") { + this.s = angle; + this.c = c + } else { + if (typeof (angle) !== "undefined") { + this.Set(angle) + } + } +} +b2Rot.prototype = { + Clone: function () { + return new b2Rot(this.s, this.c) + }, + Assign: function (l) { + this.s = l.s; + this.c = l.c + }, + Set: function (x) { + this.s = sinf(x); + this.c = cosf(x) + }, + SetIdentity: function () { + this.s = 0; + this.c = 1 + }, + GetAngle: function () { + return b2Atan2(this.s, this.c) + }, + GetXAxis: function () { + return new b2Vec2(this.c, this.s) + }, + GetYAxis: function () { + return new b2Vec2(-this.s, this.c) + }, + s: 0, + c: 1 +}; + +function b2Transform(position, rotation) { + this.p = new b2Vec2(); + this.q = new b2Rot(); + if (position) { + this.p.Assign(position); + this.q.Assign(rotation) + } +} +b2Transform.prototype = { + Clone: function () { + var xf = new b2Transform(this.p, this.q); + return xf + }, + Assign: function (xf) { + this.p.Assign(xf.p); + this.q.Assign(xf.q) + }, + SetIdentity: function () { + this.p.SetZero(); + this.q.SetIdentity() + }, + Set: function (position, angle) { + this.p.Assign(position); + this.q.Set(angle) + } +}; + +function b2Sweep() { + this.localCenter = new b2Vec2(); + this.c0 = new b2Vec2(); + this.c = new b2Vec2() +} +b2Sweep.prototype = { + Assign: function (sweep) { + this.localCenter.Assign(sweep.localCenter); + this.c0.Assign(sweep.c0); + this.c.Assign(sweep.c); + this.a = sweep.a; + this.a0 = sweep.a0; + this.alpha0 = sweep.alpha0 + }, + Clone: function () { + var sweep = new b2Sweep(); + sweep.localCenter.Assign(this.localCenter); + sweep.c0.Assign(this.c0); + sweep.c.Assign(this.c); + sweep.a = this.a; + sweep.a0 = this.a0; + sweep.alpha0 = this.alpha0; + return sweep + }, + GetTransform: function (xf, beta) { + xf.p.x = ((1 - beta) * this.c0.x) + (beta * this.c.x); + xf.p.y = ((1 - beta) * this.c0.y) + (beta * this.c.y); + var angle = (1 - beta) * this.a0 + beta * this.a; + xf.q.Set(angle); + xf.p.x -= xf.q.c * this.localCenter.x - xf.q.s * this.localCenter.y; + xf.p.y -= xf.q.s * this.localCenter.x + xf.q.c * this.localCenter.y + }, + Advance: function (alpha) { + var beta = (alpha - this.alpha0) / (1 - this.alpha0); + this.c0.Add(b2Vec2.Multiply(beta, b2Vec2.Subtract(this.c, this.c0))); + this.a0 += beta * (this.a - this.a0); + this.alpha0 = alpha + }, + Normalize: function () { + var twoPi = 2 * b2_pi; + var d = twoPi * floorf(this.a0 / twoPi); + this.a0 -= d; + this.a -= d + }, + a0: 0, + a: 0, + alpha0: 0 +}; + +function b2Dot_v2_v2(a, b) { + return a.x * b.x + a.y * b.y +} + +function b2Cross_v2_v2(a, b) { + return a.x * b.y - a.y * b.x +} + +function b2Cross_v2_f(a, s) { + return new b2Vec2(s * a.y, -s * a.x) +} + +function b2Cross_f_v2(s, a) { + return new b2Vec2(-s * a.y, s * a.x) +} + +function b2Mul_m22_v2(A, v) { + return new b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y) +} + +function b2MulT_m22_v2(A, v) { + return new b2Vec2(b2Dot_v2_v2(v, A.ex), b2Dot_v2_v2(v, A.ey)) +} + +function b2Distance(a, b) { + var c = b2Vec2.Subtract(a, b); + return c.Length() +} + +function b2DistanceSquared(a, b) { + var c = b2Vec2.Subtract(a, b); + return b2Dot_v2_v2(c, c) +} + +function b2Dot_v3_v3(a, b) { + return a.x * b.x + a.y * b.y + a.z * b.z +} + +function b2Cross_v3_v3(a, b) { + return new b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x) +} + +function b2Mul_m22_m22(A, B) { + return new b2Mat22(b2Mul_m22_v2(A, B.ex), b2Mul_m22_v2(A, B.ey)) +} + +function b2MulT_m22_m22(A, B) { + var c1 = new b2Vec2(b2Dot_v2_v2(A.ex, B.ex), b2Dot_v2_v2(A.ey, B.ex)); + var c2 = new b2Vec2(b2Dot_v2_v2(A.ex, B.ey), b2Dot_v2_v2(A.ey, B.ey)); + return new b2Mat22(c1, c2) +} + +function b2Mul_m33_v3(A, v) { + return b2Vec3.Add(b2Vec3.Add(b2Vec3.Multiply(v.x, A.ex), b2Vec3.Multiply(v.y, A.ey)), b2Vec3.Multiply(v.z, A.ez)) +} + +function b2Mul22_m33_v2(A, v) { + return new b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y) +} + +function b2Mul_r_r(q, r) { + var qr = new b2Rot(); + qr.s = q.s * r.c + q.c * r.s; + qr.c = q.c * r.c - q.s * r.s; + return qr +} + +function b2MulT_r_r(q, r) { + var qr = new b2Rot(); + qr.s = q.c * r.s - q.s * r.c; + qr.c = q.c * r.c + q.s * r.s; + return qr +} + +function b2Mul_r_v2(q, v) { + return new b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y) +} + +function b2MulT_r_v2(q, v) { + return new b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y) +} + +function b2Mul_t_v2(T, v) { + return new b2Vec2((T.q.c * v.x - T.q.s * v.y) + T.p.x, (T.q.s * v.x + T.q.c * v.y) + T.p.y) +} + +function b2MulT_t_v2(T, v) { + var px = v.x - T.p.x; + var py = v.y - T.p.y; + var x = (T.q.c * px + T.q.s * py); + var y = (-T.q.s * px + T.q.c * py); + return new b2Vec2(x, y) +} + +function b2Mul_t_t(A, B) { + var C = new b2Transform(); + C.q = b2Mul_r_r(A.q, B.q); + C.p = b2Vec2.Add(b2Mul_r_v2(A.q, B.p), A.p); + return C +} + +function b2MulT_t_t(A, B) { + var C = new b2Transform(); + C.q = b2MulT_r_r(A.q, B.q); + var tvx = B.p.x - A.p.x; + var tvy = B.p.y - A.p.y; + C.p.x = A.q.c * tvx + A.q.s * tvy; + C.p.y = -A.q.s * tvx + A.q.c * tvy; + return C +} +var b2Abs = Math.abs; + +function b2Abs_v2(a) { + return new b2Vec2(b2Abs(a.x), b2Abs(a.y)) +} + +function b2Abs_m22(A) { + return new b2Mat22(b2Abs_v2(A.ex), b2Abs_v2(A.ey)) +} +var b2Min = Math.min; + +function b2Min_v2(a, b) { + return new b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)) +} +var b2Max = Math.max; + +function b2Max_v2(a, b) { + return new b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)) +} + +function b2Clamp(a, low, high) { + return b2Max(low, b2Min(a, high)) +} + +function b2Clamp_v2(a, low, high) { + return b2Max_v2(low, b2Min_v2(a, high)) +} + +function b2NextPowerOfTwo(x) { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x + 1 +} + +function b2IsPowerOfTwo(x) { + var result = x > 0 && (x & (x - 1)) == 0; + return result +} +var RAND_LIMIT = 32767; + +function b2RandomFloat(lo, hi) { + var r = Math.random(); + if (typeof (lo) !== "undefined") { + r = (hi - lo) * r + lo + } else { + r = 2 * r - 1 + } + return r +} +"use strict"; + +function b2Color(r, g, b) { + this.r = r || 0; + this.g = g || 0; + this.b = b || 0 +} +b2Color.prototype = { + Set: function (r, g, b) { + this.r = r; + this.g = g; + this.b = b + } +}; + +function b2Draw() {} +b2Draw.prototype = { + SetFlags: function (flags) { + this.m_drawFlags = flags + }, + GetFlags: function () { + return this.m_drawFlags + }, + AppendFlags: function (flags) { + this.m_drawFlags |= flags + }, + ClearFlags: function (flags) { + this.m_drawFlags &= ~flags + }, + ToggleFlags: function (flags) { + this.m_drawFlags ^= flags + }, + DrawPolygon: function (vertices, vertexCount, color) {}, + DrawSolidPolygon: function (vertices, vertexCount, color) {}, + DrawCircle: function (center, radius, color) {}, + DrawSolidCircle: function (center, radius, axis, color) {}, + DrawSegment: function (p1, p2, color) {}, + DrawTransform: function (xf) {}, + m_drawFlags: 0 +}; +b2Draw.e_shapeBit = 1; +b2Draw.e_jointBit = 2; +b2Draw.e_aabbBit = 4; +b2Draw.e_centerOfMassBit = 8; +b2Draw.e_contactPoints = 16; +b2Draw.e_contactNormals = 32; +b2Draw.e_contactImpulses = 64; +b2Draw.e_frictionImpulses = 128; +b2Draw.e_statistics = 256; +b2Draw.e_profile = 512; +b2Draw.e_pairBit = 1024; + +"use strict"; +function b2Timer() { + this.Reset() +} +b2Timer.prototype = { + Reset: function () { + this.m_start = performance.now() + }, + GetMilliseconds: function () { + return performance.now() - this.m_start + } +}; +"use strict"; + +function b2MassData() { + this.mass = 0; + this.center = new b2Vec2(); + this.I = 0 +} + +function b2Shape() { + this.m_type = 0; + this.m_radius = 0 +} +b2Shape.prototype = { + Clone: function () {}, + GetType: function () { + return this.m_type + }, + GetChildCount: function () {}, + TestPoint: function (xf, p) {}, + RayCast: function (output, input, transform, childIndex) {}, + ComputeAABB: function (aabb, xf, childIndex) {}, + ComputeMass: function (massData, density) {}, + _serialize: function (out) { + var obj = out || {}; + obj.m_type = this.m_type; + obj.m_radius = this.m_radius; + return obj + }, + _deserialize: function (data) { + this.m_radius = data.m_radius + } +}; +b2Shape.e_circle = 0; +b2Shape.e_edge = 1; +b2Shape.e_polygon = 2; +b2Shape.e_chain = 3; +b2Shape.e_typeCount = 4; +"use strict"; + +function b2CircleShape() { + this.parent.call(this); + this.m_type = b2Shape.e_circle; + this.m_radius = 0; + this.m_p = new b2Vec2(); + Object.seal(this) +} +b2CircleShape.prototype = { + Clone: function () { + var shape = new b2CircleShape(); + shape.m_radius = this.m_radius; + shape.m_p = this.m_p.Clone(); + return shape + }, + GetChildCount: function () { + return 1 + }, + TestPoint: function (transform, p) { + var center = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); + var d = b2Vec2.Subtract(p, center); + return b2Dot_v2_v2(d, d) <= this.m_radius * this.m_radius + }, + RayCast: function (output, input, transform, childIndex) { + var position = b2Vec2.Add(transform.p, b2Mul_r_v2(transform.q, this.m_p)); + var s = b2Vec2.Subtract(input.p1, position); + var b = b2Dot_v2_v2(s, s) - this.m_radius * this.m_radius; + var r = b2Vec2.Subtract(input.p2, input.p1); + var c = b2Dot_v2_v2(s, r); + var rr = b2Dot_v2_v2(r, r); + var sigma = c * c - rr * b; + if (sigma < 0 || rr < b2_epsilon) { + return false + } + var a = -(c + b2Sqrt(sigma)); + if (0 <= a && a <= input.maxFraction * rr) { + a /= rr; + output.fraction = a; + output.normal = b2Vec2.Add(s, b2Vec2.Multiply(a, r)); + output.normal.Normalize(); + return true + } + return false + }, + ComputeAABB: function (aabb, transform, childIndex) { + var px = transform.p.x + (transform.q.c * this.m_p.x - transform.q.s * this.m_p.y); + var py = transform.p.y + (transform.q.s * this.m_p.x + transform.q.c * this.m_p.y); + aabb.lowerBound.x = px - this.m_radius; + aabb.lowerBound.y = py - this.m_radius; + aabb.upperBound.x = px + this.m_radius; + aabb.upperBound.y = py + this.m_radius + }, + ComputeMass: function (massData, density) { + massData.mass = density * b2_pi * this.m_radius * this.m_radius; + massData.center = this.m_p; + massData.I = massData.mass * (0.5 * this.m_radius * this.m_radius + b2Dot_v2_v2(this.m_p, this.m_p)) + }, + GetSupport: function (d) { + return 0 + }, + GetSupportVertex: function (d) { + return this.m_p + }, + GetVertexCount: function () { + return 1 + }, + GetVertex: function (index) { + return this.m_p + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_p = this.m_p._serialize(); + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_p._deserialize(data.m_p) + } +}; +b2CircleShape._extend(b2Shape); +"use strict"; + +function b2EdgeShape() { + this.parent.call(this); + this.m_type = b2Shape.e_edge; + this.m_radius = b2_polygonRadius; + this.m_vertex0 = new b2Vec2(); + this.m_vertex1 = new b2Vec2(); + this.m_vertex2 = new b2Vec2(); + this.m_vertex3 = new b2Vec2(); + this.m_hasVertex0 = false; + this.m_hasVertex3 = false; + Object.seal(this) +} +b2EdgeShape.prototype = { + Set: function (v1, v2) { + this.m_vertex1.Assign(v1); + this.m_vertex2.Assign(v2); + this.m_hasVertex0 = false; + this.m_hasVertex3 = false + }, + Clone: function () { + var shape = new b2EdgeShape(); + shape.m_vertex0 = this.m_vertex0.Clone(); + shape.m_vertex1 = this.m_vertex1.Clone(); + shape.m_vertex2 = this.m_vertex2.Clone(); + shape.m_vertex3 = this.m_vertex3.Clone(); + shape.m_hasVertex0 = this.m_hasVertex0; + shape.m_hasVertex3 = this.m_hasVertex3; + return shape + }, + GetChildCount: function () { + return 1 + }, + TestPoint: function (transform, p) { + return false + }, + RayCast: function (output, input, xf, childIndex) { + var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); + var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); + var d = b2Vec2.Subtract(p2, p1); + var v1 = this.m_vertex1; + var v2 = this.m_vertex2; + var e = b2Vec2.Subtract(v2, v1); + var normal = new b2Vec2(e.y, -e.x); + normal.Normalize(); + var numerator = b2Dot_v2_v2(normal, b2Vec2.Subtract(v1, p1)); + var denominator = b2Dot_v2_v2(normal, d); + if (denominator == 0) { + return false + } + var t = numerator / denominator; + if (t < 0 || input.maxFraction < t) { + return false + } + var q = b2Vec2.Add(p1, b2Vec2.Multiply(t, d)); + var r = b2Vec2.Subtract(v2, v1); + var rr = b2Dot_v2_v2(r, r); + if (rr == 0) { + return false + } + var s = b2Dot_v2_v2(b2Vec2.Subtract(q, v1), r) / rr; + if (s < 0 || 1 < s) { + return false + } + output.fraction = t; + if (numerator > 0) { + output.normal = b2Mul_r_v2(xf.q, normal).Negate() + } else { + output.normal = b2Mul_r_v2(xf.q, normal) + } + return true + }, + ComputeAABB: function (aabb, xf, childIndex) { + var v1x = (xf.q.c * this.m_vertex1.x - xf.q.s * this.m_vertex1.y) + xf.p.x; + var v1y = (xf.q.s * this.m_vertex1.x + xf.q.c * this.m_vertex1.y) + xf.p.y; + var v2x = (xf.q.c * this.m_vertex2.x - xf.q.s * this.m_vertex2.y) + xf.p.x; + var v2y = (xf.q.s * this.m_vertex2.x + xf.q.c * this.m_vertex2.y) + xf.p.y; + var lowerx = b2Min(v1x, v2x); + var lowery = b2Min(v1y, v2y); + var upperx = b2Max(v1x, v2x); + var uppery = b2Max(v1y, v2y); + aabb.lowerBound.x = lowerx - this.m_radius; + aabb.lowerBound.y = lowery - this.m_radius; + aabb.upperBound.x = upperx + this.m_radius; + aabb.upperBound.y = uppery + this.m_radius + }, + ComputeMass: function (massData, density) { + massData.mass = 0; + massData.center = b2Vec2.Multiply(0.5, b2Vec2.Add(this.m_vertex1, this.m_vertex2)); + massData.I = 0 + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_vertex1 = this.m_vertex1._serialize(); + obj.m_vertex2 = this.m_vertex2._serialize(); + obj.m_hasVertex0 = this.m_hasVertex0; + if (this.m_hasVertex0) { + obj.m_vertex0 = this.m_vertex0._serialize() + } + obj.m_hasVertex3 = this.m_hasVertex3; + if (this.m_hasVertex3) { + obj.m_vertex3 = this.m_vertex3._serialize() + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_vertex1._deserialize(data.m_vertex1); + this.m_vertex2._deserialize(data.m_vertex2); + this.m_hasVertex0 = data.m_hasVertex0; + if (this.m_hasVertex0) { + this.m_vertex0._deserialize(data.m_vertex0) + } + this.m_hasVertex3 = data.m_hasVertex3; + if (this.m_hasVertex3) { + this.m_vertex3._deserialize(data.m_vertex3) + } + } +}; +b2EdgeShape._extend(b2Shape); +"use strict"; + +function b2ChainShape() { + this.parent.call(this); + this.m_type = b2Shape.e_chain; + this.m_radius = b2_polygonRadius; + this.m_vertices = null; + this.m_count = 0; + this.m_prevVertex = new b2Vec2(); + this.m_nextVertex = new b2Vec2(); + this.m_hasPrevVertex = false; + this.m_hasNextVertex = false; + Object.seal(this) +} +b2ChainShape.prototype = { + CreateLoop: function (vertices, count) { + for (var i = 1; i < count; ++i) { + var v1 = vertices[i - 1]; + var v2 = vertices[i] + } + this.m_count = count + 1; + this.m_vertices = new Array(this.m_count); + for (var i = 0; i < count; ++i) { + this.m_vertices[i] = vertices[i].Clone() + } + this.m_vertices[count] = this.m_vertices[0].Clone(); + this.m_prevVertex.Assign(this.m_vertices[this.m_count - 2]); + this.m_nextVertex.Assign(this.m_vertices[1]); + this.m_hasPrevVertex = true; + this.m_hasNextVertex = true + }, + CreateChain: function (vertices, count) { + for (var i = 1; i < count; ++i) { + var v1 = vertices[i - 1]; + var v2 = vertices[i] + } + this.m_count = count; + this.m_vertices = new Array(count); + for (var i = 0; i < count; ++i) { + this.m_vertices[i] = vertices[i].Clone() + } this.m_hasPrevVertex = false; this.m_hasNextVertex = false; - Object.seal(this) - } - b2ChainShape.prototype = { - CreateLoop: function (vertices, count) { - for (var i = 1; i < count; ++i) { - var v1 = vertices[i - 1]; - var v2 = vertices[i] - } - this.m_count = count + 1; - this.m_vertices = new Array(this.m_count); - for (var i = 0; i < count; ++i) { - this.m_vertices[i] = vertices[i].Clone() - } - this.m_vertices[count] = this.m_vertices[0].Clone(); - this.m_prevVertex.Assign(this.m_vertices[this.m_count - 2]); - this.m_nextVertex.Assign(this.m_vertices[1]); - this.m_hasPrevVertex = true; - this.m_hasNextVertex = true - }, - CreateChain: function (vertices, count) { - for (var i = 1; i < count; ++i) { - var v1 = vertices[i - 1]; - var v2 = vertices[i] - } - this.m_count = count; - this.m_vertices = new Array(count); - for (var i = 0; i < count; ++i) { - this.m_vertices[i] = vertices[i].Clone() - } - this.m_hasPrevVertex = false; - this.m_hasNextVertex = false; - this.m_prevVertex.SetZero(); - this.m_nextVertex.SetZero() - }, - SetPrevVertex: function (prevVertex) { - this.m_prevVertex.Assign(prevVertex); - this.m_hasPrevVertex = true - }, - SetNextVertex: function (nextVertex) { - this.m_nextVertex.Assign(nextVertex); - this.m_hasNextVertex = true - }, - Clone: function () { - var shape = new b2ChainShape(); - shape.m_count = this.m_count; - shape.m_vertices = new Array(this.m_count); - for (var i = 0; i < this.m_count; ++i) { - shape.m_vertices[i] = this.m_vertices[i].Clone() - } - shape.m_prevVertex = this.m_prevVertex.Clone(); - shape.m_nextVertex = this.m_nextVertex.Clone(); - shape.m_hasPrevVertex = this.m_hasPrevVertex; - shape.m_hasNextVertex = this.m_hasNextVertex; - return shape - }, - GetChildCount: function () { - return this.m_count - 1 - }, - GetChildEdge: function (edge, index) { - edge.m_type = b2Shape.e_edge; - edge.m_radius = this.m_radius; - edge.m_vertex1 = this.m_vertices[index + 0]; - edge.m_vertex2 = this.m_vertices[index + 1]; - if (index > 0) { - edge.m_vertex0 = this.m_vertices[index - 1]; - edge.m_hasVertex0 = true - } else { - edge.m_vertex0 = this.m_prevVertex; - edge.m_hasVertex0 = this.m_hasPrevVertex - } - if (index < this.m_count - 2) { - edge.m_vertex3 = this.m_vertices[index + 2]; - edge.m_hasVertex3 = true - } else { - edge.m_vertex3 = this.m_nextVertex; - edge.m_hasVertex3 = this.m_hasNextVertex - } - }, - TestPoint: function (transform, p) { - return false - }, - RayCast: function (output, input, xf, childIndex) { - var edgeShape = new b2EdgeShape(); - var i1 = childIndex; - var i2 = childIndex + 1; - if (i2 == this.m_count) { - i2 = 0 - } - edgeShape.m_vertex1 = this.m_vertices[i1].Clone(); - edgeShape.m_vertex2 = this.m_vertices[i2].Clone(); - return edgeShape.RayCast(output, input, xf, 0) - }, - ComputeAABB: function (aabb, xf, childIndex) { - var i1 = childIndex; - var i2 = childIndex + 1; - if (i2 == this.m_count) { - i2 = 0 - } - var v1x = (xf.q.c * this.m_vertices[i1].x - xf.q.s * this.m_vertices[i1].y) + xf.p.x; - var v1y = (xf.q.s * this.m_vertices[i1].x + xf.q.c * this.m_vertices[i1].y) + xf.p.y; - var v2x = (xf.q.c * this.m_vertices[i2].x - xf.q.s * this.m_vertices[i2].y) + xf.p.x; - var v2y = (xf.q.s * this.m_vertices[i2].x + xf.q.c * this.m_vertices[i2].y) + xf.p.y; - aabb.lowerBound.x = b2Min(v1x, v2x); - aabb.lowerBound.y = b2Min(v1y, v2y); - aabb.upperBound.x = b2Max(v1x, v2x); - aabb.upperBound.y = b2Max(v1y, v2y) - }, - ComputeMass: function (massData, density) { - massData.mass = 0; - massData.center.SetZero(); - massData.I = 0 - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.m_count = this.m_count; - obj.m_vertices = []; - for (var i = 0; i < this.m_count; ++i) { - obj.m_vertices.push(this.m_vertices[i]._serialize()) - } - obj.m_hasPrevVertex = this.m_hasPrevVertex; - if (this.m_hasPrevVertex) { - obj.m_prevVertex = this.m_prevVertex._serialize() - } - obj.m_hasNextVertex = this.m_hasNextVertex; - if (this.m_hasNextVertex) { - obj.m_nextVertex = this.m_nextVertex._serialize() - } - return obj - }, - _deserialize: function (data) { - this.parent.prototype._deserialize.call(this, data); - this.m_count = data.m_count; - this.m_vertices = []; - for (var i = 0; i < this.m_count; ++i) { - this.m_vertices[i] = new b2Vec2(); - this.m_vertices[i]._deserialize(data.m_vertices[i]) - } - this.m_hasPrevVertex = data.m_hasPrevVertex; - if (this.m_hasPrevVertex) { - this.m_prevVertex._deserialize(data.m_prevVertex) - } - this.m_hasNextVertex = data.m_hasNextVertex; - if (this.m_hasNextVertex) { - this.m_nextVertex._deserialize(data.m_nextVertex) - } + this.m_prevVertex.SetZero(); + this.m_nextVertex.SetZero() + }, + SetPrevVertex: function (prevVertex) { + this.m_prevVertex.Assign(prevVertex); + this.m_hasPrevVertex = true + }, + SetNextVertex: function (nextVertex) { + this.m_nextVertex.Assign(nextVertex); + this.m_hasNextVertex = true + }, + Clone: function () { + var shape = new b2ChainShape(); + shape.m_count = this.m_count; + shape.m_vertices = new Array(this.m_count); + for (var i = 0; i < this.m_count; ++i) { + shape.m_vertices[i] = this.m_vertices[i].Clone() + } + shape.m_prevVertex = this.m_prevVertex.Clone(); + shape.m_nextVertex = this.m_nextVertex.Clone(); + shape.m_hasPrevVertex = this.m_hasPrevVertex; + shape.m_hasNextVertex = this.m_hasNextVertex; + return shape + }, + GetChildCount: function () { + return this.m_count - 1 + }, + GetChildEdge: function (edge, index) { + edge.m_type = b2Shape.e_edge; + edge.m_radius = this.m_radius; + edge.m_vertex1 = this.m_vertices[index + 0]; + edge.m_vertex2 = this.m_vertices[index + 1]; + if (index > 0) { + edge.m_vertex0 = this.m_vertices[index - 1]; + edge.m_hasVertex0 = true + } else { + edge.m_vertex0 = this.m_prevVertex; + edge.m_hasVertex0 = this.m_hasPrevVertex + } + if (index < this.m_count - 2) { + edge.m_vertex3 = this.m_vertices[index + 2]; + edge.m_hasVertex3 = true + } else { + edge.m_vertex3 = this.m_nextVertex; + edge.m_hasVertex3 = this.m_hasNextVertex + } + }, + TestPoint: function (transform, p) { + return false + }, + RayCast: function (output, input, xf, childIndex) { + var edgeShape = new b2EdgeShape(); + var i1 = childIndex; + var i2 = childIndex + 1; + if (i2 == this.m_count) { + i2 = 0 + } + edgeShape.m_vertex1 = this.m_vertices[i1].Clone(); + edgeShape.m_vertex2 = this.m_vertices[i2].Clone(); + return edgeShape.RayCast(output, input, xf, 0) + }, + ComputeAABB: function (aabb, xf, childIndex) { + var i1 = childIndex; + var i2 = childIndex + 1; + if (i2 == this.m_count) { + i2 = 0 + } + var v1x = (xf.q.c * this.m_vertices[i1].x - xf.q.s * this.m_vertices[i1].y) + xf.p.x; + var v1y = (xf.q.s * this.m_vertices[i1].x + xf.q.c * this.m_vertices[i1].y) + xf.p.y; + var v2x = (xf.q.c * this.m_vertices[i2].x - xf.q.s * this.m_vertices[i2].y) + xf.p.x; + var v2y = (xf.q.s * this.m_vertices[i2].x + xf.q.c * this.m_vertices[i2].y) + xf.p.y; + aabb.lowerBound.x = b2Min(v1x, v2x); + aabb.lowerBound.y = b2Min(v1y, v2y); + aabb.upperBound.x = b2Max(v1x, v2x); + aabb.upperBound.y = b2Max(v1y, v2y) + }, + ComputeMass: function (massData, density) { + massData.mass = 0; + massData.center.SetZero(); + massData.I = 0 + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_count = this.m_count; + obj.m_vertices = []; + for (var i = 0; i < this.m_count; ++i) { + obj.m_vertices.push(this.m_vertices[i]._serialize()) + } + obj.m_hasPrevVertex = this.m_hasPrevVertex; + if (this.m_hasPrevVertex) { + obj.m_prevVertex = this.m_prevVertex._serialize() + } + obj.m_hasNextVertex = this.m_hasNextVertex; + if (this.m_hasNextVertex) { + obj.m_nextVertex = this.m_nextVertex._serialize() + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_count = data.m_count; + this.m_vertices = []; + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i] = new b2Vec2(); + this.m_vertices[i]._deserialize(data.m_vertices[i]) + } + this.m_hasPrevVertex = data.m_hasPrevVertex; + if (this.m_hasPrevVertex) { + this.m_prevVertex._deserialize(data.m_prevVertex) + } + this.m_hasNextVertex = data.m_hasNextVertex; + if (this.m_hasNextVertex) { + this.m_nextVertex._deserialize(data.m_nextVertex) } - }; - b2ChainShape._extend(b2Shape); - "use strict"; - - function b2PolygonShape() { - this.parent.call(this); - this.m_type = b2Shape.e_polygon; - this.m_radius = b2_polygonRadius; - this.m_count = 0; - this.m_centroid = new b2Vec2(); - this.m_vertices = new Array(b2_maxPolygonVertices); - this.m_normals = new Array(b2_maxPolygonVertices); - Object.seal(this) } - b2PolygonShape.prototype = { - Clone: function () { - var shape = new b2PolygonShape(); - shape.m_count = this.m_count; - shape.m_centroid = this.m_centroid.Clone(); - for (var i = 0; i < this.m_count; ++i) { - shape.m_vertices[i] = this.m_vertices[i].Clone(); - shape.m_normals[i] = this.m_normals[i].Clone() - } - return shape - }, - GetChildCount: function () { - return 1 - }, - Set: function (vertices, count) { - if (count < 3) { - this.SetAsBox(1, 1); - return - } - var n = b2Min(count, b2_maxPolygonVertices); - var ps = new Array(b2_maxPolygonVertices); - var tempCount = 0; - for (var i = 0; i < n; ++i) { - var v = vertices[i]; - var unique = true; - for (var j = 0; j < tempCount; ++j) { - if (b2DistanceSquared(v, ps[j]) < 0.5 * b2_linearSlop) { - unique = false; - break - } - } - if (unique) { - ps[tempCount++] = v.Clone() - } - } - n = tempCount; - if (n < 3) { - this.SetAsBox(1, 1); - return - } - var i0 = 0; - var x0 = ps[0].x; - for (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 = new Array(b2_maxPolygonVertices); - var m = 0; - var ih = i0; - for (;;) { - hull[m] = ih; - var ie = 0; - for (j = 1; j < n; ++j) { - if (ie == ih) { - ie = j; - continue - } - var r = b2Vec2.Subtract(ps[ie], ps[hull[m]]); - var v = b2Vec2.Subtract(ps[j], ps[hull[m]]); - var c = b2Cross_v2_v2(r, v); - if (c < 0) { - ie = j - } - if (c == 0 && v.LengthSquared() > r.LengthSquared()) { - ie = j - } - }++m; - ih = ie; - if (ie == i0) { +}; +b2ChainShape._extend(b2Shape); +"use strict"; + +function b2PolygonShape() { + this.parent.call(this); + this.m_type = b2Shape.e_polygon; + this.m_radius = b2_polygonRadius; + this.m_count = 0; + this.m_centroid = new b2Vec2(); + this.m_vertices = new Array(b2_maxPolygonVertices); + this.m_normals = new Array(b2_maxPolygonVertices); + Object.seal(this) +} +b2PolygonShape.prototype = { + Clone: function () { + var shape = new b2PolygonShape(); + shape.m_count = this.m_count; + shape.m_centroid = this.m_centroid.Clone(); + for (var i = 0; i < this.m_count; ++i) { + shape.m_vertices[i] = this.m_vertices[i].Clone(); + shape.m_normals[i] = this.m_normals[i].Clone() + } + return shape + }, + GetChildCount: function () { + return 1 + }, + Set: function (vertices, count) { + if (count < 3) { + this.SetAsBox(1, 1); + return + } + var n = b2Min(count, b2_maxPolygonVertices); + var ps = new Array(b2_maxPolygonVertices); + var tempCount = 0; + for (var i = 0; i < n; ++i) { + var v = vertices[i]; + var unique = true; + for (var j = 0; j < tempCount; ++j) { + if (b2DistanceSquared(v, ps[j]) < 0.5 * b2_linearSlop) { + unique = false; break } } - this.m_count = m; - for (i = 0; i < m; ++i) { - this.m_vertices[i] = ps[hull[i]].Clone() - } - for (i = 0; i < m; ++i) { - var i1 = i; - var i2 = i + 1 < m ? i + 1 : 0; - var edge = b2Vec2.Subtract(this.m_vertices[i2], this.m_vertices[i1]); - this.m_normals[i] = b2Cross_v2_f(edge, 1).Clone(); - this.m_normals[i].Normalize() - } - this.m_centroid = b2PolygonShape.ComputeCentroid(this.m_vertices, m) - }, - SetAsBox: function (hx, hy, center, angle) { - this.m_count = 4; - this.m_vertices[0] = new b2Vec2(-hx, -hy); - this.m_vertices[1] = new b2Vec2(hx, -hy); - this.m_vertices[2] = new b2Vec2(hx, hy); - this.m_vertices[3] = new b2Vec2(-hx, hy); - this.m_normals[0] = new b2Vec2(0, -1); - this.m_normals[1] = new b2Vec2(1, 0); - this.m_normals[2] = new b2Vec2(0, 1); - this.m_normals[3] = new b2Vec2(-1, 0); - if (!center) { - return - } - this.m_centroid.Assign(center); - var xf = new b2Transform(); - xf.p = center; - xf.q.Set(angle); - for (var i = 0; i < this.m_count; ++i) { - this.m_vertices[i].Assign(b2Mul_t_v2(xf, this.m_vertices[i])); - this.m_normals[i].Assign(b2Mul_r_v2(xf.q, this.m_normals[i])) - } - }, - TestPoint: function (xf, p) { - var pLocal = b2MulT_r_v2(xf.q, b2Vec2.Subtract(p, xf.p)); - for (var i = 0; i < this.m_count; ++i) { - var dot = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(pLocal, this.m_vertices[i])); - if (dot > 0) { - return false - } - } - return true - }, - RayCast: function (output, input, xf, childIndex) { - var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); - var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); - var d = b2Vec2.Subtract(p2, p1); - var lower = 0, - upper = input.maxFraction; - var index = -1; - for (var i = 0; i < this.m_count; ++i) { - var numerator = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(this.m_vertices[i], p1)); - var denominator = b2Dot_v2_v2(this.m_normals[i], d); - if (denominator == 0) { - if (numerator < 0) { - return false - } - } else { - if (denominator < 0 && numerator < lower * denominator) { - lower = numerator / denominator; - index = i - } else { - if (denominator > 0 && numerator < upper * denominator) { - upper = numerator / denominator - } - } - } - if (upper < lower) { - return false - } - } - if (index >= 0) { - output.fraction = lower; - output.normal = b2Mul_r_v2(xf.q, this.m_normals[index]); - return true - } - return false - }, - ComputeAABB: function (aabb, xf, childIndex) { - var lowerx = (xf.q.c * this.m_vertices[0].x - xf.q.s * this.m_vertices[0].y) + xf.p.x; - var lowery = (xf.q.s * this.m_vertices[0].x + xf.q.c * this.m_vertices[0].y) + xf.p.y; - var upperx = lowerx; - var uppery = lowery; - for (var i = 1; i < this.m_count; ++i) { - var vx = (xf.q.c * this.m_vertices[i].x - xf.q.s * this.m_vertices[i].y) + xf.p.x; - var vy = (xf.q.s * this.m_vertices[i].x + xf.q.c * this.m_vertices[i].y) + xf.p.y; - lowerx = b2Min(lowerx, vx); - lowery = b2Min(lowery, vy); - upperx = b2Max(upperx, vx); - uppery = b2Max(uppery, vy) - } - aabb.lowerBound.x = lowerx - this.m_radius; - aabb.lowerBound.y = lowery - this.m_radius; - aabb.upperBound.x = upperx + this.m_radius; - aabb.upperBound.y = uppery + this.m_radius - }, - ComputeMass: function (massData, density) { - var center = new b2Vec2(0, 0); - var area = 0; - var I = 0; - var s = new b2Vec2(0, 0); - for (var i = 0; i < this.m_count; ++i) { - s.Add(this.m_vertices[i]) - } - s.Multiply(1 / this.m_count); - var k_inv3 = 1 / 3; - for (var i = 0; i < this.m_count; ++i) { - var e1 = b2Vec2.Subtract(this.m_vertices[i], s); - var e2 = i + 1 < this.m_count ? b2Vec2.Subtract(this.m_vertices[i + 1], s) : b2Vec2.Subtract(this.m_vertices[0], s); - var D = b2Cross_v2_v2(e1, e2); - var triangleArea = 0.5 * D; - area += triangleArea; - center.Add(b2Vec2.Multiply(triangleArea * k_inv3, b2Vec2.Add(e1, e2))); - var ex1 = e1.x, - ey1 = e1.y; - var ex2 = e2.x, - 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) - } - massData.mass = density * area; - center.Multiply(1 / area); - massData.center = b2Vec2.Add(center, s); - massData.I = density * I; - massData.I += massData.mass * (b2Dot_v2_v2(massData.center, massData.center) - b2Dot_v2_v2(center, center)) - }, - GetVertexCount: function () { - return this.m_count - }, - GetVertex: function (index) { - return this.m_vertices[index] - }, - 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 = b2Vec2.Subtract(this.m_vertices[i2], p); - for (var j = 0; j < this.m_count; ++j) { - if (j == i1 || j == i2) { - continue - } - var v = b2Vec2.Subtract(this.m_vertices[j], p); - var c = b2Cross_v2_v2(e, v); - if (c < 0) { - return false - } - } - } - return true - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.m_count = this.m_count; - obj.m_centroid = this.m_centroid._serialize(); - obj.m_vertices = []; - obj.m_normals = []; - for (var i = 0; i < this.m_count; ++i) { - obj.m_vertices.push(this.m_vertices[i]._serialize()); - obj.m_normals.push(this.m_normals[i]._serialize()) - } - return obj - }, - _deserialize: function (data) { - this.parent.prototype._deserialize.call(this, data); - this.m_count = data.m_count; - this.m_centroid._deserialize(data.m_centroid); - this.m_vertices = []; - this.m_normals = []; - for (var i = 0; i < this.m_count; ++i) { - this.m_vertices[i] = new b2Vec2(); - this.m_vertices[i]._deserialize(data.m_vertices[i]); - this.m_normals[i] = new b2Vec2(); - this.m_normals[i]._deserialize(data.m_normals[i]) + if (unique) { + ps[tempCount++] = v.Clone() } } - }; - b2PolygonShape.ComputeCentroid = function (vs, count) { - var c = new b2Vec2(); + n = tempCount; + if (n < 3) { + this.SetAsBox(1, 1); + return + } + var i0 = 0; + var x0 = ps[0].x; + for (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 = new Array(b2_maxPolygonVertices); + var m = 0; + var ih = i0; + for (;;) { + hull[m] = ih; + var ie = 0; + for (j = 1; j < n; ++j) { + if (ie == ih) { + ie = j; + continue + } + var r = b2Vec2.Subtract(ps[ie], ps[hull[m]]); + var v = b2Vec2.Subtract(ps[j], ps[hull[m]]); + var c = b2Cross_v2_v2(r, v); + if (c < 0) { + ie = j + } + if (c == 0 && v.LengthSquared() > r.LengthSquared()) { + ie = j + } + }++m; + ih = ie; + if (ie == i0) { + break + } + } + this.m_count = m; + for (i = 0; i < m; ++i) { + this.m_vertices[i] = ps[hull[i]].Clone() + } + for (i = 0; i < m; ++i) { + var i1 = i; + var i2 = i + 1 < m ? i + 1 : 0; + var edge = b2Vec2.Subtract(this.m_vertices[i2], this.m_vertices[i1]); + this.m_normals[i] = b2Cross_v2_f(edge, 1).Clone(); + this.m_normals[i].Normalize() + } + this.m_centroid = b2PolygonShape.ComputeCentroid(this.m_vertices, m) + }, + SetAsBox: function (hx, hy, center, angle) { + this.m_count = 4; + this.m_vertices[0] = new b2Vec2(-hx, -hy); + this.m_vertices[1] = new b2Vec2(hx, -hy); + this.m_vertices[2] = new b2Vec2(hx, hy); + this.m_vertices[3] = new b2Vec2(-hx, hy); + this.m_normals[0] = new b2Vec2(0, -1); + this.m_normals[1] = new b2Vec2(1, 0); + this.m_normals[2] = new b2Vec2(0, 1); + this.m_normals[3] = new b2Vec2(-1, 0); + if (!center) { + return + } + this.m_centroid.Assign(center); + var xf = new b2Transform(); + xf.p = center; + xf.q.Set(angle); + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i].Assign(b2Mul_t_v2(xf, this.m_vertices[i])); + this.m_normals[i].Assign(b2Mul_r_v2(xf.q, this.m_normals[i])) + } + }, + TestPoint: function (xf, p) { + var pLocal = b2MulT_r_v2(xf.q, b2Vec2.Subtract(p, xf.p)); + for (var i = 0; i < this.m_count; ++i) { + var dot = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(pLocal, this.m_vertices[i])); + if (dot > 0) { + return false + } + } + return true + }, + RayCast: function (output, input, xf, childIndex) { + var p1 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p1, xf.p)); + var p2 = b2MulT_r_v2(xf.q, b2Vec2.Subtract(input.p2, xf.p)); + var d = b2Vec2.Subtract(p2, p1); + var lower = 0, + upper = input.maxFraction; + var index = -1; + for (var i = 0; i < this.m_count; ++i) { + var numerator = b2Dot_v2_v2(this.m_normals[i], b2Vec2.Subtract(this.m_vertices[i], p1)); + var denominator = b2Dot_v2_v2(this.m_normals[i], d); + if (denominator == 0) { + if (numerator < 0) { + return false + } + } else { + if (denominator < 0 && numerator < lower * denominator) { + lower = numerator / denominator; + index = i + } else { + if (denominator > 0 && numerator < upper * denominator) { + upper = numerator / denominator + } + } + } + if (upper < lower) { + return false + } + } + if (index >= 0) { + output.fraction = lower; + output.normal = b2Mul_r_v2(xf.q, this.m_normals[index]); + return true + } + return false + }, + ComputeAABB: function (aabb, xf, childIndex) { + var lowerx = (xf.q.c * this.m_vertices[0].x - xf.q.s * this.m_vertices[0].y) + xf.p.x; + var lowery = (xf.q.s * this.m_vertices[0].x + xf.q.c * this.m_vertices[0].y) + xf.p.y; + var upperx = lowerx; + var uppery = lowery; + for (var i = 1; i < this.m_count; ++i) { + var vx = (xf.q.c * this.m_vertices[i].x - xf.q.s * this.m_vertices[i].y) + xf.p.x; + var vy = (xf.q.s * this.m_vertices[i].x + xf.q.c * this.m_vertices[i].y) + xf.p.y; + lowerx = b2Min(lowerx, vx); + lowery = b2Min(lowery, vy); + upperx = b2Max(upperx, vx); + uppery = b2Max(uppery, vy) + } + aabb.lowerBound.x = lowerx - this.m_radius; + aabb.lowerBound.y = lowery - this.m_radius; + aabb.upperBound.x = upperx + this.m_radius; + aabb.upperBound.y = uppery + this.m_radius + }, + ComputeMass: function (massData, density) { + var center = new b2Vec2(0, 0); var area = 0; - var pRef = new b2Vec2(0, 0); - var inv3 = 1 / 3; - for (var i = 0; i < count; ++i) { - var p1 = pRef; - var p2 = vs[i]; - var p3 = i + 1 < count ? vs[i + 1] : vs[0]; - var e1 = b2Vec2.Subtract(p2, p1); - var e2 = b2Vec2.Subtract(p3, p1); + var I = 0; + var s = new b2Vec2(0, 0); + for (var i = 0; i < this.m_count; ++i) { + s.Add(this.m_vertices[i]) + } + s.Multiply(1 / this.m_count); + var k_inv3 = 1 / 3; + for (var i = 0; i < this.m_count; ++i) { + var e1 = b2Vec2.Subtract(this.m_vertices[i], s); + var e2 = i + 1 < this.m_count ? b2Vec2.Subtract(this.m_vertices[i + 1], s) : b2Vec2.Subtract(this.m_vertices[0], s); var D = b2Cross_v2_v2(e1, e2); var triangleArea = 0.5 * D; area += triangleArea; - c.Add(b2Vec2.Multiply(triangleArea, b2Vec2.Multiply(inv3, b2Vec2.Add(b2Vec2.Add(p1, p2), p3)))) + center.Add(b2Vec2.Multiply(triangleArea * k_inv3, b2Vec2.Add(e1, e2))); + var ex1 = e1.x, + ey1 = e1.y; + var ex2 = e2.x, + 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) } - c.Multiply(1 / area); - return c - }; - b2PolygonShape._extend(b2Shape); - "use strict"; - - function b2Pair() { - this.proxyIdA = 0; - this.proxyIdB = 0 - } - - function b2PairLessThan(pair1, pair2) { - if (pair1.proxyIdA == pair2.proxyIdA) { - return pair1.proxyIdB - pair2.proxyIdB - } - return pair1.proxyIdA - pair2.proxyIdA - } - - function b2BroadPhase() { - this.m_tree = new b2DynamicTree(); - this.m_queryProxyId = 0; - this.m_proxyCount = 0; - this.m_pairCount = 0; - this.m_pairBuffer = []; - this.m_moveCount = 0; - this.m_moveBuffer = [] - } - b2BroadPhase.prototype = { - CreateProxy: function (aabb, userData) { - var proxyId = this.m_tree.CreateProxy(aabb, userData); - ++this.m_proxyCount; - this.BufferMove(proxyId); - return proxyId - }, - DestroyProxy: function (proxyId) { - this.UnBufferMove(proxyId); - --this.m_proxyCount; - this.m_tree.DestroyProxy(proxyId) - }, - MoveProxy: function (proxyId, aabb, displacement) { - var buffer = this.m_tree.MoveProxy(proxyId, aabb, displacement); - if (buffer) { - this.BufferMove(proxyId) - } - }, - TouchProxy: function (proxyId) { - this.BufferMove(proxyId) - }, - GetFatAABB: function (proxyId) { - return this.m_tree.GetFatAABB(proxyId) - }, - GetUserData: function (proxyId) { - return this.m_tree.GetUserData(proxyId) - }, - TestOverlap: function (proxyIdA, proxyIdB) { - var aabbA = this.m_tree.GetFatAABB(proxyIdA); - var aabbB = this.m_tree.GetFatAABB(proxyIdB); - return b2TestOverlap(aabbA, aabbB) - }, - GetProxyCount: function () { - return this.m_proxyCount - }, - UpdatePairs: function (callback) { - this.m_pairCount = 0; - this.m_pairBuffer.length = 0; - for (var i = 0; i < this.m_moveCount; ++i) { - this.m_queryProxyId = this.m_moveBuffer[i]; - if (this.m_queryProxyId == b2BroadPhase.e_nullProxy) { + massData.mass = density * area; + center.Multiply(1 / area); + massData.center = b2Vec2.Add(center, s); + massData.I = density * I; + massData.I += massData.mass * (b2Dot_v2_v2(massData.center, massData.center) - b2Dot_v2_v2(center, center)) + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertex: function (index) { + return this.m_vertices[index] + }, + 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 = b2Vec2.Subtract(this.m_vertices[i2], p); + for (var j = 0; j < this.m_count; ++j) { + if (j == i1 || j == i2) { continue } - var fatAABB = this.m_tree.GetFatAABB(this.m_queryProxyId); - this.m_tree.Query(this, fatAABB) + var v = b2Vec2.Subtract(this.m_vertices[j], p); + var c = b2Cross_v2_v2(e, v); + if (c < 0) { + return false + } } - this.m_moveCount = 0; - this.m_pairBuffer.sort(b2PairLessThan); - var i = 0; + } + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.m_count = this.m_count; + obj.m_centroid = this.m_centroid._serialize(); + obj.m_vertices = []; + obj.m_normals = []; + for (var i = 0; i < this.m_count; ++i) { + obj.m_vertices.push(this.m_vertices[i]._serialize()); + obj.m_normals.push(this.m_normals[i]._serialize()) + } + return obj + }, + _deserialize: function (data) { + this.parent.prototype._deserialize.call(this, data); + this.m_count = data.m_count; + this.m_centroid._deserialize(data.m_centroid); + this.m_vertices = []; + this.m_normals = []; + for (var i = 0; i < this.m_count; ++i) { + this.m_vertices[i] = new b2Vec2(); + this.m_vertices[i]._deserialize(data.m_vertices[i]); + this.m_normals[i] = new b2Vec2(); + this.m_normals[i]._deserialize(data.m_normals[i]) + } + } +}; +b2PolygonShape.ComputeCentroid = function (vs, count) { + var c = new b2Vec2(); + var area = 0; + var pRef = new b2Vec2(0, 0); + var inv3 = 1 / 3; + for (var i = 0; i < count; ++i) { + var p1 = pRef; + var p2 = vs[i]; + var p3 = i + 1 < count ? vs[i + 1] : vs[0]; + var e1 = b2Vec2.Subtract(p2, p1); + var e2 = b2Vec2.Subtract(p3, p1); + var D = b2Cross_v2_v2(e1, e2); + var triangleArea = 0.5 * D; + area += triangleArea; + c.Add(b2Vec2.Multiply(triangleArea, b2Vec2.Multiply(inv3, b2Vec2.Add(b2Vec2.Add(p1, p2), p3)))) + } + c.Multiply(1 / area); + return c +}; +b2PolygonShape._extend(b2Shape); +"use strict"; + +function b2Pair() { + this.proxyIdA = 0; + this.proxyIdB = 0 +} + +function b2PairLessThan(pair1, pair2) { + if (pair1.proxyIdA == pair2.proxyIdA) { + return pair1.proxyIdB - pair2.proxyIdB + } + return pair1.proxyIdA - pair2.proxyIdA +} + +function b2BroadPhase() { + this.m_tree = new b2DynamicTree(); + this.m_queryProxyId = 0; + this.m_proxyCount = 0; + this.m_pairCount = 0; + this.m_pairBuffer = []; + this.m_moveCount = 0; + this.m_moveBuffer = [] +} +b2BroadPhase.prototype = { + CreateProxy: function (aabb, userData) { + var proxyId = this.m_tree.CreateProxy(aabb, userData); + ++this.m_proxyCount; + this.BufferMove(proxyId); + return proxyId + }, + DestroyProxy: function (proxyId) { + this.UnBufferMove(proxyId); + --this.m_proxyCount; + this.m_tree.DestroyProxy(proxyId) + }, + MoveProxy: function (proxyId, aabb, displacement) { + var buffer = this.m_tree.MoveProxy(proxyId, aabb, displacement); + if (buffer) { + this.BufferMove(proxyId) + } + }, + TouchProxy: function (proxyId) { + this.BufferMove(proxyId) + }, + GetFatAABB: function (proxyId) { + return this.m_tree.GetFatAABB(proxyId) + }, + GetUserData: function (proxyId) { + return this.m_tree.GetUserData(proxyId) + }, + TestOverlap: function (proxyIdA, proxyIdB) { + var aabbA = this.m_tree.GetFatAABB(proxyIdA); + var aabbB = this.m_tree.GetFatAABB(proxyIdB); + return b2TestOverlap(aabbA, aabbB) + }, + GetProxyCount: function () { + return this.m_proxyCount + }, + UpdatePairs: function (callback) { + this.m_pairCount = 0; + this.m_pairBuffer.length = 0; + for (var i = 0; i < this.m_moveCount; ++i) { + this.m_queryProxyId = this.m_moveBuffer[i]; + if (this.m_queryProxyId == b2BroadPhase.e_nullProxy) { + continue + } + var fatAABB = this.m_tree.GetFatAABB(this.m_queryProxyId); + this.m_tree.Query(this, fatAABB) + } + this.m_moveCount = 0; + this.m_pairBuffer.sort(b2PairLessThan); + var i = 0; + while (i < this.m_pairCount) { + var primaryPair = this.m_pairBuffer[i]; + var userDataA = this.m_tree.GetUserData(primaryPair.proxyIdA); + var userDataB = this.m_tree.GetUserData(primaryPair.proxyIdB); + callback.AddPair(userDataA, userDataB); + ++i; while (i < this.m_pairCount) { - var primaryPair = this.m_pairBuffer[i]; - var userDataA = this.m_tree.GetUserData(primaryPair.proxyIdA); - var userDataB = this.m_tree.GetUserData(primaryPair.proxyIdB); - callback.AddPair(userDataA, userDataB); - ++i; - while (i < this.m_pairCount) { - var pair = this.m_pairBuffer[i]; - if (pair.proxyIdA != primaryPair.proxyIdA || pair.proxyIdB != primaryPair.proxyIdB) { - break - }++i - } + var pair = this.m_pairBuffer[i]; + if (pair.proxyIdA != primaryPair.proxyIdA || pair.proxyIdB != primaryPair.proxyIdB) { + break + }++i } - }, - Query: function (callback, aabb) { - this.m_tree.Query(callback, aabb) - }, - RayCast: function (callback, input) { - this.m_tree.RayCast(callback, input) - }, - GetTreeHeight: function () { - return this.m_tree.GetHeight() - }, - GetTreeBalance: function () { - return this.m_tree.GetMaxBalance() - }, - GetTreeQuality: function () { - return this.m_tree.GetAreaRatio() - }, - ShiftOrigin: function (newOrigin) { - this.m_tree.ShiftOrigin(newOrigin) - }, - BufferMove: function (proxyId) { - this.m_moveBuffer[this.m_moveCount] = proxyId; - ++this.m_moveCount - }, - UnBufferMove: function (proxyId) { - for (var i = 0; i < this.m_moveCount; ++i) { - if (this.m_moveBuffer[i] == proxyId) { - this.m_moveBuffer[i] = b2BroadPhase.e_nullProxy - } + } + }, + Query: function (callback, aabb) { + this.m_tree.Query(callback, aabb) + }, + RayCast: function (callback, input) { + this.m_tree.RayCast(callback, input) + }, + GetTreeHeight: function () { + return this.m_tree.GetHeight() + }, + GetTreeBalance: function () { + return this.m_tree.GetMaxBalance() + }, + GetTreeQuality: function () { + return this.m_tree.GetAreaRatio() + }, + ShiftOrigin: function (newOrigin) { + this.m_tree.ShiftOrigin(newOrigin) + }, + BufferMove: function (proxyId) { + this.m_moveBuffer[this.m_moveCount] = proxyId; + ++this.m_moveCount + }, + UnBufferMove: function (proxyId) { + for (var i = 0; i < this.m_moveCount; ++i) { + if (this.m_moveBuffer[i] == proxyId) { + this.m_moveBuffer[i] = b2BroadPhase.e_nullProxy } - }, - QueryCallback: function (proxyId) { - if (proxyId == this.m_queryProxyId) { - return true - } - this.m_pairBuffer[this.m_pairCount] = new b2Pair(); - this.m_pairBuffer[this.m_pairCount].proxyIdA = b2Min(proxyId, this.m_queryProxyId); - this.m_pairBuffer[this.m_pairCount].proxyIdB = b2Max(proxyId, this.m_queryProxyId); - ++this.m_pairCount; + } + }, + QueryCallback: function (proxyId) { + if (proxyId == this.m_queryProxyId) { return true } - }; - b2BroadPhase.e_nullProxy = -1; - "use strict"; - - function b2DistanceProxy() { - this.m_vertices = null; - this.m_count = 0; - this.m_radius = 0 + this.m_pairBuffer[this.m_pairCount] = new b2Pair(); + this.m_pairBuffer[this.m_pairCount].proxyIdA = b2Min(proxyId, this.m_queryProxyId); + this.m_pairBuffer[this.m_pairCount].proxyIdB = b2Max(proxyId, this.m_queryProxyId); + ++this.m_pairCount; + return true } - b2DistanceProxy.prototype = { - Assign: function (l) { - this.m_vertices = l.m_vertices; - this.m_count = l.m_count; - this.m_radius = l.m_radius - }, - Set: function (shape, index) { - switch (shape.GetType()) { - case b2Shape.e_circle: - var circle = shape; - this.m_vertices = [circle.m_p]; - this.m_count = 1; - this.m_radius = circle.m_radius; - break; - case b2Shape.e_polygon: - var polygon = shape; - this.m_vertices = polygon.m_vertices; - this.m_count = polygon.m_count; - this.m_radius = polygon.m_radius; - break; - case b2Shape.e_chain: - var chain = shape; - this.m_vertices = [chain.m_vertices[index]]; - if (index + 1 < chain.m_count) { - this.m_vertices[1] = chain.m_vertices[index + 1] - } else { - this.m_vertices[1] = chain.m_vertices[0] - } - this.m_count = 2; - this.m_radius = chain.m_radius; - break; - case b2Shape.e_edge: - var edge = shape; - this.m_vertices = [edge.m_vertex1, edge.m_vertex2]; - this.m_count = 2; - this.m_radius = edge.m_radius; - break - } - }, - GetSupport: function (dx, dy) { - var bestIndex = 0; - var bestValue = this.m_vertices[0].x * dx + this.m_vertices[0].y * dy; - for (var i = 1; i < this.m_count; ++i) { - var value = this.m_vertices[i].x * dx + this.m_vertices[i].y * dy; - if (value > bestValue) { - bestIndex = i; - bestValue = value - } - } - return bestIndex - }, - GetSupportVertex: function (dx, dy) { - return this.m_vertices[this.GetSupport(dx, dy)] - }, - GetVertexCount: function () { - return this.m_count - }, - GetVertex: function (index) { - return this.m_vertices[index] - } - }; +}; +b2BroadPhase.e_nullProxy = -1; +"use strict"; - function b2SimplexCache() { - this.metric = 0; - this.count = 0; - this.indexA = [0, 0, 0]; - this.indexB = [0, 0, 0] - } - - function b2DistanceInput() { - this.proxyA = new b2DistanceProxy(); - this.proxyB = new b2DistanceProxy(); - this.transformA = new b2Transform(); - this.transformB = new b2Transform(); - this.useRadii = false - } - - function b2DistanceOutput() { - this.pointA = new b2Vec2(); - this.pointB = new b2Vec2(); - this.distance = 0; - this.iterations = 0 - } - - function b2SimplexVertex() { - this.wA = new b2Vec2(); - this.wB = new b2Vec2(); - this.w = new b2Vec2(); - this.a = 0; - this.indexA = 0; - this.indexB = 0 - } - b2SimplexVertex.prototype = { - Assign: function (l) { - this.wA.x = l.wA.x; - this.wA.y = l.wA.y; - this.wB.x = l.wB.x; - this.wB.y = l.wB.y; - this.w.x = l.w.x; - this.w.y = l.w.y; - this.a = l.a; - this.indexA = l.indexA; - this.indexB = l.indexB - } - }; - - function b2Simplex() { - this.m_v = [new b2SimplexVertex(), new b2SimplexVertex(), new b2SimplexVertex()]; - this.m_count = 0 - } - b2Simplex.prototype = { - ReadCache: function (cache, proxyA, transformA, proxyB, transformB) { - this.m_count = cache.count; - var vertices = this.m_v; - for (var i = 0; i < this.m_count; ++i) { - var v = vertices[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.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; - v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; - v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; - v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; - v.w.x = v.wB.x - v.wA.x; - v.w.y = v.wB.y - v.wA.y; - v.a = 0 - } - if (this.m_count > 1) { - var metric1 = cache.metric; - var metric2 = this.GetMetric(); - if (metric2 < 0.5 * metric1 || 2 * metric1 < metric2 || metric2 < b2_epsilon) { - this.m_count = 0 - } - } - if (this.m_count == 0) { - var v = vertices[0]; - v.indexA = 0; - v.indexB = 0; - var wALocal = proxyA.GetVertex(0); - var wBLocal = proxyB.GetVertex(0); - v.wA.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; - v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; - v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; - v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; - v.w.x = v.wB.x - v.wA.x; - v.w.y = v.wB.y - v.wA.y; - v.a = 1; - this.m_count = 1 - } - }, - WriteCache: function (cache) { - cache.metric = this.GetMetric(); - cache.count = this.m_count; - var vertices = this.m_v; - for (var i = 0; i < this.m_count; ++i) { - cache.indexA[i] = vertices[i].indexA; - cache.indexB[i] = vertices[i].indexB - } - }, - GetSearchDirection: function (p) { - switch (this.m_count) { - case 1: - p.x = -this.m_v[0].w.x; - p.y = -this.m_v[0].w.y; - break; - case 2: - var e12x = this.m_v[1].w.x - this.m_v[0].w.x; - var e12y = this.m_v[1].w.y - this.m_v[0].w.y; - var sgn = e12x * -this.m_v[0].w.y - e12y * -this.m_v[0].w.x; - if (sgn > 0) { - p.x = -1 * e12y; - p.y = 1 * e12x - } else { - p.x = 1 * e12y; - p.y = -1 * e12x - } - break - } - }, - GetClosestPoint: function (p) { - switch (this.m_count) { - case 1: - p.x = this.m_v[0].w.x; - p.y = this.m_v[0].w.y; - break; - case 2: - p.x = (this.m_v[0].a * this.m_v[0].w.x) + (this.m_v[1].a * this.m_v[1].w.x); - p.y = (this.m_v[0].a * this.m_v[0].w.y) + (this.m_v[1].a * this.m_v[1].w.y); - break; - case 3: - p.x = p.y = 0; - break - } - }, - GetWitnessPoints: function (pA, pB) { - switch (this.m_count) { - case 1: - pA.x = this.m_v[0].wA.x; - pA.y = this.m_v[0].wA.y; - pB.x = this.m_v[0].wB.x; - pB.y = this.m_v[0].wB.y; - break; - case 2: - pA.x = (this.m_v[0].a * this.m_v[0].wA.x) + (this.m_v[1].a * this.m_v[1].wA.x); - pA.y = (this.m_v[0].a * this.m_v[0].wA.y) + (this.m_v[1].a * this.m_v[1].wA.y); - pB.x = (this.m_v[0].a * this.m_v[0].wB.x) + (this.m_v[1].a * this.m_v[1].wB.x); - pB.y = (this.m_v[0].a * this.m_v[0].wB.y) + (this.m_v[1].a * this.m_v[1].wB.y); - break; - case 3: - pA.x = (this.m_v[0].a, this.m_v[0].wA.x) + (this.m_v[1].a, this.m_v[1].wA.x) + (this.m_v[2].a, this.m_v[2].wA.x); - pA.y = (this.m_v[0].a, this.m_v[0].wA.y) + (this.m_v[1].a, this.m_v[1].wA.y) + (this.m_v[2].a, this.m_v[2].wA.y); - pB.x = pA.x; - pB.y = pA.y; - break - } - }, - GetMetric: function () { - switch (this.m_count) { - case 1: - return 0; - case 2: - return b2Distance(this.m_v[0].w, this.m_v[1].w); - case 3: - return (this.m_v[1].w.x - this.m_v[0].w.x) * (this.m_v[2].w.y - this.m_v[0].w.y) - (this.m_v[1].w.y - this.m_v[0].w.y) * (this.m_v[2].w.x - this.m_v[0].w.x) - } - }, - Solve2: function () { - var w1 = this.m_v[0].w; - var w2 = this.m_v[1].w; - var e12x = w2.x - w1.x; - var e12y = w2.y - w1.y; - var d12_2 = -(w1.x * e12x + w1.y * e12y); - if (d12_2 <= 0) { - this.m_v[0].a = 1; +function b2DistanceProxy() { + this.m_vertices = null; + this.m_count = 0; + this.m_radius = 0 +} +b2DistanceProxy.prototype = { + Assign: function (l) { + this.m_vertices = l.m_vertices; + this.m_count = l.m_count; + this.m_radius = l.m_radius + }, + Set: function (shape, index) { + switch (shape.GetType()) { + case b2Shape.e_circle: + var circle = shape; + this.m_vertices = [circle.m_p]; this.m_count = 1; - return + this.m_radius = circle.m_radius; + break; + case b2Shape.e_polygon: + var polygon = shape; + this.m_vertices = polygon.m_vertices; + this.m_count = polygon.m_count; + this.m_radius = polygon.m_radius; + break; + case b2Shape.e_chain: + var chain = shape; + this.m_vertices = [chain.m_vertices[index]]; + if (index + 1 < chain.m_count) { + this.m_vertices[1] = chain.m_vertices[index + 1] + } else { + this.m_vertices[1] = chain.m_vertices[0] + } + this.m_count = 2; + this.m_radius = chain.m_radius; + break; + case b2Shape.e_edge: + var edge = shape; + this.m_vertices = [edge.m_vertex1, edge.m_vertex2]; + this.m_count = 2; + this.m_radius = edge.m_radius; + break + } + }, + GetSupport: function (dx, dy) { + var bestIndex = 0; + var bestValue = this.m_vertices[0].x * dx + this.m_vertices[0].y * dy; + for (var i = 1; i < this.m_count; ++i) { + var value = this.m_vertices[i].x * dx + this.m_vertices[i].y * dy; + if (value > bestValue) { + bestIndex = i; + bestValue = value } - var d12_1 = w2.x * e12x + w2.y * e12y; - if (d12_1 <= 0) { - this.m_v[1].a = 1; - this.m_count = 1; - this.m_v[0].Assign(this.m_v[1]); - return + } + return bestIndex + }, + GetSupportVertex: function (dx, dy) { + return this.m_vertices[this.GetSupport(dx, dy)] + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertex: function (index) { + return this.m_vertices[index] + } +}; + +function b2SimplexCache() { + this.metric = 0; + this.count = 0; + this.indexA = [0, 0, 0]; + this.indexB = [0, 0, 0] +} + +function b2DistanceInput() { + this.proxyA = new b2DistanceProxy(); + this.proxyB = new b2DistanceProxy(); + this.transformA = new b2Transform(); + this.transformB = new b2Transform(); + this.useRadii = false +} + +function b2DistanceOutput() { + this.pointA = new b2Vec2(); + this.pointB = new b2Vec2(); + this.distance = 0; + this.iterations = 0 +} + +function b2SimplexVertex() { + this.wA = new b2Vec2(); + this.wB = new b2Vec2(); + this.w = new b2Vec2(); + this.a = 0; + this.indexA = 0; + this.indexB = 0 +} +b2SimplexVertex.prototype = { + Assign: function (l) { + this.wA.x = l.wA.x; + this.wA.y = l.wA.y; + this.wB.x = l.wB.x; + this.wB.y = l.wB.y; + this.w.x = l.w.x; + this.w.y = l.w.y; + this.a = l.a; + this.indexA = l.indexA; + this.indexB = l.indexB + } +}; + +function b2Simplex() { + this.m_v = [new b2SimplexVertex(), new b2SimplexVertex(), new b2SimplexVertex()]; + this.m_count = 0 +} +b2Simplex.prototype = { + ReadCache: function (cache, proxyA, transformA, proxyB, transformB) { + this.m_count = cache.count; + var vertices = this.m_v; + for (var i = 0; i < this.m_count; ++i) { + var v = vertices[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.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; + v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; + v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; + v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; + v.w.x = v.wB.x - v.wA.x; + v.w.y = v.wB.y - v.wA.y; + v.a = 0 + } + if (this.m_count > 1) { + var metric1 = cache.metric; + var metric2 = this.GetMetric(); + if (metric2 < 0.5 * metric1 || 2 * metric1 < metric2 || metric2 < b2_epsilon) { + this.m_count = 0 } + } + if (this.m_count == 0) { + var v = vertices[0]; + v.indexA = 0; + v.indexB = 0; + var wALocal = proxyA.GetVertex(0); + var wBLocal = proxyB.GetVertex(0); + v.wA.x = (transformA.q.c * wALocal.x - transformA.q.s * wALocal.y) + transformA.p.x; + v.wA.y = (transformA.q.s * wALocal.x + transformA.q.c * wALocal.y) + transformA.p.y; + v.wB.x = (transformB.q.c * wBLocal.x - transformB.q.s * wBLocal.y) + transformB.p.x; + v.wB.y = (transformB.q.s * wBLocal.x + transformB.q.c * wBLocal.y) + transformB.p.y; + v.w.x = v.wB.x - v.wA.x; + v.w.y = v.wB.y - v.wA.y; + v.a = 1; + this.m_count = 1 + } + }, + WriteCache: function (cache) { + cache.metric = this.GetMetric(); + cache.count = this.m_count; + var vertices = this.m_v; + for (var i = 0; i < this.m_count; ++i) { + cache.indexA[i] = vertices[i].indexA; + cache.indexB[i] = vertices[i].indexB + } + }, + GetSearchDirection: function (p) { + switch (this.m_count) { + case 1: + p.x = -this.m_v[0].w.x; + p.y = -this.m_v[0].w.y; + break; + case 2: + var e12x = this.m_v[1].w.x - this.m_v[0].w.x; + var e12y = this.m_v[1].w.y - this.m_v[0].w.y; + var sgn = e12x * -this.m_v[0].w.y - e12y * -this.m_v[0].w.x; + if (sgn > 0) { + p.x = -1 * e12y; + p.y = 1 * e12x + } else { + p.x = 1 * e12y; + p.y = -1 * e12x + } + break + } + }, + GetClosestPoint: function (p) { + switch (this.m_count) { + case 1: + p.x = this.m_v[0].w.x; + p.y = this.m_v[0].w.y; + break; + case 2: + p.x = (this.m_v[0].a * this.m_v[0].w.x) + (this.m_v[1].a * this.m_v[1].w.x); + p.y = (this.m_v[0].a * this.m_v[0].w.y) + (this.m_v[1].a * this.m_v[1].w.y); + break; + case 3: + p.x = p.y = 0; + break + } + }, + GetWitnessPoints: function (pA, pB) { + switch (this.m_count) { + case 1: + pA.x = this.m_v[0].wA.x; + pA.y = this.m_v[0].wA.y; + pB.x = this.m_v[0].wB.x; + pB.y = this.m_v[0].wB.y; + break; + case 2: + pA.x = (this.m_v[0].a * this.m_v[0].wA.x) + (this.m_v[1].a * this.m_v[1].wA.x); + pA.y = (this.m_v[0].a * this.m_v[0].wA.y) + (this.m_v[1].a * this.m_v[1].wA.y); + pB.x = (this.m_v[0].a * this.m_v[0].wB.x) + (this.m_v[1].a * this.m_v[1].wB.x); + pB.y = (this.m_v[0].a * this.m_v[0].wB.y) + (this.m_v[1].a * this.m_v[1].wB.y); + break; + case 3: + pA.x = (this.m_v[0].a, this.m_v[0].wA.x) + (this.m_v[1].a, this.m_v[1].wA.x) + (this.m_v[2].a, this.m_v[2].wA.x); + pA.y = (this.m_v[0].a, this.m_v[0].wA.y) + (this.m_v[1].a, this.m_v[1].wA.y) + (this.m_v[2].a, this.m_v[2].wA.y); + pB.x = pA.x; + pB.y = pA.y; + break + } + }, + GetMetric: function () { + switch (this.m_count) { + case 1: + return 0; + case 2: + return b2Distance(this.m_v[0].w, this.m_v[1].w); + case 3: + return (this.m_v[1].w.x - this.m_v[0].w.x) * (this.m_v[2].w.y - this.m_v[0].w.y) - (this.m_v[1].w.y - this.m_v[0].w.y) * (this.m_v[2].w.x - this.m_v[0].w.x) + } + }, + Solve2: function () { + var w1 = this.m_v[0].w; + var w2 = this.m_v[1].w; + var e12x = w2.x - w1.x; + var e12y = w2.y - w1.y; + var d12_2 = -(w1.x * e12x + w1.y * e12y); + if (d12_2 <= 0) { + this.m_v[0].a = 1; + this.m_count = 1; + return + } + var d12_1 = w2.x * e12x + w2.y * e12y; + if (d12_1 <= 0) { + this.m_v[1].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[1]); + return + } + var inv_d12 = 1 / (d12_1 + d12_2); + this.m_v[0].a = d12_1 * inv_d12; + this.m_v[1].a = d12_2 * inv_d12; + this.m_count = 2 + }, + Solve3: function () { + var w1 = this.m_v[0].w; + var w2 = this.m_v[1].w; + var w3 = this.m_v[2].w; + var e12x = w2.x - w1.x; + var e12y = w2.y - w1.y; + var w1e12 = w1.x * e12x + w1.y * e12y; + var w2e12 = w2.x * e12x + w2.y * e12y; + var d12_1 = w2e12; + var d12_2 = -w1e12; + var e13x = w3.x - w1.x; + var e13y = w3.y - w1.y; + var w1e13 = w1.x * e13x + w1.y * e13y; + var w3e13 = w3.x * e13x + w3.y * e13y; + var d13_1 = w3e13; + var d13_2 = -w1e13; + var e23x = w3.x - w2.x; + var e23y = w3.y - w2.y; + var w2e23 = w2.x * e23x + w2.y * e23y; + var w3e23 = w3.x * e23x + w3.y * e23y; + var d23_1 = w3e23; + var d23_2 = -w2e23; + var n123 = e12x * e13y - e12y * e13x; + var d123_1 = n123 * (w2.x * w3.y - w2.y * w3.x); + var d123_2 = n123 * (w3.x * w1.y - w3.y * w1.x); + var d123_3 = n123 * (w1.x * w2.y - w1.y * w2.x); + if (d12_2 <= 0 && d13_2 <= 0) { + this.m_v[0].a = 1; + this.m_count = 1; + return + } + if (d12_1 > 0 && d12_2 > 0 && d123_3 <= 0) { var inv_d12 = 1 / (d12_1 + d12_2); this.m_v[0].a = d12_1 * inv_d12; this.m_v[1].a = d12_2 * inv_d12; - this.m_count = 2 - }, - Solve3: function () { - var w1 = this.m_v[0].w; - var w2 = this.m_v[1].w; - var w3 = this.m_v[2].w; - var e12x = w2.x - w1.x; - var e12y = w2.y - w1.y; - var w1e12 = w1.x * e12x + w1.y * e12y; - var w2e12 = w2.x * e12x + w2.y * e12y; - var d12_1 = w2e12; - var d12_2 = -w1e12; - var e13x = w3.x - w1.x; - var e13y = w3.y - w1.y; - var w1e13 = w1.x * e13x + w1.y * e13y; - var w3e13 = w3.x * e13x + w3.y * e13y; - var d13_1 = w3e13; - var d13_2 = -w1e13; - var e23x = w3.x - w2.x; - var e23y = w3.y - w2.y; - var w2e23 = w2.x * e23x + w2.y * e23y; - var w3e23 = w3.x * e23x + w3.y * e23y; - var d23_1 = w3e23; - var d23_2 = -w2e23; - var n123 = e12x * e13y - e12y * e13x; - var d123_1 = n123 * (w2.x * w3.y - w2.y * w3.x); - var d123_2 = n123 * (w3.x * w1.y - w3.y * w1.x); - var d123_3 = n123 * (w1.x * w2.y - w1.y * w2.x); - if (d12_2 <= 0 && d13_2 <= 0) { - this.m_v[0].a = 1; - this.m_count = 1; - return - } - if (d12_1 > 0 && d12_2 > 0 && d123_3 <= 0) { - var inv_d12 = 1 / (d12_1 + d12_2); - this.m_v[0].a = d12_1 * inv_d12; - this.m_v[1].a = d12_2 * inv_d12; - this.m_count = 2; - return - } - if (d13_1 > 0 && d13_2 > 0 && d123_2 <= 0) { - var inv_d13 = 1 / (d13_1 + d13_2); - this.m_v[0].a = d13_1 * inv_d13; - this.m_v[2].a = d13_2 * inv_d13; - this.m_count = 2; - this.m_v[1].Assign(this.m_v[2]); - return - } - if (d12_1 <= 0 && d23_2 <= 0) { - this.m_v[1].a = 1; - this.m_count = 1; - this.m_v[0].Assign(this.m_v[1]); - return - } - if (d13_1 <= 0 && d23_1 <= 0) { - this.m_v[2].a = 1; - this.m_count = 1; - this.m_v[0].Assign(this.m_v[2]); - return - } - if (d23_1 > 0 && d23_2 > 0 && d123_1 <= 0) { - var inv_d23 = 1 / (d23_1 + d23_2); - this.m_v[1].a = d23_1 * inv_d23; - this.m_v[2].a = d23_2 * inv_d23; - this.m_count = 2; - this.m_v[0].Assign(this.m_v[2]); - return - } - var inv_d123 = 1 / (d123_1 + d123_2 + d123_3); - this.m_v[0].a = d123_1 * inv_d123; - this.m_v[1].a = d123_2 * inv_d123; - this.m_v[2].a = d123_3 * inv_d123; - this.m_count = 3 - } - }; - var _b2Distance_simplex = new b2Simplex(); - var _b2Distance_normal = new b2Vec2(); - var _b2Distance_p = new b2Vec2(); - - function b2DistanceFunc(output, cache, input) { - ++b2DistanceFunc.b2_gjkCalls; - var proxyA = input.proxyA; - var proxyB = input.proxyB; - var transformA = input.transformA; - var transformB = input.transformB; - _b2Distance_simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB); - var vertices = _b2Distance_simplex.m_v; - var k_maxIters = 20; - var saveA = [0, 0, 0], - saveB = [0, 0, 0]; - var saveCount = 0; - var distanceSqr1 = b2_maxFloat; - var distanceSqr2 = distanceSqr1; - var iter = 0; - while (iter < k_maxIters) { - saveCount = _b2Distance_simplex.m_count; - for (var i = 0; i < saveCount; ++i) { - saveA[i] = vertices[i].indexA; - saveB[i] = vertices[i].indexB - } - switch (_b2Distance_simplex.m_count) { - case 1: - break; - case 2: - _b2Distance_simplex.Solve2(); - break; - case 3: - _b2Distance_simplex.Solve3(); - break - } - if (_b2Distance_simplex.m_count == 3) { - break - } - _b2Distance_simplex.GetClosestPoint(_b2Distance_p); - distanceSqr2 = _b2Distance_p.LengthSquared(); - if (distanceSqr2 >= distanceSqr1) {} - distanceSqr1 = distanceSqr2; - _b2Distance_simplex.GetSearchDirection(_b2Distance_p); - if (_b2Distance_p.LengthSquared() < b2_epsilon * b2_epsilon) { - break - } - var vertex = vertices[_b2Distance_simplex.m_count]; - vertex.indexA = proxyA.GetSupport(transformA.q.c * -_b2Distance_p.x + transformA.q.s * -_b2Distance_p.y, -transformA.q.s * -_b2Distance_p.x + transformA.q.c * -_b2Distance_p.y); - var pva = proxyA.GetVertex(vertex.indexA); - vertex.wA.x = (transformA.q.c * pva.x - transformA.q.s * pva.y) + transformA.p.x; - vertex.wA.y = (transformA.q.s * pva.x + transformA.q.c * pva.y) + transformA.p.y; - vertex.indexB = proxyB.GetSupport(transformB.q.c * _b2Distance_p.x + transformB.q.s * _b2Distance_p.y, -transformB.q.s * _b2Distance_p.x + transformB.q.c * _b2Distance_p.y); - var pvb = proxyB.GetVertex(vertex.indexB); - vertex.wB.x = (transformB.q.c * pvb.x - transformB.q.s * pvb.y) + transformB.p.x; - vertex.wB.y = (transformB.q.s * pvb.x + transformB.q.c * pvb.y) + transformB.p.y; - vertex.w.x = vertex.wB.x - vertex.wA.x; - vertex.w.y = vertex.wB.y - vertex.wA.y; - ++iter; - ++b2DistanceFunc.b2_gjkIters; - var duplicate = false; - for (var i = 0; i < saveCount; ++i) { - if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) { - duplicate = true; - break - } - } - if (duplicate) { - break - }++_b2Distance_simplex.m_count - } - b2DistanceFunc.b2_gjkMaxIters = b2Max(b2DistanceFunc.b2_gjkMaxIters, iter); - _b2Distance_simplex.GetWitnessPoints(output.pointA, output.pointB); - output.distance = b2Distance(output.pointA, output.pointB); - output.iterations = iter; - _b2Distance_simplex.WriteCache(cache); - if (input.useRadii) { - var rA = proxyA.m_radius; - var rB = proxyB.m_radius; - if (output.distance > rA + rB && output.distance > b2_epsilon) { - output.distance -= rA + rB; - _b2Distance_normal.x = output.pointB.x - output.pointA.x; - _b2Distance_normal.y = output.pointB.y - output.pointA.y; - _b2Distance_normal.Normalize(); - output.pointA.x += (rA * _b2Distance_normal.x); - output.pointA.y += (rA * _b2Distance_normal.y); - output.pointB.x -= (rB * _b2Distance_normal.x); - output.pointB.y -= (rB * _b2Distance_normal.y) - } else { - var px = (0.5 * (output.pointA.x + output.pointB.x)); - var py = (0.5 * (output.pointA.y + output.pointB.y)); - output.pointA.x = px; - output.pointA.y = py; - output.pointB.x = px; - output.pointB.y = py; - output.distance = 0 - } - } - } - b2DistanceFunc.b2_gjkCalls = 0; - b2DistanceFunc.b2_gjkIters = 0; - b2DistanceFunc.b2_gjkMaxIters = 0; - "use strict"; - var b2_nullFeature = 255; - - function b2ContactID() {} - b2ContactID.prototype = { - indexA: 0, - indexB: 0, - typeA: 0, - typeB: 0, - Reset: function () { - this.indexA = this.indexB = this.typeA = this.typeB = 0 - }, - Get: function () { - return this.indexA | (this.indexB << 8) | (this.typeA << 16) | (this.typeB << 24) - }, - Assign: function (k) { - this.indexA = k.indexA; - this.indexB = k.indexB; - this.typeA = k.typeA; - this.typeB = k.typeB - } - }; - b2ContactID.e_vertex = 0; - b2ContactID.e_face = 1; - - function b2ManifoldPoint() { - this.localPoint = new b2Vec2(); - this.normalImpulse = 0; - this.tangentImpulse = 0; - this.id = new b2ContactID() - } - b2ManifoldPoint.prototype = { - Clone: function () { - var point = new b2ManifoldPoint(); - point.localPoint.x = this.localPoint.x; - point.localPoint.y = this.localPoint.y; - point.normalImpulse = this.normalImpulse; - point.tangentImpulse = this.tangentImpulse; - point.id.Assign(this.id); - return point - } - }; - - function b2Manifold() { - this.points = new Array(b2_maxManifoldPoints); - this.localNormal = new b2Vec2(); - this.localPoint = new b2Vec2(); - this.type = 0; - this.pointCount = 0 - } - b2Manifold.prototype = { - Clone: function () { - var manifold = new b2Manifold(); - manifold.pointCount = this.pointCount; - manifold.type = this.type; - manifold.localPoint.x = this.localPoint.x; - manifold.localPoint.y = this.localPoint.y; - manifold.localNormal.x = this.localNormal.x; - manifold.localNormal.y = this.localNormal.y; - for (var i = 0; i < this.pointCount; ++i) { - manifold.points[i] = this.points[i].Clone() - } - return manifold - }, - Assign: function (manifold) { - this.pointCount = manifold.pointCount; - this.type = manifold.type; - this.localPoint.x = manifold.localPoint.x; - this.localPoint.y = manifold.localPoint.y; - this.localNormal.x = manifold.localNormal.x; - this.localNormal.y = manifold.localNormal.y; - for (var i = 0; i < this.pointCount; ++i) { - this.points[i] = manifold.points[i].Clone() - } - } - }; - b2Manifold.e_circles = 0; - b2Manifold.e_faceA = 1; - b2Manifold.e_faceB = 2; - b2Manifold.b2_nullState = 0; - b2Manifold.b2_addState = 1; - b2Manifold.b2_persistState = 2; - b2Manifold.b2_removeState = 3; - - function b2WorldManifold() { - this.normal = new b2Vec2(); - this.points = new Array(b2_maxManifoldPoints); - this.separations = new Array(b2_maxManifoldPoints) - } - b2WorldManifold.prototype = { - Initialize: function (manifold, xfA, radiusA, xfB, radiusB) { - if (manifold.pointCount == 0) { - return - } - switch (manifold.type) { - case b2Manifold.e_circles: - this.normal.x = 1; - this.normal.y = 0; - var pointAx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; - var pointAy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; - var pointBx = (xfB.q.c * manifold.points[0].localPoint.x - xfB.q.s * manifold.points[0].localPoint.y) + xfB.p.x; - var pointBy = (xfB.q.s * manifold.points[0].localPoint.x + xfB.q.c * manifold.points[0].localPoint.y) + xfB.p.y; - var cx = pointAx - pointBx; - var cy = pointAy - pointBy; - if ((cx * cx + cy * cy) > b2_epsilon * b2_epsilon) { - this.normal.x = pointBx - pointAx; - this.normal.y = pointBy - pointAy; - this.normal.Normalize() - } - var cAx = pointAx + (radiusA * this.normal.x); - var cAy = pointAy + (radiusA * this.normal.y); - var cBx = pointBx - (radiusB * this.normal.x); - var cBy = pointBy - (radiusB * this.normal.y); - this.points[0] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); - this.separations[0] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y; - break; - case b2Manifold.e_faceA: - this.normal.x = xfA.q.c * manifold.localNormal.x - xfA.q.s * manifold.localNormal.y; - this.normal.y = xfA.q.s * manifold.localNormal.x + xfA.q.c * manifold.localNormal.y; - var planePointx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; - var planePointy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; - for (var i = 0; i < manifold.pointCount; ++i) { - var clipPointx = (xfB.q.c * manifold.points[i].localPoint.x - xfB.q.s * manifold.points[i].localPoint.y) + xfB.p.x; - var clipPointy = (xfB.q.s * manifold.points[i].localPoint.x + xfB.q.c * manifold.points[i].localPoint.y) + xfB.p.y; - var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; - var cAx = clipPointx + ((radiusA - d) * this.normal.x); - var cAy = clipPointy + ((radiusA - d) * this.normal.y); - var cBx = (clipPointx - (radiusB * this.normal.x)); - var cBy = (clipPointy - (radiusB * this.normal.y)); - this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); - this.separations[i] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y - } - break; - case b2Manifold.e_faceB: - this.normal.x = xfB.q.c * manifold.localNormal.x - xfB.q.s * manifold.localNormal.y; - this.normal.y = xfB.q.s * manifold.localNormal.x + xfB.q.c * manifold.localNormal.y; - var planePointx = (xfB.q.c * manifold.localPoint.x - xfB.q.s * manifold.localPoint.y) + xfB.p.x; - var planePointy = (xfB.q.s * manifold.localPoint.x + xfB.q.c * manifold.localPoint.y) + xfB.p.y; - for (var i = 0; i < manifold.pointCount; ++i) { - var clipPointx = (xfA.q.c * manifold.points[i].localPoint.x - xfA.q.s * manifold.points[i].localPoint.y) + xfA.p.x; - var clipPointy = (xfA.q.s * manifold.points[i].localPoint.x + xfA.q.c * manifold.points[i].localPoint.y) + xfA.p.y; - var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; - var cBx = clipPointx + ((radiusB - d) * this.normal.x); - var cBy = clipPointy + ((radiusB - d) * this.normal.y); - var cAx = (clipPointx - (radiusA * this.normal.x)); - var cAy = (clipPointy - (radiusA * this.normal.y)); - this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); - this.separations[i] = (cAx - cBx) * this.normal.x + (cAy - cBy) * this.normal.y - } - this.normal.x = -this.normal.x; - this.normal.y = -this.normal.y; - break - } - } - }; - - function b2GetPointStates(state1, state2, manifold1, manifold2) { - for (var i = 0; i < b2_maxManifoldPoints; ++i) { - state1[i] = b2Manifold.b2_nullState; - state2[i] = b2Manifold.b2_nullState - } - for (var i = 0; i < manifold1.pointCount; ++i) { - var id = manifold1.points[i].id; - state1[i] = b2Manifold.b2_removeState; - for (var j = 0; j < manifold2.pointCount; ++j) { - if (manifold2.points[j].id.Get() == id.Get()) { - state1[i] = b2Manifold.b2_persistState; - break - } - } - } - for (var i = 0; i < manifold2.pointCount; ++i) { - var id = manifold2.points[i].id; - state2[i] = b2Manifold.b2_addState; - for (var j = 0; j < manifold1.pointCount; ++j) { - if (manifold1.points[j].id.Get() == id.Get()) { - state2[i] = b2Manifold.b2_persistState; - break - } - } - } - } - - function b2ClipVertex() { - this.v = new b2Vec2(); - this.id = new b2ContactID() - } - - function b2RayCastInput() { - this.p1 = new b2Vec2(), this.p2 = new b2Vec2(); - this.maxFraction = 0 - } - - function b2RayCastOutput() { - this.normal = new b2Vec2(); - this.fraction = 0 - } - - function b2AABB() { - this.lowerBound = new b2Vec2(); - this.upperBound = new b2Vec2() - } - b2AABB.prototype = { - Assign: function (other) { - this.lowerBound.x = other.lowerBound.x; - this.lowerBound.y = other.lowerBound.y; - this.upperBound.x = other.upperBound.x; - this.upperBound.y = other.upperBound.y - }, - Clone: function () { - var clone = new b2AABB(); - clone.lowerBound.x = this.lowerBound.x; - clone.lowerBound.y = this.lowerBound.y; - clone.lowerBound.x = this.lowerBound.x; - clone.lowerBound.y = this.lowerBound.y; - return clone - }, - IsValid: function () { - return (this.upperBound.x - this.lowerBound.x) >= 0 && (this.upperBound.y - this.lowerBound.y) >= 0 && this.lowerBound.IsValid() && this.upperBound.IsValid() - }, - GetCenter: function () { - return new b2Vec2(0.5 * (this.lowerBound.x + this.upperBound.x), 0.5 * (this.lowerBound.y + this.upperBound.y)) - }, - GetExtents: function () { - return new b2Vec2(0.5 * (this.upperBound.x - this.lowerBound.x), 0.5 * (this.upperBound.y - this.lowerBound.y)) - }, - GetPerimeter: function () { - return 2 * ((this.upperBound.x - this.lowerBound.x) + (this.upperBound.y - this.lowerBound.y)) - }, - Combine: function (aabb1, aabb2) { - if (aabb2) { - this.lowerBound.x = b2Min(aabb1.lowerBound.x, aabb2.lowerBound.x); - this.lowerBound.y = b2Min(aabb1.lowerBound.y, aabb2.lowerBound.y); - this.upperBound.x = b2Max(aabb1.upperBound.x, aabb2.upperBound.x); - this.upperBound.y = b2Max(aabb1.upperBound.y, aabb2.upperBound.y) - } else { - this.lowerBound.x = b2Min(this.lowerBound.x, aabb1.lowerBound.x); - this.lowerBound.y = b2Min(this.lowerBound.y, aabb1.lowerBound.y); - this.upperBound.x = b2Max(this.upperBound.x, aabb1.upperBound.x); - this.upperBound.y = b2Max(this.upperBound.y, aabb1.upperBound.y) - } - }, - Contains: function (aabb) { - return this.lowerBound.x <= aabb.lowerBound.x && this.lowerBound.y <= aabb.lowerBound.y && aabb.upperBound.x <= this.upperBound.x && aabb.upperBound.y <= this.upperBound.y - }, - RayCast: function (output, input) { - var tmin = -b2_maxFloat; - var tmax = b2_maxFloat; - var p = input.p1; - var d = b2Vec2.Subtract(input.p2, input.p1); - var absD = b2Abs_v2(d); - var normal = new b2Vec2(); - for (var i = 0; i < 2; ++i) { - if (absD.get_i(i) < b2_epsilon) { - if (p.get_i(i) < this.lowerBound.get_i(i) || this.upperBound.get_i(i) < p.get_i(i)) { - return false - } - } else { - var inv_d = 1 / d.get_i(i); - var t1 = (this.lowerBound.get_i(i) - p.get_i(i)) * inv_d; - var t2 = (this.upperBound.get_i(i) - p.get_i(i)) * inv_d; - var s = -1; - if (t1 > t2) { - var temp = t2; - t2 = t1; - t1 = temp; - s = 1 - } - if (t1 > tmin) { - normal.x = normal.y = 0; - normal.set_i(i, s); - tmin = t1 - } - tmax = b2Min(tmax, t2); - if (tmin > tmax) { - return false - } - } - } - if (tmin < 0 || input.maxFraction < tmin) { - return false - } - output.fraction = tmin; - output.normal.x = normal.x; - output.normal.y = normal.y; - return true - } - }; - - function b2CollideCircles(manifold, circleA, xfA, circleB, xfB) { - manifold.pointCount = 0; - var pA = b2Mul_t_v2(xfA, circleA.m_p); - var pB = b2Mul_t_v2(xfB, circleB.m_p); - var dx = pB.x - pA.x; - var dy = pB.y - pA.y; - var distSqr = dx * dx + dy * dy; - var rA = circleA.m_radius, - rB = circleB.m_radius; - var radius = rA + rB; - if (distSqr > radius * radius) { + this.m_count = 2; return } - manifold.type = b2Manifold.e_circles; - manifold.localPoint.x = circleA.m_p.x; - manifold.localPoint.y = circleA.m_p.y; - manifold.localNormal.x = manifold.localNormal.y = 0; + if (d13_1 > 0 && d13_2 > 0 && d123_2 <= 0) { + var inv_d13 = 1 / (d13_1 + d13_2); + this.m_v[0].a = d13_1 * inv_d13; + this.m_v[2].a = d13_2 * inv_d13; + this.m_count = 2; + this.m_v[1].Assign(this.m_v[2]); + return + } + if (d12_1 <= 0 && d23_2 <= 0) { + this.m_v[1].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[1]); + return + } + if (d13_1 <= 0 && d23_1 <= 0) { + this.m_v[2].a = 1; + this.m_count = 1; + this.m_v[0].Assign(this.m_v[2]); + return + } + if (d23_1 > 0 && d23_2 > 0 && d123_1 <= 0) { + var inv_d23 = 1 / (d23_1 + d23_2); + this.m_v[1].a = d23_1 * inv_d23; + this.m_v[2].a = d23_2 * inv_d23; + this.m_count = 2; + this.m_v[0].Assign(this.m_v[2]); + return + } + var inv_d123 = 1 / (d123_1 + d123_2 + d123_3); + this.m_v[0].a = d123_1 * inv_d123; + this.m_v[1].a = d123_2 * inv_d123; + this.m_v[2].a = d123_3 * inv_d123; + this.m_count = 3 + } +}; +var _b2Distance_simplex = new b2Simplex(); +var _b2Distance_normal = new b2Vec2(); +var _b2Distance_p = new b2Vec2(); + +function b2DistanceFunc(output, cache, input) { + ++b2DistanceFunc.b2_gjkCalls; + var proxyA = input.proxyA; + var proxyB = input.proxyB; + var transformA = input.transformA; + var transformB = input.transformB; + _b2Distance_simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB); + var vertices = _b2Distance_simplex.m_v; + var k_maxIters = 20; + var saveA = [0, 0, 0], + saveB = [0, 0, 0]; + var saveCount = 0; + var distanceSqr1 = b2_maxFloat; + var distanceSqr2 = distanceSqr1; + var iter = 0; + while (iter < k_maxIters) { + saveCount = _b2Distance_simplex.m_count; + for (var i = 0; i < saveCount; ++i) { + saveA[i] = vertices[i].indexA; + saveB[i] = vertices[i].indexB + } + switch (_b2Distance_simplex.m_count) { + case 1: + break; + case 2: + _b2Distance_simplex.Solve2(); + break; + case 3: + _b2Distance_simplex.Solve3(); + break + } + if (_b2Distance_simplex.m_count == 3) { + break + } + _b2Distance_simplex.GetClosestPoint(_b2Distance_p); + distanceSqr2 = _b2Distance_p.LengthSquared(); + if (distanceSqr2 >= distanceSqr1) {} + distanceSqr1 = distanceSqr2; + _b2Distance_simplex.GetSearchDirection(_b2Distance_p); + if (_b2Distance_p.LengthSquared() < b2_epsilon * b2_epsilon) { + break + } + var vertex = vertices[_b2Distance_simplex.m_count]; + vertex.indexA = proxyA.GetSupport(transformA.q.c * -_b2Distance_p.x + transformA.q.s * -_b2Distance_p.y, -transformA.q.s * -_b2Distance_p.x + transformA.q.c * -_b2Distance_p.y); + var pva = proxyA.GetVertex(vertex.indexA); + vertex.wA.x = (transformA.q.c * pva.x - transformA.q.s * pva.y) + transformA.p.x; + vertex.wA.y = (transformA.q.s * pva.x + transformA.q.c * pva.y) + transformA.p.y; + vertex.indexB = proxyB.GetSupport(transformB.q.c * _b2Distance_p.x + transformB.q.s * _b2Distance_p.y, -transformB.q.s * _b2Distance_p.x + transformB.q.c * _b2Distance_p.y); + var pvb = proxyB.GetVertex(vertex.indexB); + vertex.wB.x = (transformB.q.c * pvb.x - transformB.q.s * pvb.y) + transformB.p.x; + vertex.wB.y = (transformB.q.s * pvb.x + transformB.q.c * pvb.y) + transformB.p.y; + vertex.w.x = vertex.wB.x - vertex.wA.x; + vertex.w.y = vertex.wB.y - vertex.wA.y; + ++iter; + ++b2DistanceFunc.b2_gjkIters; + var duplicate = false; + for (var i = 0; i < saveCount; ++i) { + if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) { + duplicate = true; + break + } + } + if (duplicate) { + break + }++_b2Distance_simplex.m_count + } + b2DistanceFunc.b2_gjkMaxIters = b2Max(b2DistanceFunc.b2_gjkMaxIters, iter); + _b2Distance_simplex.GetWitnessPoints(output.pointA, output.pointB); + output.distance = b2Distance(output.pointA, output.pointB); + output.iterations = iter; + _b2Distance_simplex.WriteCache(cache); + if (input.useRadii) { + var rA = proxyA.m_radius; + var rB = proxyB.m_radius; + if (output.distance > rA + rB && output.distance > b2_epsilon) { + output.distance -= rA + rB; + _b2Distance_normal.x = output.pointB.x - output.pointA.x; + _b2Distance_normal.y = output.pointB.y - output.pointA.y; + _b2Distance_normal.Normalize(); + output.pointA.x += (rA * _b2Distance_normal.x); + output.pointA.y += (rA * _b2Distance_normal.y); + output.pointB.x -= (rB * _b2Distance_normal.x); + output.pointB.y -= (rB * _b2Distance_normal.y) + } else { + var px = (0.5 * (output.pointA.x + output.pointB.x)); + var py = (0.5 * (output.pointA.y + output.pointB.y)); + output.pointA.x = px; + output.pointA.y = py; + output.pointB.x = px; + output.pointB.y = py; + output.distance = 0 + } + } +} +b2DistanceFunc.b2_gjkCalls = 0; +b2DistanceFunc.b2_gjkIters = 0; +b2DistanceFunc.b2_gjkMaxIters = 0; +"use strict"; +var b2_nullFeature = 255; + +function b2ContactID() {} +b2ContactID.prototype = { + indexA: 0, + indexB: 0, + typeA: 0, + typeB: 0, + Reset: function () { + this.indexA = this.indexB = this.typeA = this.typeB = 0 + }, + Get: function () { + return this.indexA | (this.indexB << 8) | (this.typeA << 16) | (this.typeB << 24) + }, + Assign: function (k) { + this.indexA = k.indexA; + this.indexB = k.indexB; + this.typeA = k.typeA; + this.typeB = k.typeB + } +}; +b2ContactID.e_vertex = 0; +b2ContactID.e_face = 1; + +function b2ManifoldPoint() { + this.localPoint = new b2Vec2(); + this.normalImpulse = 0; + this.tangentImpulse = 0; + this.id = new b2ContactID() +} +b2ManifoldPoint.prototype = { + Clone: function () { + var point = new b2ManifoldPoint(); + point.localPoint.x = this.localPoint.x; + point.localPoint.y = this.localPoint.y; + point.normalImpulse = this.normalImpulse; + point.tangentImpulse = this.tangentImpulse; + point.id.Assign(this.id); + return point + } +}; + +function b2Manifold() { + this.points = new Array(b2_maxManifoldPoints); + this.localNormal = new b2Vec2(); + this.localPoint = new b2Vec2(); + this.type = 0; + this.pointCount = 0 +} +b2Manifold.prototype = { + Clone: function () { + var manifold = new b2Manifold(); + manifold.pointCount = this.pointCount; + manifold.type = this.type; + manifold.localPoint.x = this.localPoint.x; + manifold.localPoint.y = this.localPoint.y; + manifold.localNormal.x = this.localNormal.x; + manifold.localNormal.y = this.localNormal.y; + for (var i = 0; i < this.pointCount; ++i) { + manifold.points[i] = this.points[i].Clone() + } + return manifold + }, + Assign: function (manifold) { + this.pointCount = manifold.pointCount; + this.type = manifold.type; + this.localPoint.x = manifold.localPoint.x; + this.localPoint.y = manifold.localPoint.y; + this.localNormal.x = manifold.localNormal.x; + this.localNormal.y = manifold.localNormal.y; + for (var i = 0; i < this.pointCount; ++i) { + this.points[i] = manifold.points[i].Clone() + } + } +}; +b2Manifold.e_circles = 0; +b2Manifold.e_faceA = 1; +b2Manifold.e_faceB = 2; +b2Manifold.b2_nullState = 0; +b2Manifold.b2_addState = 1; +b2Manifold.b2_persistState = 2; +b2Manifold.b2_removeState = 3; + +function b2WorldManifold() { + this.normal = new b2Vec2(); + this.points = new Array(b2_maxManifoldPoints); + this.separations = new Array(b2_maxManifoldPoints) +} +b2WorldManifold.prototype = { + Initialize: function (manifold, xfA, radiusA, xfB, radiusB) { + if (manifold.pointCount == 0) { + return + } + switch (manifold.type) { + case b2Manifold.e_circles: + this.normal.x = 1; + this.normal.y = 0; + var pointAx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; + var pointAy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; + var pointBx = (xfB.q.c * manifold.points[0].localPoint.x - xfB.q.s * manifold.points[0].localPoint.y) + xfB.p.x; + var pointBy = (xfB.q.s * manifold.points[0].localPoint.x + xfB.q.c * manifold.points[0].localPoint.y) + xfB.p.y; + var cx = pointAx - pointBx; + var cy = pointAy - pointBy; + if ((cx * cx + cy * cy) > b2_epsilon * b2_epsilon) { + this.normal.x = pointBx - pointAx; + this.normal.y = pointBy - pointAy; + this.normal.Normalize() + } + var cAx = pointAx + (radiusA * this.normal.x); + var cAy = pointAy + (radiusA * this.normal.y); + var cBx = pointBx - (radiusB * this.normal.x); + var cBy = pointBy - (radiusB * this.normal.y); + this.points[0] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[0] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y; + break; + case b2Manifold.e_faceA: + this.normal.x = xfA.q.c * manifold.localNormal.x - xfA.q.s * manifold.localNormal.y; + this.normal.y = xfA.q.s * manifold.localNormal.x + xfA.q.c * manifold.localNormal.y; + var planePointx = (xfA.q.c * manifold.localPoint.x - xfA.q.s * manifold.localPoint.y) + xfA.p.x; + var planePointy = (xfA.q.s * manifold.localPoint.x + xfA.q.c * manifold.localPoint.y) + xfA.p.y; + for (var i = 0; i < manifold.pointCount; ++i) { + var clipPointx = (xfB.q.c * manifold.points[i].localPoint.x - xfB.q.s * manifold.points[i].localPoint.y) + xfB.p.x; + var clipPointy = (xfB.q.s * manifold.points[i].localPoint.x + xfB.q.c * manifold.points[i].localPoint.y) + xfB.p.y; + var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; + var cAx = clipPointx + ((radiusA - d) * this.normal.x); + var cAy = clipPointy + ((radiusA - d) * this.normal.y); + var cBx = (clipPointx - (radiusB * this.normal.x)); + var cBy = (clipPointy - (radiusB * this.normal.y)); + this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[i] = (cBx - cAx) * this.normal.x + (cBy - cAy) * this.normal.y + } + break; + case b2Manifold.e_faceB: + this.normal.x = xfB.q.c * manifold.localNormal.x - xfB.q.s * manifold.localNormal.y; + this.normal.y = xfB.q.s * manifold.localNormal.x + xfB.q.c * manifold.localNormal.y; + var planePointx = (xfB.q.c * manifold.localPoint.x - xfB.q.s * manifold.localPoint.y) + xfB.p.x; + var planePointy = (xfB.q.s * manifold.localPoint.x + xfB.q.c * manifold.localPoint.y) + xfB.p.y; + for (var i = 0; i < manifold.pointCount; ++i) { + var clipPointx = (xfA.q.c * manifold.points[i].localPoint.x - xfA.q.s * manifold.points[i].localPoint.y) + xfA.p.x; + var clipPointy = (xfA.q.s * manifold.points[i].localPoint.x + xfA.q.c * manifold.points[i].localPoint.y) + xfA.p.y; + var d = (clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y; + var cBx = clipPointx + ((radiusB - d) * this.normal.x); + var cBy = clipPointy + ((radiusB - d) * this.normal.y); + var cAx = (clipPointx - (radiusA * this.normal.x)); + var cAy = (clipPointy - (radiusA * this.normal.y)); + this.points[i] = new b2Vec2(0.5 * (cAx + cBx), 0.5 * (cAy + cBy)); + this.separations[i] = (cAx - cBx) * this.normal.x + (cAy - cBy) * this.normal.y + } + this.normal.x = -this.normal.x; + this.normal.y = -this.normal.y; + break + } + } +}; + +function b2GetPointStates(state1, state2, manifold1, manifold2) { + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + state1[i] = b2Manifold.b2_nullState; + state2[i] = b2Manifold.b2_nullState + } + for (var i = 0; i < manifold1.pointCount; ++i) { + var id = manifold1.points[i].id; + state1[i] = b2Manifold.b2_removeState; + for (var j = 0; j < manifold2.pointCount; ++j) { + if (manifold2.points[j].id.Get() == id.Get()) { + state1[i] = b2Manifold.b2_persistState; + break + } + } + } + for (var i = 0; i < manifold2.pointCount; ++i) { + var id = manifold2.points[i].id; + state2[i] = b2Manifold.b2_addState; + for (var j = 0; j < manifold1.pointCount; ++j) { + if (manifold1.points[j].id.Get() == id.Get()) { + state2[i] = b2Manifold.b2_persistState; + break + } + } + } +} + +function b2ClipVertex() { + this.v = new b2Vec2(); + this.id = new b2ContactID() +} + +function b2RayCastInput() { + this.p1 = new b2Vec2(), this.p2 = new b2Vec2(); + this.maxFraction = 0 +} + +function b2RayCastOutput() { + this.normal = new b2Vec2(); + this.fraction = 0 +} + +function b2AABB() { + this.lowerBound = new b2Vec2(); + this.upperBound = new b2Vec2() +} +b2AABB.prototype = { + Assign: function (other) { + this.lowerBound.x = other.lowerBound.x; + this.lowerBound.y = other.lowerBound.y; + this.upperBound.x = other.upperBound.x; + this.upperBound.y = other.upperBound.y + }, + Clone: function () { + var clone = new b2AABB(); + clone.lowerBound.x = this.lowerBound.x; + clone.lowerBound.y = this.lowerBound.y; + clone.lowerBound.x = this.lowerBound.x; + clone.lowerBound.y = this.lowerBound.y; + return clone + }, + IsValid: function () { + return (this.upperBound.x - this.lowerBound.x) >= 0 && (this.upperBound.y - this.lowerBound.y) >= 0 && this.lowerBound.IsValid() && this.upperBound.IsValid() + }, + GetCenter: function () { + return new b2Vec2(0.5 * (this.lowerBound.x + this.upperBound.x), 0.5 * (this.lowerBound.y + this.upperBound.y)) + }, + GetExtents: function () { + return new b2Vec2(0.5 * (this.upperBound.x - this.lowerBound.x), 0.5 * (this.upperBound.y - this.lowerBound.y)) + }, + GetPerimeter: function () { + return 2 * ((this.upperBound.x - this.lowerBound.x) + (this.upperBound.y - this.lowerBound.y)) + }, + Combine: function (aabb1, aabb2) { + if (aabb2) { + this.lowerBound.x = b2Min(aabb1.lowerBound.x, aabb2.lowerBound.x); + this.lowerBound.y = b2Min(aabb1.lowerBound.y, aabb2.lowerBound.y); + this.upperBound.x = b2Max(aabb1.upperBound.x, aabb2.upperBound.x); + this.upperBound.y = b2Max(aabb1.upperBound.y, aabb2.upperBound.y) + } else { + this.lowerBound.x = b2Min(this.lowerBound.x, aabb1.lowerBound.x); + this.lowerBound.y = b2Min(this.lowerBound.y, aabb1.lowerBound.y); + this.upperBound.x = b2Max(this.upperBound.x, aabb1.upperBound.x); + this.upperBound.y = b2Max(this.upperBound.y, aabb1.upperBound.y) + } + }, + Contains: function (aabb) { + return this.lowerBound.x <= aabb.lowerBound.x && this.lowerBound.y <= aabb.lowerBound.y && aabb.upperBound.x <= this.upperBound.x && aabb.upperBound.y <= this.upperBound.y + }, + RayCast: function (output, input) { + var tmin = -b2_maxFloat; + var tmax = b2_maxFloat; + var p = input.p1; + var d = b2Vec2.Subtract(input.p2, input.p1); + var absD = b2Abs_v2(d); + var normal = new b2Vec2(); + for (var i = 0; i < 2; ++i) { + if (absD.get_i(i) < b2_epsilon) { + if (p.get_i(i) < this.lowerBound.get_i(i) || this.upperBound.get_i(i) < p.get_i(i)) { + return false + } + } else { + var inv_d = 1 / d.get_i(i); + var t1 = (this.lowerBound.get_i(i) - p.get_i(i)) * inv_d; + var t2 = (this.upperBound.get_i(i) - p.get_i(i)) * inv_d; + var s = -1; + if (t1 > t2) { + var temp = t2; + t2 = t1; + t1 = temp; + s = 1 + } + if (t1 > tmin) { + normal.x = normal.y = 0; + normal.set_i(i, s); + tmin = t1 + } + tmax = b2Min(tmax, t2); + if (tmin > tmax) { + return false + } + } + } + if (tmin < 0 || input.maxFraction < tmin) { + return false + } + output.fraction = tmin; + output.normal.x = normal.x; + output.normal.y = normal.y; + return true + } +}; + +function b2CollideCircles(manifold, circleA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var pA = b2Mul_t_v2(xfA, circleA.m_p); + var pB = b2Mul_t_v2(xfB, circleB.m_p); + var dx = pB.x - pA.x; + var dy = pB.y - pA.y; + var distSqr = dx * dx + dy * dy; + var rA = circleA.m_radius, + rB = circleB.m_radius; + var radius = rA + rB; + if (distSqr > radius * radius) { + return + } + manifold.type = b2Manifold.e_circles; + manifold.localPoint.x = circleA.m_p.x; + manifold.localPoint.y = circleA.m_p.y; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.pointCount = 1; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() +} + +function b2CollidePolygonAndCircle(manifold, polygonA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var c = b2Mul_t_v2(xfB, circleB.m_p); + var cLocal = b2MulT_t_v2(xfA, c); + var normalIndex = 0; + var separation = -b2_maxFloat; + 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 = normals[i].x * (cLocal.x - vertices[i].x) + normals[i].y * (cLocal.y - vertices[i].y); + if (s > radius) { + return + } + if (s > separation) { + separation = s; + normalIndex = i + } + } + var vertIndex1 = normalIndex; + var vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; + var v1 = vertices[vertIndex1]; + var v2 = vertices[vertIndex2]; + if (separation < b2_epsilon) { manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = normals[normalIndex].x; + manifold.localNormal.y = normals[normalIndex].y; + manifold.localPoint.x = 0.5 * (v1.x + v2.x); + manifold.localPoint.y = 0.5 * (v1.y + v2.y); + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset(); + return + } + var u1 = (cLocal.x - v1.x) * (v2.x - v1.x) + (cLocal.y - v1.y) * (v2.y - v1.y); + var u2 = (cLocal.x - v2.x) * (v1.x - v2.x) + (cLocal.y - v2.y) * (v1.y - v2.y); + if (u1 <= 0) { + if (b2DistanceSquared(cLocal, v1) > radius * radius) { + return + } + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = cLocal.x - v1.x; + manifold.localNormal.y = cLocal.y - v1.y; + manifold.localNormal.Normalize(); + manifold.localPoint.x = v1.x; + manifold.localPoint.y = v1.y; manifold.points[0] = new b2ManifoldPoint(); manifold.points[0].localPoint.x = circleB.m_p.x; manifold.points[0].localPoint.y = circleB.m_p.y; manifold.points[0].id.Reset() - } - - function b2CollidePolygonAndCircle(manifold, polygonA, xfA, circleB, xfB) { - manifold.pointCount = 0; - var c = b2Mul_t_v2(xfB, circleB.m_p); - var cLocal = b2MulT_t_v2(xfA, c); - var normalIndex = 0; - var separation = -b2_maxFloat; - 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 = normals[i].x * (cLocal.x - vertices[i].x) + normals[i].y * (cLocal.y - vertices[i].y); - if (s > radius) { - return - } - if (s > separation) { - separation = s; - normalIndex = i - } - } - var vertIndex1 = normalIndex; - var vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; - var v1 = vertices[vertIndex1]; - var v2 = vertices[vertIndex2]; - if (separation < b2_epsilon) { - manifold.pointCount = 1; - manifold.type = b2Manifold.e_faceA; - manifold.localNormal.x = normals[normalIndex].x; - manifold.localNormal.y = normals[normalIndex].y; - manifold.localPoint.x = 0.5 * (v1.x + v2.x); - manifold.localPoint.y = 0.5 * (v1.y + v2.y); - manifold.points[0] = new b2ManifoldPoint(); - manifold.points[0].localPoint.x = circleB.m_p.x; - manifold.points[0].localPoint.y = circleB.m_p.y; - manifold.points[0].id.Reset(); - return - } - var u1 = (cLocal.x - v1.x) * (v2.x - v1.x) + (cLocal.y - v1.y) * (v2.y - v1.y); - var u2 = (cLocal.x - v2.x) * (v1.x - v2.x) + (cLocal.y - v2.y) * (v1.y - v2.y); - if (u1 <= 0) { - if (b2DistanceSquared(cLocal, v1) > radius * radius) { + } else { + if (u2 <= 0) { + if (b2DistanceSquared(cLocal, v2) > radius * radius) { return } manifold.pointCount = 1; manifold.type = b2Manifold.e_faceA; - manifold.localNormal.x = cLocal.x - v1.x; - manifold.localNormal.y = cLocal.y - v1.y; + manifold.localNormal.x = cLocal.x - v2.x; + manifold.localNormal.y = cLocal.y - v2.y; manifold.localNormal.Normalize(); - manifold.localPoint.x = v1.x; - manifold.localPoint.y = v1.y; + manifold.localPoint.x = v2.x; + manifold.localPoint.y = v2.y; manifold.points[0] = new b2ManifoldPoint(); manifold.points[0].localPoint.x = circleB.m_p.x; manifold.points[0].localPoint.y = circleB.m_p.y; manifold.points[0].id.Reset() } else { - if (u2 <= 0) { - if (b2DistanceSquared(cLocal, v2) > radius * radius) { - return - } - manifold.pointCount = 1; - manifold.type = b2Manifold.e_faceA; - manifold.localNormal.x = cLocal.x - v2.x; - manifold.localNormal.y = cLocal.y - v2.y; - manifold.localNormal.Normalize(); - manifold.localPoint.x = v2.x; - manifold.localPoint.y = v2.y; - manifold.points[0] = new b2ManifoldPoint(); - manifold.points[0].localPoint.x = circleB.m_p.x; - manifold.points[0].localPoint.y = circleB.m_p.y; - manifold.points[0].id.Reset() - } else { - var faceCenterx = 0.5 * (v1.x + v2.x); - var faceCentery = 0.5 * (v1.y + v2.y); - var separation = (cLocal.x - faceCenterx) * normals[vertIndex1].x + (cLocal.y - faceCentery) * normals[vertIndex1].y; - if (separation > radius) { - return - } - manifold.pointCount = 1; - manifold.type = b2Manifold.e_faceA; - manifold.localNormal.x = normals[vertIndex1].x; - manifold.localNormal.y = normals[vertIndex1].y; - manifold.localPoint.x = faceCenterx; - manifold.localPoint.y = faceCentery; - manifold.points[0] = new b2ManifoldPoint(); - manifold.points[0].localPoint.x = circleB.m_p.x; - manifold.points[0].localPoint.y = circleB.m_p.y; - manifold.points[0].id.Reset() + var faceCenterx = 0.5 * (v1.x + v2.x); + var faceCentery = 0.5 * (v1.y + v2.y); + var separation = (cLocal.x - faceCenterx) * normals[vertIndex1].x + (cLocal.y - faceCentery) * normals[vertIndex1].y; + if (separation > radius) { + return } - } - } - - function b2FindMaxSeparation(edgeIndex, 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 = b2MulT_t_t(xf2, xf1); - var bestIndex = 0; - var maxSeparation = -b2_maxFloat; - for (var i = 0; i < count1; ++i) { - var nx = xf.q.c * n1s[i].x - xf.q.s * n1s[i].y; - var ny = xf.q.s * n1s[i].x + xf.q.c * n1s[i].y; - var v1x = (xf.q.c * v1s[i].x - xf.q.s * v1s[i].y) + xf.p.x; - var v1y = (xf.q.s * v1s[i].x + xf.q.c * v1s[i].y) + xf.p.y; - var si = b2_maxFloat; - for (var j = 0; j < count2; ++j) { - var sij = nx * (v2s[j].x - v1x) + ny * (v2s[j].y - v1y); - if (sij < si) { - si = sij - } - } - if (si > maxSeparation) { - maxSeparation = si; - bestIndex = i - } - } - edgeIndex[0] = bestIndex; - return maxSeparation - } - - function b2FindIncidentEdge(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; - var t1x = xf1.q.c * normals1[edge1].x - xf1.q.s * normals1[edge1].y; - var t1y = xf1.q.s * normals1[edge1].x + xf1.q.c * normals1[edge1].y; - var normal1x = xf2.q.c * t1x + xf2.q.s * t1y; - var normal1y = -xf2.q.s * t1x + xf2.q.c * t1y; - var index = 0; - var minDot = b2_maxFloat; - for (var i = 0; i < count2; ++i) { - var dot = normal1x * normals2[i].x + normal1y * normals2[i].y; - if (dot < minDot) { - minDot = dot; - index = i - } - } - var i1 = index; - var i2 = i1 + 1 < count2 ? i1 + 1 : 0; - c[0].v.x = (xf2.q.c * vertices2[i1].x - xf2.q.s * vertices2[i1].y) + xf2.p.x; - c[0].v.y = (xf2.q.s * vertices2[i1].x + xf2.q.c * vertices2[i1].y) + xf2.p.y; - c[0].id.indexA = edge1; - c[0].id.indexB = i1; - c[0].id.typeA = b2ContactID.e_face; - c[0].id.typeB = b2ContactID.e_vertex; - c[1].v.x = (xf2.q.c * vertices2[i2].x - xf2.q.s * vertices2[i2].y) + xf2.p.x; - c[1].v.y = (xf2.q.s * vertices2[i2].x + xf2.q.c * vertices2[i2].y) + xf2.p.y; - c[1].id.indexA = edge1; - c[1].id.indexB = i2; - c[1].id.typeA = b2ContactID.e_face; - c[1].id.typeB = b2ContactID.e_vertex - } - - function b2CollidePolygons(manifold, polyA, xfA, polyB, xfB) { - manifold.pointCount = 0; - var totalRadius = polyA.m_radius + polyB.m_radius; - var edgeA = [0]; - var separationA = b2FindMaxSeparation(edgeA, polyA, xfA, polyB, xfB); - if (separationA > totalRadius) { - return - } - var edgeB = [0]; - var separationB = b2FindMaxSeparation(edgeB, polyB, xfB, polyA, xfA); - if (separationB > totalRadius) { - return - } - var poly1; - var poly2; - var xf1, xf2; - var edge1 = 0; - var flip = 0; - var k_tol = 0.1 * b2_linearSlop; - if (separationB > separationA + k_tol) { - poly1 = polyB; - poly2 = polyA; - xf1 = xfB; - xf2 = xfA; - edge1 = edgeB[0]; - manifold.type = b2Manifold.e_faceB; - flip = 1 - } else { - poly1 = polyA; - poly2 = polyB; - xf1 = xfA; - xf2 = xfB; - edge1 = edgeA[0]; + manifold.pointCount = 1; manifold.type = b2Manifold.e_faceA; - flip = 0 + manifold.localNormal.x = normals[vertIndex1].x; + manifold.localNormal.y = normals[vertIndex1].y; + manifold.localPoint.x = faceCenterx; + manifold.localPoint.y = faceCentery; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + manifold.points[0].id.Reset() } - b2FindIncidentEdge(b2CollidePolygons._local_incidentEdges, 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]; - b2CollidePolygons._localTangent.x = v12.x - v11.x; - b2CollidePolygons._localTangent.y = v12.y - v11.y; - b2CollidePolygons._localTangent.Normalize(); - var localNormalx = 1 * b2CollidePolygons._localTangent.y; - var localNormaly = -1 * b2CollidePolygons._localTangent.x; - var planePointx = 0.5 * (v11.x + v12.x); - var planePointy = 0.5 * (v11.y + v12.y); - var tangentx = xf1.q.c * b2CollidePolygons._localTangent.x - xf1.q.s * b2CollidePolygons._localTangent.y; - var tangenty = xf1.q.s * b2CollidePolygons._localTangent.x + xf1.q.c * b2CollidePolygons._localTangent.y; - var normalx = 1 * tangenty; - var normaly = -1 * tangentx; - v11 = b2Mul_t_v2(xf1, v11); - v12 = b2Mul_t_v2(xf1, v12); - var frontOffset = normalx * v11.x + normaly * v11.y; - var sideOffset1 = -(tangentx * v11.x + tangenty * v11.y) + totalRadius; - var sideOffset2 = (tangentx * v12.x + tangenty * v12.y) + totalRadius; - var clipPoints1 = new Array(2); - var clipPoints2 = new Array(2); - var np; - np = b2ClipSegmentToLine(clipPoints1, b2CollidePolygons._local_incidentEdges, -tangentx, -tangenty, sideOffset1, iv1); - if (np < 2) { - return - } - np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangentx, tangenty, sideOffset2, iv2); - if (np < 2) { - return - } - manifold.localNormal.x = localNormalx; - manifold.localNormal.y = localNormaly; - manifold.localPoint.x = planePointx; - manifold.localPoint.y = planePointy; - var pointCount = 0; - for (var i = 0; i < b2_maxManifoldPoints; ++i) { - var separation = (normalx * clipPoints2[i].v.x + normaly * clipPoints2[i].v.y) - frontOffset; - if (separation <= totalRadius) { - var cp = manifold.points[pointCount] = new b2ManifoldPoint(); - cp.localPoint.Assign(b2MulT_t_v2(xf2, clipPoints2[i].v)); - cp.id.Assign(clipPoints2[i].id); - if (flip) { - var cf = new b2ContactID(); - cf.Assign(cp.id); - cp.id.indexA = cf.indexB; - cp.id.indexB = cf.indexA; - cp.id.typeA = cf.typeB; - cp.id.typeB = cf.typeA - }++pointCount - } - } - manifold.pointCount = pointCount } - b2CollidePolygons._localTangent = new b2Vec2(); - b2CollidePolygons._local_incidentEdges = [new b2ClipVertex(), new b2ClipVertex()]; +} - function b2CollideEdgeAndCircle(manifold, edgeA, xfA, circleB, xfB) { - manifold.pointCount = 0; - var Q = b2MulT_t_v2(xfA, b2Mul_t_v2(xfB, circleB.m_p)); - var A = edgeA.m_vertex1, - B = edgeA.m_vertex2; - var ex = B.x - A.x; - var ey = B.y - A.y; - var u = ex * (B.x - Q.x) + ey * (B.y - Q.y); - var v = ex * (Q.x - A.x) + ey * (Q.y - A.y); - var radius = edgeA.m_radius + circleB.m_radius; - var cf = new b2ContactID(); - cf.indexB = 0; - cf.typeB = b2ContactID.e_vertex; - if (v <= 0) { - var P = A; - var dx = Q.x - P.x; - var dy = Q.y - P.y; - var dd = dx * dx + dy * dy; - if (dd > radius * radius) { - return +function b2FindMaxSeparation(edgeIndex, 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 = b2MulT_t_t(xf2, xf1); + var bestIndex = 0; + var maxSeparation = -b2_maxFloat; + for (var i = 0; i < count1; ++i) { + var nx = xf.q.c * n1s[i].x - xf.q.s * n1s[i].y; + var ny = xf.q.s * n1s[i].x + xf.q.c * n1s[i].y; + var v1x = (xf.q.c * v1s[i].x - xf.q.s * v1s[i].y) + xf.p.x; + var v1y = (xf.q.s * v1s[i].x + xf.q.c * v1s[i].y) + xf.p.y; + var si = b2_maxFloat; + for (var j = 0; j < count2; ++j) { + var sij = nx * (v2s[j].x - v1x) + ny * (v2s[j].y - v1y); + if (sij < si) { + si = sij } - if (edgeA.m_hasVertex0) { - var A1 = edgeA.m_vertex0; - var B1 = A; - var e1x = B1.x - A1.x; - var e1y = B1.y - A1.y; - var u1 = e1x * (B1.x - Q.x) + e1y * (B1.y - Q.y); - if (u1 > 0) { - return - } - } - cf.indexA = 0; - cf.typeA = b2ContactID.e_vertex; - manifold.pointCount = 1; - manifold.type = b2Manifold.e_circles; - manifold.localNormal.x = manifold.localNormal.y = 0; - manifold.localPoint.x = P.x; - manifold.localPoint.y = P.y; - manifold.points[0] = new b2ManifoldPoint(); - manifold.points[0].id.Assign(cf); - manifold.points[0].localPoint.x = circleB.m_p.x; - manifold.points[0].localPoint.y = circleB.m_p.y; - return } - if (u <= 0) { - var P = B; - var dx = Q.x - P.x; - var dy = Q.y - P.y; - var dd = dx * dx + dy * dy; - if (dd > radius * radius) { - return - } - if (edgeA.m_hasVertex3) { - var B2 = edgeA.m_vertex3; - var A2 = B; - var e2x = B2.x - A2.x; - var e2y = B2.y - A2.y; - var v2 = e2x * (Q.x - A2.x) + e2y * (Q.y - A2.y); - if (v2 > 0) { - return - } - } - cf.indexA = 1; - cf.typeA = b2ContactID.e_vertex; - manifold.pointCount = 1; - manifold.type = b2Manifold.e_circles; - manifold.localNormal.x = manifold.localNormal.y = 0; - manifold.localPoint.x = P.x; - manifold.localPoint.y = P.y; - manifold.points[0] = new b2ManifoldPoint(); - manifold.points[0].id.Assign(cf); - manifold.points[0].localPoint.x = circleB.m_p.x; - manifold.points[0].localPoint.y = circleB.m_p.y; - return + if (si > maxSeparation) { + maxSeparation = si; + bestIndex = i } - var den = ex * ex + ey * ey; - var Px = (1 / den) * ((u * A.x) + (v * B.x)); - var Py = (1 / den) * ((u * A.y) + (v * B.y)); - var dx = Q.x - Px; - var dy = Q.y - Py; + } + edgeIndex[0] = bestIndex; + return maxSeparation +} + +function b2FindIncidentEdge(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; + var t1x = xf1.q.c * normals1[edge1].x - xf1.q.s * normals1[edge1].y; + var t1y = xf1.q.s * normals1[edge1].x + xf1.q.c * normals1[edge1].y; + var normal1x = xf2.q.c * t1x + xf2.q.s * t1y; + var normal1y = -xf2.q.s * t1x + xf2.q.c * t1y; + var index = 0; + var minDot = b2_maxFloat; + for (var i = 0; i < count2; ++i) { + var dot = normal1x * normals2[i].x + normal1y * normals2[i].y; + if (dot < minDot) { + minDot = dot; + index = i + } + } + var i1 = index; + var i2 = i1 + 1 < count2 ? i1 + 1 : 0; + c[0].v.x = (xf2.q.c * vertices2[i1].x - xf2.q.s * vertices2[i1].y) + xf2.p.x; + c[0].v.y = (xf2.q.s * vertices2[i1].x + xf2.q.c * vertices2[i1].y) + xf2.p.y; + c[0].id.indexA = edge1; + c[0].id.indexB = i1; + c[0].id.typeA = b2ContactID.e_face; + c[0].id.typeB = b2ContactID.e_vertex; + c[1].v.x = (xf2.q.c * vertices2[i2].x - xf2.q.s * vertices2[i2].y) + xf2.p.x; + c[1].v.y = (xf2.q.s * vertices2[i2].x + xf2.q.c * vertices2[i2].y) + xf2.p.y; + c[1].id.indexA = edge1; + c[1].id.indexB = i2; + c[1].id.typeA = b2ContactID.e_face; + c[1].id.typeB = b2ContactID.e_vertex +} + +function b2CollidePolygons(manifold, polyA, xfA, polyB, xfB) { + manifold.pointCount = 0; + var totalRadius = polyA.m_radius + polyB.m_radius; + var edgeA = [0]; + var separationA = b2FindMaxSeparation(edgeA, polyA, xfA, polyB, xfB); + if (separationA > totalRadius) { + return + } + var edgeB = [0]; + var separationB = b2FindMaxSeparation(edgeB, polyB, xfB, polyA, xfA); + if (separationB > totalRadius) { + return + } + var poly1; + var poly2; + var xf1, xf2; + var edge1 = 0; + var flip = 0; + var k_tol = 0.1 * b2_linearSlop; + if (separationB > separationA + k_tol) { + poly1 = polyB; + poly2 = polyA; + xf1 = xfB; + xf2 = xfA; + edge1 = edgeB[0]; + manifold.type = b2Manifold.e_faceB; + flip = 1 + } else { + poly1 = polyA; + poly2 = polyB; + xf1 = xfA; + xf2 = xfB; + edge1 = edgeA[0]; + manifold.type = b2Manifold.e_faceA; + flip = 0 + } + b2FindIncidentEdge(b2CollidePolygons._local_incidentEdges, 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]; + b2CollidePolygons._localTangent.x = v12.x - v11.x; + b2CollidePolygons._localTangent.y = v12.y - v11.y; + b2CollidePolygons._localTangent.Normalize(); + var localNormalx = 1 * b2CollidePolygons._localTangent.y; + var localNormaly = -1 * b2CollidePolygons._localTangent.x; + var planePointx = 0.5 * (v11.x + v12.x); + var planePointy = 0.5 * (v11.y + v12.y); + var tangentx = xf1.q.c * b2CollidePolygons._localTangent.x - xf1.q.s * b2CollidePolygons._localTangent.y; + var tangenty = xf1.q.s * b2CollidePolygons._localTangent.x + xf1.q.c * b2CollidePolygons._localTangent.y; + var normalx = 1 * tangenty; + var normaly = -1 * tangentx; + v11 = b2Mul_t_v2(xf1, v11); + v12 = b2Mul_t_v2(xf1, v12); + var frontOffset = normalx * v11.x + normaly * v11.y; + var sideOffset1 = -(tangentx * v11.x + tangenty * v11.y) + totalRadius; + var sideOffset2 = (tangentx * v12.x + tangenty * v12.y) + totalRadius; + var clipPoints1 = new Array(2); + var clipPoints2 = new Array(2); + var np; + np = b2ClipSegmentToLine(clipPoints1, b2CollidePolygons._local_incidentEdges, -tangentx, -tangenty, sideOffset1, iv1); + if (np < 2) { + return + } + np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangentx, tangenty, sideOffset2, iv2); + if (np < 2) { + return + } + manifold.localNormal.x = localNormalx; + manifold.localNormal.y = localNormaly; + manifold.localPoint.x = planePointx; + manifold.localPoint.y = planePointy; + var pointCount = 0; + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + var separation = (normalx * clipPoints2[i].v.x + normaly * clipPoints2[i].v.y) - frontOffset; + if (separation <= totalRadius) { + var cp = manifold.points[pointCount] = new b2ManifoldPoint(); + cp.localPoint.Assign(b2MulT_t_v2(xf2, clipPoints2[i].v)); + cp.id.Assign(clipPoints2[i].id); + if (flip) { + var cf = new b2ContactID(); + cf.Assign(cp.id); + cp.id.indexA = cf.indexB; + cp.id.indexB = cf.indexA; + cp.id.typeA = cf.typeB; + cp.id.typeB = cf.typeA + }++pointCount + } + } + manifold.pointCount = pointCount +} +b2CollidePolygons._localTangent = new b2Vec2(); +b2CollidePolygons._local_incidentEdges = [new b2ClipVertex(), new b2ClipVertex()]; + +function b2CollideEdgeAndCircle(manifold, edgeA, xfA, circleB, xfB) { + manifold.pointCount = 0; + var Q = b2MulT_t_v2(xfA, b2Mul_t_v2(xfB, circleB.m_p)); + var A = edgeA.m_vertex1, + B = edgeA.m_vertex2; + var ex = B.x - A.x; + var ey = B.y - A.y; + var u = ex * (B.x - Q.x) + ey * (B.y - Q.y); + var v = ex * (Q.x - A.x) + ey * (Q.y - A.y); + var radius = edgeA.m_radius + circleB.m_radius; + var cf = new b2ContactID(); + cf.indexB = 0; + cf.typeB = b2ContactID.e_vertex; + if (v <= 0) { + var P = A; + var dx = Q.x - P.x; + var dy = Q.y - P.y; var dd = dx * dx + dy * dy; if (dd > radius * radius) { return } - var nx = -ey; - var ny = ex; - if (nx * (Q.x - A.x) + ny * (Q.y - A.y) < 0) { - nx = -nx; - ny = -ny + if (edgeA.m_hasVertex0) { + var A1 = edgeA.m_vertex0; + var B1 = A; + var e1x = B1.x - A1.x; + var e1y = B1.y - A1.y; + var u1 = e1x * (B1.x - Q.x) + e1y * (B1.y - Q.y); + if (u1 > 0) { + return + } } cf.indexA = 0; - cf.typeA = b2ContactID.e_face; + cf.typeA = b2ContactID.e_vertex; manifold.pointCount = 1; - manifold.type = b2Manifold.e_faceA; - manifold.localNormal.x = nx; - manifold.localNormal.y = ny; - manifold.localNormal.Normalize(); - manifold.localPoint.x = A.x; - manifold.localPoint.y = A.y; + manifold.type = b2Manifold.e_circles; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.localPoint.x = P.x; + manifold.localPoint.y = P.y; manifold.points[0] = new b2ManifoldPoint(); manifold.points[0].id.Assign(cf); manifold.points[0].localPoint.x = circleB.m_p.x; - manifold.points[0].localPoint.y = circleB.m_p.y + manifold.points[0].localPoint.y = circleB.m_p.y; + return } - - function b2EPAxis() { - this.type = 0; - this.index = 0; - this.separation = 0 - } - b2EPAxis.e_unknown = 0; - b2EPAxis.e_edgeA = 1; - b2EPAxis.e_edgeB = 2; - - function b2TempPolygon() { - this.vertices = new Array(b2_maxPolygonVertices); - this.normals = new Array(b2_maxPolygonVertices); - this.count = 0 - } - - function b2ReferenceFace() { - this.i1 = 0, this.i2 = 0; - this.v1 = new b2Vec2(), this.v2 = new b2Vec2(); - this.normal = new b2Vec2(); - this.sideNormal1 = new b2Vec2(); - this.sideOffset1 = 0; - this.sideNormal2 = new b2Vec2(); - this.sideOffset2 = 0 - } - - function b2EPCollider() { - this.m_polygonB = new b2TempPolygon(); - this.m_xf = new b2Transform(); - this.m_centroidB = new b2Vec2(); - this.m_v0 = new b2Vec2(), this.m_v1 = new b2Vec2(), this.m_v2 = new b2Vec2(), this.m_v3 = new b2Vec2(); - this.m_normal0 = new b2Vec2(), this.m_normal1 = new b2Vec2(), this.m_normal2 = new b2Vec2(); - this.m_normal = new b2Vec2(); - this.m_type1 = 0, this.m_type2 = 0; - this.m_lowerLimit = new b2Vec2(), this.m_upperLimit = new b2Vec2(); - this.m_radius = 0; - this.m_front = false - } - b2EPCollider._temp_edge = new b2Vec2(); - b2EPCollider._temp_edge0 = new b2Vec2(); - b2EPCollider._temp_edge2 = new b2Vec2(); - b2EPCollider.prototype = { - Collide: function (manifold, edgeA, xfA, polygonB, xfB) { - this.m_xf.Assign(b2MulT_t_t(xfA, xfB)); - this.m_centroidB.x = (this.m_xf.q.c * polygonB.m_centroid.x - this.m_xf.q.s * polygonB.m_centroid.y) + this.m_xf.p.x; - this.m_centroidB.y = (this.m_xf.q.s * polygonB.m_centroid.x + this.m_xf.q.c * polygonB.m_centroid.y) + this.m_xf.p.y; - this.m_v0.x = edgeA.m_vertex0.x; - this.m_v0.y = edgeA.m_vertex0.y; - this.m_v1.x = edgeA.m_vertex1.x; - this.m_v1.y = edgeA.m_vertex1.y; - this.m_v2.x = edgeA.m_vertex2.x; - this.m_v2.y = edgeA.m_vertex2.y; - this.m_v3.x = edgeA.m_vertex3.x; - this.m_v3.y = edgeA.m_vertex3.y; - var hasVertex0 = edgeA.m_hasVertex0; - var hasVertex3 = edgeA.m_hasVertex3; - b2EPCollider._temp_edge.x = this.m_v2.x - this.m_v1.x; - b2EPCollider._temp_edge.y = this.m_v2.y - this.m_v1.y; - b2EPCollider._temp_edge.Normalize(); - this.m_normal1.x = b2EPCollider._temp_edge.y; - this.m_normal1.y = -b2EPCollider._temp_edge.x; - var offset1 = this.m_normal1.x * (this.m_centroidB.x - this.m_v1.x) + this.m_normal1.y * (this.m_centroidB.y - this.m_v1.y); - var offset0 = 0, - offset2 = 0; - var convex1 = false, - convex2 = false; - if (hasVertex0) { - b2EPCollider._temp_edge0.x = this.m_v1.x - this.m_v0.x; - b2EPCollider._temp_edge0.y = this.m_v1.y - this.m_v0.y; - b2EPCollider._temp_edge0.Normalize(); - this.m_normal0.x = b2EPCollider._temp_edge0.y; - this.m_normal0.y = -b2EPCollider._temp_edge0.x; - convex1 = (b2EPCollider._temp_edge0.x * b2EPCollider._temp_edge.y - b2EPCollider._temp_edge0.y * b2EPCollider._temp_edge.x) >= 0; - offset0 = this.m_normal0.x * (this.m_centroidB.x - this.m_v0.x) + this.m_normal0.y * (this.m_centroidB.y - this.m_v0.y) + if (u <= 0) { + var P = B; + var dx = Q.x - P.x; + var dy = Q.y - P.y; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + if (edgeA.m_hasVertex3) { + var B2 = edgeA.m_vertex3; + var A2 = B; + var e2x = B2.x - A2.x; + var e2y = B2.y - A2.y; + var v2 = e2x * (Q.x - A2.x) + e2y * (Q.y - A2.y); + if (v2 > 0) { + return } - if (hasVertex3) { - b2EPCollider._temp_edge2.x = this.m_v3.x - this.m_v2.x; - b2EPCollider._temp_edge2.y = this.m_v3.y - this.m_v2.y; - b2EPCollider._temp_edge2.Normalize(); - this.m_normal2.x = b2EPCollider._temp_edge2.y; - this.m_normal2.y = -b2EPCollider._temp_edge2.x; - convex2 = (b2EPCollider._temp_edge.x * b2EPCollider._temp_edge2.y - b2EPCollider._temp_edge.y * b2EPCollider._temp_edge2.x) > 0; - offset2 = this.m_normal2.x * (this.m_centroidB.x - this.m_v2.x) + this.m_normal2.y * (this.m_centroidB.y - this.m_v2.y) - } - if (hasVertex0 && hasVertex3) { - if (convex1 && convex2) { - this.m_front = offset0 >= 0 || offset1 >= 0 || offset2 >= 0; + } + cf.indexA = 1; + cf.typeA = b2ContactID.e_vertex; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_circles; + manifold.localNormal.x = manifold.localNormal.y = 0; + manifold.localPoint.x = P.x; + manifold.localPoint.y = P.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y; + return + } + var den = ex * ex + ey * ey; + var Px = (1 / den) * ((u * A.x) + (v * B.x)); + var Py = (1 / den) * ((u * A.y) + (v * B.y)); + var dx = Q.x - Px; + var dy = Q.y - Py; + var dd = dx * dx + dy * dy; + if (dd > radius * radius) { + return + } + var nx = -ey; + var ny = ex; + if (nx * (Q.x - A.x) + ny * (Q.y - A.y) < 0) { + nx = -nx; + ny = -ny + } + cf.indexA = 0; + cf.typeA = b2ContactID.e_face; + manifold.pointCount = 1; + manifold.type = b2Manifold.e_faceA; + manifold.localNormal.x = nx; + manifold.localNormal.y = ny; + manifold.localNormal.Normalize(); + manifold.localPoint.x = A.x; + manifold.localPoint.y = A.y; + manifold.points[0] = new b2ManifoldPoint(); + manifold.points[0].id.Assign(cf); + manifold.points[0].localPoint.x = circleB.m_p.x; + manifold.points[0].localPoint.y = circleB.m_p.y +} + +function b2EPAxis() { + this.type = 0; + this.index = 0; + this.separation = 0 +} +b2EPAxis.e_unknown = 0; +b2EPAxis.e_edgeA = 1; +b2EPAxis.e_edgeB = 2; + +function b2TempPolygon() { + this.vertices = new Array(b2_maxPolygonVertices); + this.normals = new Array(b2_maxPolygonVertices); + this.count = 0 +} + +function b2ReferenceFace() { + this.i1 = 0, this.i2 = 0; + this.v1 = new b2Vec2(), this.v2 = new b2Vec2(); + this.normal = new b2Vec2(); + this.sideNormal1 = new b2Vec2(); + this.sideOffset1 = 0; + this.sideNormal2 = new b2Vec2(); + this.sideOffset2 = 0 +} + +function b2EPCollider() { + this.m_polygonB = new b2TempPolygon(); + this.m_xf = new b2Transform(); + this.m_centroidB = new b2Vec2(); + this.m_v0 = new b2Vec2(), this.m_v1 = new b2Vec2(), this.m_v2 = new b2Vec2(), this.m_v3 = new b2Vec2(); + this.m_normal0 = new b2Vec2(), this.m_normal1 = new b2Vec2(), this.m_normal2 = new b2Vec2(); + this.m_normal = new b2Vec2(); + this.m_type1 = 0, this.m_type2 = 0; + this.m_lowerLimit = new b2Vec2(), this.m_upperLimit = new b2Vec2(); + this.m_radius = 0; + this.m_front = false +} +b2EPCollider._temp_edge = new b2Vec2(); +b2EPCollider._temp_edge0 = new b2Vec2(); +b2EPCollider._temp_edge2 = new b2Vec2(); +b2EPCollider.prototype = { + Collide: function (manifold, edgeA, xfA, polygonB, xfB) { + this.m_xf.Assign(b2MulT_t_t(xfA, xfB)); + this.m_centroidB.x = (this.m_xf.q.c * polygonB.m_centroid.x - this.m_xf.q.s * polygonB.m_centroid.y) + this.m_xf.p.x; + this.m_centroidB.y = (this.m_xf.q.s * polygonB.m_centroid.x + this.m_xf.q.c * polygonB.m_centroid.y) + this.m_xf.p.y; + this.m_v0.x = edgeA.m_vertex0.x; + this.m_v0.y = edgeA.m_vertex0.y; + this.m_v1.x = edgeA.m_vertex1.x; + this.m_v1.y = edgeA.m_vertex1.y; + this.m_v2.x = edgeA.m_vertex2.x; + this.m_v2.y = edgeA.m_vertex2.y; + this.m_v3.x = edgeA.m_vertex3.x; + this.m_v3.y = edgeA.m_vertex3.y; + var hasVertex0 = edgeA.m_hasVertex0; + var hasVertex3 = edgeA.m_hasVertex3; + b2EPCollider._temp_edge.x = this.m_v2.x - this.m_v1.x; + b2EPCollider._temp_edge.y = this.m_v2.y - this.m_v1.y; + b2EPCollider._temp_edge.Normalize(); + this.m_normal1.x = b2EPCollider._temp_edge.y; + this.m_normal1.y = -b2EPCollider._temp_edge.x; + var offset1 = this.m_normal1.x * (this.m_centroidB.x - this.m_v1.x) + this.m_normal1.y * (this.m_centroidB.y - this.m_v1.y); + var offset0 = 0, + offset2 = 0; + var convex1 = false, + convex2 = false; + if (hasVertex0) { + b2EPCollider._temp_edge0.x = this.m_v1.x - this.m_v0.x; + b2EPCollider._temp_edge0.y = this.m_v1.y - this.m_v0.y; + b2EPCollider._temp_edge0.Normalize(); + this.m_normal0.x = b2EPCollider._temp_edge0.y; + this.m_normal0.y = -b2EPCollider._temp_edge0.x; + convex1 = (b2EPCollider._temp_edge0.x * b2EPCollider._temp_edge.y - b2EPCollider._temp_edge0.y * b2EPCollider._temp_edge.x) >= 0; + offset0 = this.m_normal0.x * (this.m_centroidB.x - this.m_v0.x) + this.m_normal0.y * (this.m_centroidB.y - this.m_v0.y) + } + if (hasVertex3) { + b2EPCollider._temp_edge2.x = this.m_v3.x - this.m_v2.x; + b2EPCollider._temp_edge2.y = this.m_v3.y - this.m_v2.y; + b2EPCollider._temp_edge2.Normalize(); + this.m_normal2.x = b2EPCollider._temp_edge2.y; + this.m_normal2.y = -b2EPCollider._temp_edge2.x; + convex2 = (b2EPCollider._temp_edge.x * b2EPCollider._temp_edge2.y - b2EPCollider._temp_edge.y * b2EPCollider._temp_edge2.x) > 0; + offset2 = this.m_normal2.x * (this.m_centroidB.x - this.m_v2.x) + this.m_normal2.y * (this.m_centroidB.y - this.m_v2.y) + } + if (hasVertex0 && hasVertex3) { + if (convex1 && convex2) { + this.m_front = offset0 >= 0 || offset1 >= 0 || offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + if (convex1) { + this.m_front = offset0 >= 0 || (offset1 >= 0 && offset2 >= 0); if (this.m_front) { this.m_normal.x = this.m_normal1.x; this.m_normal.y = this.m_normal1.y; this.m_lowerLimit.x = this.m_normal0.x; this.m_lowerLimit.y = this.m_normal0.y; - this.m_upperLimit.x = this.m_normal2.x; - this.m_upperLimit.y = this.m_normal2.y + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y } else { this.m_normal.x = -this.m_normal1.x; this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal1.x; - this.m_lowerLimit.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; this.m_upperLimit.x = -this.m_normal1.x; this.m_upperLimit.y = -this.m_normal1.y } } else { - if (convex1) { - this.m_front = offset0 >= 0 || (offset1 >= 0 && offset2 >= 0); + if (convex2) { + this.m_front = offset2 >= 0 || (offset0 >= 0 && offset1 >= 0); if (this.m_front) { this.m_normal.x = this.m_normal1.x; this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal0.x; - this.m_lowerLimit.y = this.m_normal0.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } else { + this.m_front = offset0 >= 0 && offset1 >= 0 && offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; this.m_upperLimit.x = this.m_normal1.x; this.m_upperLimit.y = this.m_normal1.y } else { @@ -2846,2637 +2880,2785 @@ this.m_normal.y = -this.m_normal1.y; this.m_lowerLimit.x = -this.m_normal2.x; this.m_lowerLimit.y = -this.m_normal2.y; - this.m_upperLimit.x = -this.m_normal1.x; - this.m_upperLimit.y = -this.m_normal1.y - } - } else { - if (convex2) { - this.m_front = offset2 >= 0 || (offset0 >= 0 && offset1 >= 0); - if (this.m_front) { - this.m_normal.x = this.m_normal1.x; - this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal1.x; - this.m_lowerLimit.y = this.m_normal1.y; - this.m_upperLimit.x = this.m_normal2.x; - this.m_upperLimit.y = this.m_normal2.y - } else { - this.m_normal.x = -this.m_normal1.x; - this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal1.x; - this.m_lowerLimit.y = -this.m_normal1.y; - this.m_upperLimit.x = -this.m_normal0.x; - this.m_upperLimit.y = -this.m_normal0.y - } - } else { - this.m_front = offset0 >= 0 && offset1 >= 0 && offset2 >= 0; - if (this.m_front) { - this.m_normal.x = this.m_normal1.x; - this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal1.x; - this.m_lowerLimit.y = this.m_normal1.y; - this.m_upperLimit.x = this.m_normal1.x; - this.m_upperLimit.y = this.m_normal1.y - } else { - this.m_normal.x = -this.m_normal1.x; - this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal2.x; - this.m_lowerLimit.y = -this.m_normal2.y; - this.m_upperLimit.x = -this.m_normal0.x; - this.m_upperLimit.y = -this.m_normal0.y - } - } - } - } - } else { - if (hasVertex0) { - if (convex1) { - this.m_front = offset0 >= 0 || offset1 >= 0; - if (this.m_front) { - this.m_normal.x = this.m_normal1.x; - this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal0.x; - this.m_lowerLimit.y = this.m_normal0.y; - this.m_upperLimit.x = -this.m_normal1.x; - this.m_upperLimit.y = -this.m_normal1.y - } else { - this.m_normal.x = -this.m_normal1.x; - this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal1.x; - this.m_lowerLimit.y = this.m_normal1.y; - this.m_upperLimit.x = -this.m_normal1.x; - this.m_upperLimit.y = -this.m_normal1.y - } - } else { - this.m_front = offset0 >= 0 && offset1 >= 0; - if (this.m_front) { - this.m_normal.x = this.m_normal1.x; - this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal1.x; - this.m_lowerLimit.y = this.m_normal1.y; - this.m_upperLimit.x = -this.m_normal1.x; - this.m_upperLimit.y = -this.m_normal1.y - } else { - this.m_normal.x = -this.m_normal1.x; - this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal1.x; - this.m_lowerLimit.y = this.m_normal1.y; this.m_upperLimit.x = -this.m_normal0.x; this.m_upperLimit.y = -this.m_normal0.y } } - } else { - if (hasVertex3) { - if (convex2) { - this.m_front = offset1 >= 0 || offset2 >= 0; - if (this.m_front) { - this.m_normal.x = this.m_normal1.x; - this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal1.x; - this.m_lowerLimit.y = -this.m_normal1.y; - this.m_upperLimit.x = this.m_normal2.x; - this.m_upperLimit.y = this.m_normal2.y - } else { - this.m_normal.x = -this.m_normal1.x; - this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal1.x; - this.m_lowerLimit.y = -this.m_normal1.y; - this.m_upperLimit.x = this.m_normal1.x; - this.m_upperLimit.y = this.m_normal1.y - } - } else { - this.m_front = offset1 >= 0 && offset2 >= 0; - if (this.m_front) { - this.m_normal.x = this.m_normal1.x; - this.m_normal.y = this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal1.x; - this.m_lowerLimit.y = -this.m_normal1.y; - this.m_upperLimit.x = this.m_normal1.x; - this.m_upperLimit.y = this.m_normal1.y - } else { - this.m_normal.x = -this.m_normal1.x; - this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = -this.m_normal2.x; - this.m_lowerLimit.y = -this.m_normal2.y; - this.m_upperLimit.x = this.m_normal1.x; - this.m_upperLimit.y = this.m_normal1.y - } - } + } + } + } else { + if (hasVertex0) { + if (convex1) { + this.m_front = offset0 >= 0 || offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal0.x; + this.m_lowerLimit.y = this.m_normal0.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y } else { - this.m_front = offset1 >= 0; + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } + } else { + this.m_front = offset0 >= 0 && offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal0.x; + this.m_upperLimit.y = -this.m_normal0.y + } + } + } else { + if (hasVertex3) { + if (convex2) { + this.m_front = offset1 >= 0 || offset2 >= 0; if (this.m_front) { this.m_normal.x = this.m_normal1.x; this.m_normal.y = this.m_normal1.y; this.m_lowerLimit.x = -this.m_normal1.x; this.m_lowerLimit.y = -this.m_normal1.y; - this.m_upperLimit.x = -this.m_normal1.x; - this.m_upperLimit.y = -this.m_normal1.y + this.m_upperLimit.x = this.m_normal2.x; + this.m_upperLimit.y = this.m_normal2.y } else { this.m_normal.x = -this.m_normal1.x; this.m_normal.y = -this.m_normal1.y; - this.m_lowerLimit.x = this.m_normal1.x; - this.m_lowerLimit.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } + } else { + this.m_front = offset1 >= 0 && offset2 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal2.x; + this.m_lowerLimit.y = -this.m_normal2.y; this.m_upperLimit.x = this.m_normal1.x; this.m_upperLimit.y = this.m_normal1.y } } + } else { + this.m_front = offset1 >= 0; + if (this.m_front) { + this.m_normal.x = this.m_normal1.x; + this.m_normal.y = this.m_normal1.y; + this.m_lowerLimit.x = -this.m_normal1.x; + this.m_lowerLimit.y = -this.m_normal1.y; + this.m_upperLimit.x = -this.m_normal1.x; + this.m_upperLimit.y = -this.m_normal1.y + } else { + this.m_normal.x = -this.m_normal1.x; + this.m_normal.y = -this.m_normal1.y; + this.m_lowerLimit.x = this.m_normal1.x; + this.m_lowerLimit.y = this.m_normal1.y; + this.m_upperLimit.x = this.m_normal1.x; + this.m_upperLimit.y = this.m_normal1.y + } } } - this.m_polygonB.count = polygonB.m_count; - for (var i = 0; i < polygonB.m_count; ++i) { - this.m_polygonB.vertices[i] = b2Mul_t_v2(this.m_xf, polygonB.m_vertices[i]); - this.m_polygonB.normals[i] = b2Mul_r_v2(this.m_xf.q, polygonB.m_normals[i]) - } - this.m_radius = 2 * b2_polygonRadius; - manifold.pointCount = 0; - var edgeAxis = this.ComputeEdgeSeparation(); - if (edgeAxis.type == b2EPAxis.e_unknown) { - return - } - if (edgeAxis.separation > this.m_radius) { - return - } - var polygonAxis = this.ComputePolygonSeparation(); - if (polygonAxis.type != b2EPAxis.e_unknown && polygonAxis.separation > this.m_radius) { - return - } - var k_relativeTol = 0.98; - var k_absoluteTol = 0.001; - var primaryAxis = new b2EPAxis(); - if (polygonAxis.type == b2EPAxis.e_unknown) { + } + this.m_polygonB.count = polygonB.m_count; + for (var i = 0; i < polygonB.m_count; ++i) { + this.m_polygonB.vertices[i] = b2Mul_t_v2(this.m_xf, polygonB.m_vertices[i]); + this.m_polygonB.normals[i] = b2Mul_r_v2(this.m_xf.q, polygonB.m_normals[i]) + } + this.m_radius = 2 * b2_polygonRadius; + manifold.pointCount = 0; + var edgeAxis = this.ComputeEdgeSeparation(); + if (edgeAxis.type == b2EPAxis.e_unknown) { + return + } + if (edgeAxis.separation > this.m_radius) { + return + } + var polygonAxis = this.ComputePolygonSeparation(); + if (polygonAxis.type != b2EPAxis.e_unknown && polygonAxis.separation > this.m_radius) { + return + } + var k_relativeTol = 0.98; + var k_absoluteTol = 0.001; + var primaryAxis = new b2EPAxis(); + if (polygonAxis.type == b2EPAxis.e_unknown) { + primaryAxis = edgeAxis + } else { + if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) { + primaryAxis = polygonAxis + } else { primaryAxis = edgeAxis + } + } + var ie = new Array(2); + var rf = new b2ReferenceFace(); + if (primaryAxis.type == b2EPAxis.e_edgeA) { + manifold.type = b2Manifold.e_faceA; + var bestIndex = 0; + var bestValue = this.m_normal.x * this.m_polygonB.normals[0].x + this.m_normal.y * this.m_polygonB.normals[0].y; + for (var i = 1; i < this.m_polygonB.count; ++i) { + var value = this.m_normal.x * this.m_polygonB.normals[i].x + this.m_normal.y * this.m_polygonB.normals[i].y; + if (value < bestValue) { + bestValue = value; + bestIndex = i + } + } + var i1 = bestIndex; + var i2 = i1 + 1 < this.m_polygonB.count ? i1 + 1 : 0; + ie[0] = new b2ClipVertex(); + ie[0].v.x = this.m_polygonB.vertices[i1].x; + ie[0].v.y = this.m_polygonB.vertices[i1].y; + ie[0].id.indexA = 0; + ie[0].id.indexB = i1; + ie[0].id.typeA = b2ContactID.e_face; + ie[0].id.typeB = b2ContactID.e_vertex; + ie[1] = new b2ClipVertex(); + ie[1].v.x = this.m_polygonB.vertices[i2].x; + ie[1].v.y = this.m_polygonB.vertices[i2].y; + ie[1].id.indexA = 0; + ie[1].id.indexB = i2; + ie[1].id.typeA = b2ContactID.e_face; + ie[1].id.typeB = b2ContactID.e_vertex; + if (this.m_front) { + rf.i1 = 0; + rf.i2 = 1; + rf.v1.x = this.m_v1.x; + rf.v1.y = this.m_v1.y; + rf.v2.x = this.m_v2.x; + rf.v2.y = this.m_v2.y; + rf.normal.x = this.m_normal1.x; + rf.normal.y = this.m_normal1.y } else { - if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) { - primaryAxis = polygonAxis + rf.i1 = 1; + rf.i2 = 0; + rf.v1.x = this.m_v2.x; + rf.v1.y = this.m_v2.y; + rf.v2.x = this.m_v1.x; + rf.v2.y = this.m_v1.y; + rf.normal.x = -this.m_normal1.x; + rf.normal.y = -this.m_normal1.y + } + } else { + manifold.type = b2Manifold.e_faceB; + ie[0] = new b2ClipVertex(); + ie[0].v = this.m_v1; + ie[0].id.indexA = 0; + ie[0].id.indexB = primaryAxis.index; + ie[0].id.typeA = b2ContactID.e_vertex; + ie[0].id.typeB = b2ContactID.e_face; + ie[1] = new b2ClipVertex(); + ie[1].v = this.m_v2; + ie[1].id.indexA = 0; + ie[1].id.indexB = primaryAxis.index; + ie[1].id.typeA = b2ContactID.e_vertex; + ie[1].id.typeB = b2ContactID.e_face; + rf.i1 = primaryAxis.index; + rf.i2 = rf.i1 + 1 < this.m_polygonB.count ? rf.i1 + 1 : 0; + rf.v1.x = this.m_polygonB.vertices[rf.i1].x; + rf.v1.y = this.m_polygonB.vertices[rf.i1].y; + rf.v2.x = this.m_polygonB.vertices[rf.i2].x; + rf.v2.y = this.m_polygonB.vertices[rf.i2].y; + rf.normal.x = this.m_polygonB.normals[rf.i1].x; + rf.normal.y = this.m_polygonB.normals[rf.i1].y + } + rf.sideNormal1.x = rf.normal.y; + rf.sideNormal1.y = -rf.normal.x; + rf.sideNormal2.x = -rf.sideNormal1.x; + rf.sideNormal2.y = -rf.sideNormal1.y; + rf.sideOffset1 = rf.sideNormal1.x * rf.v1.x + rf.sideNormal1.y * rf.v1.y; + rf.sideOffset2 = rf.sideNormal2.x * rf.v2.x + rf.sideNormal2.y * rf.v2.y; + var clipPoints1 = new Array(2); + var clipPoints2 = new Array(2); + var np; + np = b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1.x, rf.sideNormal1.y, rf.sideOffset1, rf.i1); + if (np < b2_maxManifoldPoints) { + return + } + np = b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2.x, rf.sideNormal2.y, rf.sideOffset2, rf.i2); + if (np < b2_maxManifoldPoints) { + return + } + if (primaryAxis.type == b2EPAxis.e_edgeA) { + manifold.localNormal.x = rf.normal.x; + manifold.localNormal.y = rf.normal.y; + manifold.localPoint.x = rf.v1.x; + manifold.localPoint.y = rf.v1.y + } else { + manifold.localNormal.x = polygonB.m_normals[rf.i1].x; + manifold.localNormal.y = polygonB.m_normals[rf.i1].y; + manifold.localPoint.x = polygonB.m_vertices[rf.i1].x; + manifold.localPoint.y = polygonB.m_vertices[rf.i1].y + } + var pointCount = 0; + for (var i = 0; i < b2_maxManifoldPoints; ++i) { + var separation = rf.normal.x * (clipPoints2[i].v.x - rf.v1.x) + rf.normal.y * (clipPoints2[i].v.y - rf.v1.y); + if (separation <= this.m_radius) { + var cp = manifold.points[pointCount] = new b2ManifoldPoint(); + if (primaryAxis.type == b2EPAxis.e_edgeA) { + cp.localPoint.Assign(b2MulT_t_v2(this.m_xf, clipPoints2[i].v)); + cp.id.Assign(clipPoints2[i].id) } else { - primaryAxis = edgeAxis - } + cp.localPoint.x = clipPoints2[i].v.x; + cp.localPoint.y = clipPoints2[i].v.y; + cp.id.typeA = clipPoints2[i].id.typeB; + cp.id.typeB = clipPoints2[i].id.typeA; + cp.id.indexA = clipPoints2[i].id.indexB; + cp.id.indexB = clipPoints2[i].id.indexA + }++pointCount } - var ie = new Array(2); - var rf = new b2ReferenceFace(); - if (primaryAxis.type == b2EPAxis.e_edgeA) { - manifold.type = b2Manifold.e_faceA; - var bestIndex = 0; - var bestValue = this.m_normal.x * this.m_polygonB.normals[0].x + this.m_normal.y * this.m_polygonB.normals[0].y; - for (var i = 1; i < this.m_polygonB.count; ++i) { - var value = this.m_normal.x * this.m_polygonB.normals[i].x + this.m_normal.y * this.m_polygonB.normals[i].y; - if (value < bestValue) { - bestValue = value; - bestIndex = i - } - } - var i1 = bestIndex; - var i2 = i1 + 1 < this.m_polygonB.count ? i1 + 1 : 0; - ie[0] = new b2ClipVertex(); - ie[0].v.x = this.m_polygonB.vertices[i1].x; - ie[0].v.y = this.m_polygonB.vertices[i1].y; - ie[0].id.indexA = 0; - ie[0].id.indexB = i1; - ie[0].id.typeA = b2ContactID.e_face; - ie[0].id.typeB = b2ContactID.e_vertex; - ie[1] = new b2ClipVertex(); - ie[1].v.x = this.m_polygonB.vertices[i2].x; - ie[1].v.y = this.m_polygonB.vertices[i2].y; - ie[1].id.indexA = 0; - ie[1].id.indexB = i2; - ie[1].id.typeA = b2ContactID.e_face; - ie[1].id.typeB = b2ContactID.e_vertex; - if (this.m_front) { - rf.i1 = 0; - rf.i2 = 1; - rf.v1.x = this.m_v1.x; - rf.v1.y = this.m_v1.y; - rf.v2.x = this.m_v2.x; - rf.v2.y = this.m_v2.y; - rf.normal.x = this.m_normal1.x; - rf.normal.y = this.m_normal1.y - } else { - rf.i1 = 1; - rf.i2 = 0; - rf.v1.x = this.m_v2.x; - rf.v1.y = this.m_v2.y; - rf.v2.x = this.m_v1.x; - rf.v2.y = this.m_v1.y; - rf.normal.x = -this.m_normal1.x; - rf.normal.y = -this.m_normal1.y - } - } else { - manifold.type = b2Manifold.e_faceB; - ie[0] = new b2ClipVertex(); - ie[0].v = this.m_v1; - ie[0].id.indexA = 0; - ie[0].id.indexB = primaryAxis.index; - ie[0].id.typeA = b2ContactID.e_vertex; - ie[0].id.typeB = b2ContactID.e_face; - ie[1] = new b2ClipVertex(); - ie[1].v = this.m_v2; - ie[1].id.indexA = 0; - ie[1].id.indexB = primaryAxis.index; - ie[1].id.typeA = b2ContactID.e_vertex; - ie[1].id.typeB = b2ContactID.e_face; - rf.i1 = primaryAxis.index; - rf.i2 = rf.i1 + 1 < this.m_polygonB.count ? rf.i1 + 1 : 0; - rf.v1.x = this.m_polygonB.vertices[rf.i1].x; - rf.v1.y = this.m_polygonB.vertices[rf.i1].y; - rf.v2.x = this.m_polygonB.vertices[rf.i2].x; - rf.v2.y = this.m_polygonB.vertices[rf.i2].y; - rf.normal.x = this.m_polygonB.normals[rf.i1].x; - rf.normal.y = this.m_polygonB.normals[rf.i1].y - } - rf.sideNormal1.x = rf.normal.y; - rf.sideNormal1.y = -rf.normal.x; - rf.sideNormal2.x = -rf.sideNormal1.x; - rf.sideNormal2.y = -rf.sideNormal1.y; - rf.sideOffset1 = rf.sideNormal1.x * rf.v1.x + rf.sideNormal1.y * rf.v1.y; - rf.sideOffset2 = rf.sideNormal2.x * rf.v2.x + rf.sideNormal2.y * rf.v2.y; - var clipPoints1 = new Array(2); - var clipPoints2 = new Array(2); - var np; - np = b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1.x, rf.sideNormal1.y, rf.sideOffset1, rf.i1); - if (np < b2_maxManifoldPoints) { - return - } - np = b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2.x, rf.sideNormal2.y, rf.sideOffset2, rf.i2); - if (np < b2_maxManifoldPoints) { - return - } - if (primaryAxis.type == b2EPAxis.e_edgeA) { - manifold.localNormal.x = rf.normal.x; - manifold.localNormal.y = rf.normal.y; - manifold.localPoint.x = rf.v1.x; - manifold.localPoint.y = rf.v1.y - } else { - manifold.localNormal.x = polygonB.m_normals[rf.i1].x; - manifold.localNormal.y = polygonB.m_normals[rf.i1].y; - manifold.localPoint.x = polygonB.m_vertices[rf.i1].x; - manifold.localPoint.y = polygonB.m_vertices[rf.i1].y - } - var pointCount = 0; - for (var i = 0; i < b2_maxManifoldPoints; ++i) { - var separation = rf.normal.x * (clipPoints2[i].v.x - rf.v1.x) + rf.normal.y * (clipPoints2[i].v.y - rf.v1.y); - if (separation <= this.m_radius) { - var cp = manifold.points[pointCount] = new b2ManifoldPoint(); - if (primaryAxis.type == b2EPAxis.e_edgeA) { - cp.localPoint.Assign(b2MulT_t_v2(this.m_xf, clipPoints2[i].v)); - cp.id.Assign(clipPoints2[i].id) - } else { - cp.localPoint.x = clipPoints2[i].v.x; - cp.localPoint.y = clipPoints2[i].v.y; - cp.id.typeA = clipPoints2[i].id.typeB; - cp.id.typeB = clipPoints2[i].id.typeA; - cp.id.indexA = clipPoints2[i].id.indexB; - cp.id.indexB = clipPoints2[i].id.indexA - }++pointCount - } - } - manifold.pointCount = pointCount - }, - ComputeEdgeSeparation: function () { - var axis = new b2EPAxis(); - axis.type = b2EPAxis.e_edgeA; - axis.index = this.m_front ? 0 : 1; - axis.separation = Number.MAX_VALUE; - for (var i = 0; i < this.m_polygonB.count; ++i) { - var s = this.m_normal.x * (this.m_polygonB.vertices[i].x - this.m_v1.x) + this.m_normal.y * (this.m_polygonB.vertices[i].y - this.m_v1.y); - if (s < axis.separation) { - axis.separation = s - } - } - return axis - }, - ComputePolygonSeparation: function () { - var axis = new b2EPAxis(); - axis.type = b2EPAxis.e_unknown; - axis.index = -1; - axis.separation = -Number.MAX_VALUE; - var perpx = -this.m_normal.y; - var perpy = this.m_normal.x; - for (var i = 0; i < this.m_polygonB.count; ++i) { - var nx = -this.m_polygonB.normals[i].x; - var ny = -this.m_polygonB.normals[i].y; - var s1 = nx * (this.m_polygonB.vertices[i].x - this.m_v1.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v1.y); - var s2 = nx * (this.m_polygonB.vertices[i].x - this.m_v2.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v2.y); - var s = b2Min(s1, s2); - if (s > this.m_radius) { - axis.type = b2EPAxis.e_edgeB; - axis.index = i; - axis.separation = s; - return axis - } - if (nx * perpx + ny * perpy >= 0) { - if ((nx - this.m_upperLimit.x) * this.m_normal.x + (ny - this.m_upperLimit.y) * this.m_normal.y < -b2_angularSlop) { - continue - } - } else { - if ((nx - this.m_lowerLimit.x) * this.m_normal.x + (ny - this.m_lowerLimit.y) * this.m_normal.y < -b2_angularSlop) { - continue - } - } - if (s > axis.separation) { - axis.type = b2EPAxis.e_edgeB; - axis.index = i; - axis.separation = s - } - } - return axis } - }; - b2EPCollider.e_isolated = 0; - b2EPCollider.e_concave = 1; - b2EPCollider.e_convex = 2; - - function b2CollideEdgeAndPolygon(manifold, edgeA, xfA, polygonB, xfB) { - b2CollideEdgeAndPolygon.collider.Collide(manifold, edgeA, xfA, polygonB, xfB) - } - b2CollideEdgeAndPolygon.collider = new b2EPCollider(); - - function b2ClipSegmentToLine(vOut, vIn, normalx, normaly, offset, vertexIndexA) { - var numOut = 0; - var distance0 = (normalx * vIn[0].v.x + normaly * vIn[0].v.y) - offset; - var distance1 = (normalx * vIn[1].v.x + normaly * vIn[1].v.y) - offset; - if (distance0 <= 0) { - vOut[numOut++] = vIn[0] - } - if (distance1 <= 0) { - vOut[numOut++] = vIn[1] - } - if (distance0 * distance1 < 0) { - var interp = distance0 / (distance0 - distance1); - vOut[numOut] = new b2ClipVertex(); - vOut[numOut].v.x = vIn[0].v.x + (interp * (vIn[1].v.x - vIn[0].v.x)); - vOut[numOut].v.y = vIn[0].v.y + (interp * (vIn[1].v.y - vIn[0].v.y)); - vOut[numOut].id.indexA = vertexIndexA; - vOut[numOut].id.indexB = vIn[0].id.indexB; - vOut[numOut].id.typeA = b2ContactID.e_vertex; - vOut[numOut].id.typeB = b2ContactID.e_face; - ++numOut - } - return numOut - } - - function b2TestShapeOverlap(shapeA, indexA, shapeB, indexB, xfA, xfB) { - b2TestShapeOverlap.input.proxyA.Set(shapeA, indexA); - b2TestShapeOverlap.input.proxyB.Set(shapeB, indexB); - b2TestShapeOverlap.input.transformA = xfA; - b2TestShapeOverlap.input.transformB = xfB; - b2TestShapeOverlap.input.useRadii = true; - b2TestShapeOverlap.cache.count = 0; - b2DistanceFunc(b2TestShapeOverlap.output, b2TestShapeOverlap.cache, b2TestShapeOverlap.input); - return b2TestShapeOverlap.output.distance < 10 * b2_epsilon - } - b2TestShapeOverlap.input = new b2DistanceInput(); - b2TestShapeOverlap.cache = new b2SimplexCache(); - b2TestShapeOverlap.output = new b2DistanceOutput(); - - function b2TestOverlap(a, b) { - return !((b.lowerBound.x - a.upperBound.x) > 0 || (b.lowerBound.y - a.upperBound.y) > 0 || (a.lowerBound.x - b.upperBound.x) > 0 || (a.lowerBound.y - b.upperBound.y) > 0) - } - "use strict"; - var b2_nullNode = -1; - - function b2TreeNode() { - this.aabb = new b2AABB(); - this.userData = null; - this.parent = 0; - this.child1 = this.child2 = this.height = 0 - } - b2TreeNode.prototype = { - IsLeaf: function () { - return this.child1 == b2_nullNode - } - }; - - function b2DynamicTree() { - this.m_root = b2_nullNode; - this.m_nodeCapacity = 16; - this.m_nodeCount = 0; - this.m_nodes = new Array(this.m_nodeCapacity); - for (var i = 0; i < this.m_nodeCapacity - 1; ++i) { - this.m_nodes[i] = new b2TreeNode(); - this.m_nodes[i].parent = i + 1; - this.m_nodes[i].height = -1 - } - this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); - this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; - this.m_nodes[this.m_nodeCapacity - 1].height = -1; - this.m_freeList = 0; - this.m_path = 0; - this.m_insertionCount = 0 - } - b2DynamicTree.aabbExtensionFattener = new b2Vec2(b2_aabbExtension, b2_aabbExtension); - b2DynamicTree.prototype = { - CreateProxy: function (aabb, userData) { - var proxyId = this.AllocateNode(); - this.m_nodes[proxyId].aabb.lowerBound.Assign(b2Vec2.Subtract(aabb.lowerBound, b2DynamicTree.aabbExtensionFattener)); - this.m_nodes[proxyId].aabb.upperBound.Assign(b2Vec2.Add(aabb.upperBound, b2DynamicTree.aabbExtensionFattener)); - this.m_nodes[proxyId].userData = userData; - this.m_nodes[proxyId].height = 0; - this.InsertLeaf(proxyId); - return proxyId - }, - DestroyProxy: function (proxyId) { - this.RemoveLeaf(proxyId); - this.FreeNode(proxyId) - }, - MoveProxy: function (proxyId, aabb, displacement) { - if (this.m_nodes[proxyId].aabb.Contains(aabb)) { - return false + manifold.pointCount = pointCount + }, + ComputeEdgeSeparation: function () { + var axis = new b2EPAxis(); + axis.type = b2EPAxis.e_edgeA; + axis.index = this.m_front ? 0 : 1; + axis.separation = Number.MAX_VALUE; + for (var i = 0; i < this.m_polygonB.count; ++i) { + var s = this.m_normal.x * (this.m_polygonB.vertices[i].x - this.m_v1.x) + this.m_normal.y * (this.m_polygonB.vertices[i].y - this.m_v1.y); + if (s < axis.separation) { + axis.separation = s } - this.RemoveLeaf(proxyId); - this.m_nodes[proxyId].aabb.Assign(aabb); - this.m_nodes[proxyId].aabb.lowerBound.Subtract(b2DynamicTree.aabbExtensionFattener); - this.m_nodes[proxyId].aabb.upperBound.Add(b2DynamicTree.aabbExtensionFattener); - var d = b2Vec2.Multiply(b2_aabbMultiplier, displacement); - if (d.x < 0) { - this.m_nodes[proxyId].aabb.lowerBound.x += d.x - } else { - this.m_nodes[proxyId].aabb.upperBound.x += d.x + } + return axis + }, + ComputePolygonSeparation: function () { + var axis = new b2EPAxis(); + axis.type = b2EPAxis.e_unknown; + axis.index = -1; + axis.separation = -Number.MAX_VALUE; + var perpx = -this.m_normal.y; + var perpy = this.m_normal.x; + for (var i = 0; i < this.m_polygonB.count; ++i) { + var nx = -this.m_polygonB.normals[i].x; + var ny = -this.m_polygonB.normals[i].y; + var s1 = nx * (this.m_polygonB.vertices[i].x - this.m_v1.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v1.y); + var s2 = nx * (this.m_polygonB.vertices[i].x - this.m_v2.x) + ny * (this.m_polygonB.vertices[i].y - this.m_v2.y); + var s = b2Min(s1, s2); + if (s > this.m_radius) { + axis.type = b2EPAxis.e_edgeB; + axis.index = i; + axis.separation = s; + return axis } - if (d.y < 0) { - this.m_nodes[proxyId].aabb.lowerBound.y += d.y - } else { - this.m_nodes[proxyId].aabb.upperBound.y += d.y - } - this.InsertLeaf(proxyId); - return true - }, - GetUserData: function (proxyId) { - return this.m_nodes[proxyId].userData - }, - GetFatAABB: function (proxyId) { - return this.m_nodes[proxyId].aabb - }, - Query: function (callback, aabb) { - var stack = []; - stack.push(this.m_root); - while (stack.length > 0) { - var nodeId = stack.pop(); - if (nodeId == b2_nullNode) { + if (nx * perpx + ny * perpy >= 0) { + if ((nx - this.m_upperLimit.x) * this.m_normal.x + (ny - this.m_upperLimit.y) * this.m_normal.y < -b2_angularSlop) { continue } - var node = this.m_nodes[nodeId]; - if (b2TestOverlap(node.aabb, aabb)) { - if (node.IsLeaf()) { - var proceed = callback.QueryCallback(nodeId); - if (proceed == false) { - return - } - } else { - stack.push(node.child1); - stack.push(node.child2) - } + } else { + if ((nx - this.m_lowerLimit.x) * this.m_normal.x + (ny - this.m_lowerLimit.y) * this.m_normal.y < -b2_angularSlop) { + continue } } - }, - RayCast: function (callback, input) { - var p1 = input.p1; - var p2 = input.p2; - var r = b2Vec2.Subtract(p2, p1); - r.Normalize(); - var v = b2Cross_f_v2(1, r); - var abs_v = b2Abs_v2(v); - var maxFraction = input.maxFraction; - var segmentAABB = new b2AABB(); - var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); - segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); - segmentAABB.upperBound.Assign(b2Max_v2(p1, t)); - var stack = []; - stack.push(this.m_root); - while (stack.length > 0) { - var nodeId = stack.pop(); - if (nodeId == b2_nullNode) { - continue - } - var node = this.m_nodes[nodeId]; - if (b2TestOverlap(node.aabb, segmentAABB) == false) { - continue - } - var c = node.aabb.GetCenter(); - var h = node.aabb.GetExtents(); - var separation = b2Abs(b2Dot_v2_v2(v, b2Vec2.Subtract(p1, c))) - b2Dot_v2_v2(abs_v, h); - if (separation > 0) { - continue - } + if (s > axis.separation) { + axis.type = b2EPAxis.e_edgeB; + axis.index = i; + axis.separation = s + } + } + return axis + } +}; +b2EPCollider.e_isolated = 0; +b2EPCollider.e_concave = 1; +b2EPCollider.e_convex = 2; + +function b2CollideEdgeAndPolygon(manifold, edgeA, xfA, polygonB, xfB) { + b2CollideEdgeAndPolygon.collider.Collide(manifold, edgeA, xfA, polygonB, xfB) +} +b2CollideEdgeAndPolygon.collider = new b2EPCollider(); + +function b2ClipSegmentToLine(vOut, vIn, normalx, normaly, offset, vertexIndexA) { + var numOut = 0; + var distance0 = (normalx * vIn[0].v.x + normaly * vIn[0].v.y) - offset; + var distance1 = (normalx * vIn[1].v.x + normaly * vIn[1].v.y) - offset; + if (distance0 <= 0) { + vOut[numOut++] = vIn[0] + } + if (distance1 <= 0) { + vOut[numOut++] = vIn[1] + } + if (distance0 * distance1 < 0) { + var interp = distance0 / (distance0 - distance1); + vOut[numOut] = new b2ClipVertex(); + vOut[numOut].v.x = vIn[0].v.x + (interp * (vIn[1].v.x - vIn[0].v.x)); + vOut[numOut].v.y = vIn[0].v.y + (interp * (vIn[1].v.y - vIn[0].v.y)); + vOut[numOut].id.indexA = vertexIndexA; + vOut[numOut].id.indexB = vIn[0].id.indexB; + vOut[numOut].id.typeA = b2ContactID.e_vertex; + vOut[numOut].id.typeB = b2ContactID.e_face; + ++numOut + } + return numOut +} + +function b2TestShapeOverlap(shapeA, indexA, shapeB, indexB, xfA, xfB) { + b2TestShapeOverlap.input.proxyA.Set(shapeA, indexA); + b2TestShapeOverlap.input.proxyB.Set(shapeB, indexB); + b2TestShapeOverlap.input.transformA = xfA; + b2TestShapeOverlap.input.transformB = xfB; + b2TestShapeOverlap.input.useRadii = true; + b2TestShapeOverlap.cache.count = 0; + b2DistanceFunc(b2TestShapeOverlap.output, b2TestShapeOverlap.cache, b2TestShapeOverlap.input); + return b2TestShapeOverlap.output.distance < 10 * b2_epsilon +} +b2TestShapeOverlap.input = new b2DistanceInput(); +b2TestShapeOverlap.cache = new b2SimplexCache(); +b2TestShapeOverlap.output = new b2DistanceOutput(); + +function b2TestOverlap(a, b) { + return !((b.lowerBound.x - a.upperBound.x) > 0 || (b.lowerBound.y - a.upperBound.y) > 0 || (a.lowerBound.x - b.upperBound.x) > 0 || (a.lowerBound.y - b.upperBound.y) > 0) +} +"use strict"; +var b2_nullNode = -1; + +function b2TreeNode() { + this.aabb = new b2AABB(); + this.userData = null; + this.parent = 0; + this.child1 = this.child2 = this.height = 0 +} +b2TreeNode.prototype = { + IsLeaf: function () { + return this.child1 == b2_nullNode + } +}; + +function b2DynamicTree() { + this.m_root = b2_nullNode; + this.m_nodeCapacity = 16; + this.m_nodeCount = 0; + this.m_nodes = new Array(this.m_nodeCapacity); + for (var i = 0; i < this.m_nodeCapacity - 1; ++i) { + this.m_nodes[i] = new b2TreeNode(); + this.m_nodes[i].parent = i + 1; + this.m_nodes[i].height = -1 + } + this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); + this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; + this.m_nodes[this.m_nodeCapacity - 1].height = -1; + this.m_freeList = 0; + this.m_path = 0; + this.m_insertionCount = 0 +} +b2DynamicTree.aabbExtensionFattener = new b2Vec2(b2_aabbExtension, b2_aabbExtension); +b2DynamicTree.prototype = { + CreateProxy: function (aabb, userData) { + var proxyId = this.AllocateNode(); + this.m_nodes[proxyId].aabb.lowerBound.Assign(b2Vec2.Subtract(aabb.lowerBound, b2DynamicTree.aabbExtensionFattener)); + this.m_nodes[proxyId].aabb.upperBound.Assign(b2Vec2.Add(aabb.upperBound, b2DynamicTree.aabbExtensionFattener)); + this.m_nodes[proxyId].userData = userData; + this.m_nodes[proxyId].height = 0; + this.InsertLeaf(proxyId); + return proxyId + }, + DestroyProxy: function (proxyId) { + this.RemoveLeaf(proxyId); + this.FreeNode(proxyId) + }, + MoveProxy: function (proxyId, aabb, displacement) { + if (this.m_nodes[proxyId].aabb.Contains(aabb)) { + return false + } + this.RemoveLeaf(proxyId); + this.m_nodes[proxyId].aabb.Assign(aabb); + this.m_nodes[proxyId].aabb.lowerBound.Subtract(b2DynamicTree.aabbExtensionFattener); + this.m_nodes[proxyId].aabb.upperBound.Add(b2DynamicTree.aabbExtensionFattener); + var d = b2Vec2.Multiply(b2_aabbMultiplier, displacement); + if (d.x < 0) { + this.m_nodes[proxyId].aabb.lowerBound.x += d.x + } else { + this.m_nodes[proxyId].aabb.upperBound.x += d.x + } + if (d.y < 0) { + this.m_nodes[proxyId].aabb.lowerBound.y += d.y + } else { + this.m_nodes[proxyId].aabb.upperBound.y += d.y + } + this.InsertLeaf(proxyId); + return true + }, + GetUserData: function (proxyId) { + return this.m_nodes[proxyId].userData + }, + GetFatAABB: function (proxyId) { + return this.m_nodes[proxyId].aabb + }, + Query: function (callback, aabb) { + var stack = []; + stack.push(this.m_root); + while (stack.length > 0) { + var nodeId = stack.pop(); + if (nodeId == b2_nullNode) { + continue + } + var node = this.m_nodes[nodeId]; + if (b2TestOverlap(node.aabb, aabb)) { if (node.IsLeaf()) { - var subInput = new b2RayCastInput(); - subInput.p1.Assign(input.p1); - subInput.p2.Assign(input.p2); - subInput.maxFraction = maxFraction; - var value = callback.RayCastCallback(subInput, nodeId); - if (value == 0) { + var proceed = callback.QueryCallback(nodeId); + if (proceed == false) { return } - if (value > 0) { - maxFraction = value; - var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); - segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); - segmentAABB.upperBound.Assign(b2Max_v2(p1, t)) - } } else { stack.push(node.child1); stack.push(node.child2) } } - }, - Validate: function () { - this.ValidateStructure(this.m_root); - this.ValidateMetrics(this.m_root); - var freeCount = 0; - var freeIndex = this.m_freeList; - while (freeIndex != b2_nullNode) { - freeIndex = this.m_nodes[freeIndex].parent; - ++freeCount + } + }, + RayCast: function (callback, input) { + var p1 = input.p1; + var p2 = input.p2; + var r = b2Vec2.Subtract(p2, p1); + r.Normalize(); + var v = b2Cross_f_v2(1, r); + var abs_v = b2Abs_v2(v); + var maxFraction = input.maxFraction; + var segmentAABB = new b2AABB(); + var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); + segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); + segmentAABB.upperBound.Assign(b2Max_v2(p1, t)); + var stack = []; + stack.push(this.m_root); + while (stack.length > 0) { + var nodeId = stack.pop(); + if (nodeId == b2_nullNode) { + continue } - }, - GetHeight: function () { - if (this.m_root == b2_nullNode) { - return 0 + var node = this.m_nodes[nodeId]; + if (b2TestOverlap(node.aabb, segmentAABB) == false) { + continue } - return this.m_nodes[this.m_root].height - }, - GetMaxBalance: function () { - var maxBalance = 0; - for (var i = 0; i < this.m_nodeCapacity; ++i) { - var node = this.m_nodes[i]; - if (node.height <= 1) { - continue + var c = node.aabb.GetCenter(); + var h = node.aabb.GetExtents(); + var separation = b2Abs(b2Dot_v2_v2(v, b2Vec2.Subtract(p1, c))) - b2Dot_v2_v2(abs_v, h); + if (separation > 0) { + continue + } + if (node.IsLeaf()) { + var subInput = new b2RayCastInput(); + subInput.p1.Assign(input.p1); + subInput.p2.Assign(input.p2); + subInput.maxFraction = maxFraction; + var value = callback.RayCastCallback(subInput, nodeId); + if (value == 0) { + return } - var child1 = node.child1; - var child2 = node.child2; - var balance = b2Abs(this.m_nodes[child2].height - this.m_nodes[child1].height); - maxBalance = b2Max(maxBalance, balance) - } - return maxBalance - }, - GetAreaRatio: function () { - if (this.m_root == b2_nullNode) { - return 0 - } - var root = this.m_nodes[this.m_root]; - var rootArea = root.aabb.GetPerimeter(); - var totalArea = 0; - for (var i = 0; i < this.m_nodeCapacity; ++i) { - var node = this.m_nodes[i]; - if (node.height < 0) { - continue + if (value > 0) { + maxFraction = value; + var t = b2Vec2.Add(p1, b2Vec2.Multiply(maxFraction, b2Vec2.Subtract(p2, p1))); + segmentAABB.lowerBound.Assign(b2Min_v2(p1, t)); + segmentAABB.upperBound.Assign(b2Max_v2(p1, t)) } - totalArea += node.aabb.GetPerimeter() + } else { + stack.push(node.child1); + stack.push(node.child2) } - return totalArea / rootArea - }, - RebuildBottomUp: function () { - var nodes = new Array(this.m_nodeCount); - var count = 0; - for (var i = 0; i < this.m_nodeCapacity; ++i) { - if (this.m_nodes[i].height < 0) { - continue - } - if (this.m_nodes[i].IsLeaf()) { - this.m_nodes[i].parent = b2_nullNode; - nodes[count] = i; - ++count - } else { - this.FreeNode(i) - } + } + }, + Validate: function () { + this.ValidateStructure(this.m_root); + this.ValidateMetrics(this.m_root); + var freeCount = 0; + var freeIndex = this.m_freeList; + while (freeIndex != b2_nullNode) { + freeIndex = this.m_nodes[freeIndex].parent; + ++freeCount + } + }, + GetHeight: function () { + if (this.m_root == b2_nullNode) { + return 0 + } + return this.m_nodes[this.m_root].height + }, + GetMaxBalance: function () { + var maxBalance = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + var node = this.m_nodes[i]; + if (node.height <= 1) { + continue } - while (count > 1) { - var minCost = b2_maxFloat; - var iMin = -1, - jMin = -1; - for (i = 0; i < count; ++i) { - var aabbi = this.m_nodes[nodes[i]].aabb; - for (var j = i + 1; j < count; ++j) { - var aabbj = this.m_nodes[nodes[j]].aabb; - var b = new b2AABB(); - b.Combine(aabbi, aabbj); - var cost = b.GetPerimeter(); - if (cost < minCost) { - iMin = i; - jMin = j; - minCost = cost - } + var child1 = node.child1; + var child2 = node.child2; + var balance = b2Abs(this.m_nodes[child2].height - this.m_nodes[child1].height); + maxBalance = b2Max(maxBalance, balance) + } + return maxBalance + }, + GetAreaRatio: function () { + if (this.m_root == b2_nullNode) { + return 0 + } + var root = this.m_nodes[this.m_root]; + var rootArea = root.aabb.GetPerimeter(); + var totalArea = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + var node = this.m_nodes[i]; + if (node.height < 0) { + continue + } + totalArea += node.aabb.GetPerimeter() + } + return totalArea / rootArea + }, + RebuildBottomUp: function () { + var nodes = new Array(this.m_nodeCount); + var count = 0; + for (var i = 0; i < this.m_nodeCapacity; ++i) { + if (this.m_nodes[i].height < 0) { + continue + } + if (this.m_nodes[i].IsLeaf()) { + this.m_nodes[i].parent = b2_nullNode; + nodes[count] = i; + ++count + } else { + this.FreeNode(i) + } + } + while (count > 1) { + var minCost = b2_maxFloat; + var iMin = -1, + jMin = -1; + for (i = 0; i < count; ++i) { + var aabbi = this.m_nodes[nodes[i]].aabb; + for (var j = i + 1; j < count; ++j) { + var aabbj = this.m_nodes[nodes[j]].aabb; + var b = new b2AABB(); + b.Combine(aabbi, aabbj); + var cost = b.GetPerimeter(); + if (cost < minCost) { + iMin = i; + jMin = j; + minCost = cost } } - var index1 = nodes[iMin]; - var index2 = nodes[jMin]; - var child1 = this.m_nodes[index1]; - var child2 = this.m_nodes[index2]; - var parentIndex = this.AllocateNode(); - var parent = this.m_nodes[parentIndex]; - parent.child1 = index1; - parent.child2 = index2; - parent.height = 1 + b2Max(child1.height, child2.height); - parent.aabb.Combine(child1.aabb, child2.aabb); - parent.parent = b2_nullNode; - child1.parent = parentIndex; - child2.parent = parentIndex; - nodes[jMin] = nodes[count - 1]; - nodes[iMin] = parentIndex; - --count } - this.m_root = nodes[0]; - this.Validate() - }, - ShiftOrigin: function (newOrigin) { - for (var i = 0; i < this.m_nodeCapacity; ++i) { - this.m_nodes[i].aabb.lowerBound.Subtract(newOrigin); - this.m_nodes[i].aabb.upperBound.Subtract(newOrigin) + var index1 = nodes[iMin]; + var index2 = nodes[jMin]; + var child1 = this.m_nodes[index1]; + var child2 = this.m_nodes[index2]; + var parentIndex = this.AllocateNode(); + var parent = this.m_nodes[parentIndex]; + parent.child1 = index1; + parent.child2 = index2; + parent.height = 1 + b2Max(child1.height, child2.height); + parent.aabb.Combine(child1.aabb, child2.aabb); + parent.parent = b2_nullNode; + child1.parent = parentIndex; + child2.parent = parentIndex; + nodes[jMin] = nodes[count - 1]; + nodes[iMin] = parentIndex; + --count + } + this.m_root = nodes[0]; + this.Validate() + }, + ShiftOrigin: function (newOrigin) { + for (var i = 0; i < this.m_nodeCapacity; ++i) { + this.m_nodes[i].aabb.lowerBound.Subtract(newOrigin); + this.m_nodes[i].aabb.upperBound.Subtract(newOrigin) + } + }, + AllocateNode: function () { + if (this.m_freeList == b2_nullNode) { + var oldNodes = this.m_nodes; + this.m_nodeCapacity *= 2; + this.m_nodes = oldNodes.concat(new Array(this.m_nodeCapacity - this.m_nodeCount)); + for (var i = this.m_nodeCount; i < this.m_nodeCapacity - 1; ++i) { + this.m_nodes[i] = new b2TreeNode(); + this.m_nodes[i].parent = i + 1; + this.m_nodes[i].height = -1 } - }, - AllocateNode: function () { - if (this.m_freeList == b2_nullNode) { - var oldNodes = this.m_nodes; - this.m_nodeCapacity *= 2; - this.m_nodes = oldNodes.concat(new Array(this.m_nodeCapacity - this.m_nodeCount)); - for (var i = this.m_nodeCount; i < this.m_nodeCapacity - 1; ++i) { - this.m_nodes[i] = new b2TreeNode(); - this.m_nodes[i].parent = i + 1; - this.m_nodes[i].height = -1 - } - this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); - this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; - this.m_nodes[this.m_nodeCapacity - 1].height = -1; - this.m_freeList = this.m_nodeCount - } - var nodeId = this.m_freeList; - this.m_freeList = this.m_nodes[nodeId].parent; - this.m_nodes[nodeId].parent = b2_nullNode; - this.m_nodes[nodeId].child1 = b2_nullNode; - this.m_nodes[nodeId].child2 = b2_nullNode; - this.m_nodes[nodeId].height = 0; - this.m_nodes[nodeId].userData = null; - ++this.m_nodeCount; - return nodeId - }, - FreeNode: function (nodeId) { - this.m_nodes[nodeId].parent = this.m_freeList; - this.m_nodes[nodeId].height = -1; - this.m_freeList = nodeId; - --this.m_nodeCount - }, - InsertLeaf: function (leaf) { - ++this.m_insertionCount; - if (this.m_root == b2_nullNode) { - this.m_root = leaf; - this.m_nodes[this.m_root].parent = b2_nullNode; - return - } - var leafAABB = this.m_nodes[leaf].aabb; - var index = this.m_root; - while (this.m_nodes[index].IsLeaf() == false) { - var child1 = this.m_nodes[index].child1; - var child2 = this.m_nodes[index].child2; - var area = this.m_nodes[index].aabb.GetPerimeter(); - var combinedAABB = new b2AABB(); - combinedAABB.Combine(this.m_nodes[index].aabb, leafAABB); - var combinedArea = combinedAABB.GetPerimeter(); - var cost = 2 * combinedArea; - var inheritanceCost = 2 * (combinedArea - area); - var cost1; - var aabb; - if (this.m_nodes[child1].IsLeaf()) { - aabb = new b2AABB(); - aabb.Combine(leafAABB, this.m_nodes[child1].aabb); - cost1 = aabb.GetPerimeter() + inheritanceCost - } else { - aabb = new b2AABB(); - aabb.Combine(leafAABB, this.m_nodes[child1].aabb); - var oldArea = this.m_nodes[child1].aabb.GetPerimeter(); - var newArea = aabb.GetPerimeter(); - cost1 = (newArea - oldArea) + inheritanceCost - } - var cost2; - if (this.m_nodes[child2].IsLeaf()) { - aabb = new b2AABB(); - aabb.Combine(leafAABB, this.m_nodes[child2].aabb); - cost2 = aabb.GetPerimeter() + inheritanceCost - } else { - aabb = new b2AABB(); - aabb.Combine(leafAABB, this.m_nodes[child2].aabb); - var oldArea = this.m_nodes[child2].aabb.GetPerimeter(); - var newArea = aabb.GetPerimeter(); - cost2 = newArea - oldArea + inheritanceCost - } - if (cost < cost1 && cost < cost2) { - break - } - if (cost1 < cost2) { - index = child1 - } else { - index = child2 - } - } - var sibling = index; - var oldParent = this.m_nodes[sibling].parent; - var newParent = this.AllocateNode(); - this.m_nodes[newParent].parent = oldParent; - this.m_nodes[newParent].userData = null; - this.m_nodes[newParent].aabb.Combine(leafAABB, this.m_nodes[sibling].aabb); - this.m_nodes[newParent].height = this.m_nodes[sibling].height + 1; - if (oldParent != b2_nullNode) { - if (this.m_nodes[oldParent].child1 == sibling) { - this.m_nodes[oldParent].child1 = newParent - } else { - this.m_nodes[oldParent].child2 = newParent - } - this.m_nodes[newParent].child1 = sibling; - this.m_nodes[newParent].child2 = leaf; - this.m_nodes[sibling].parent = newParent; - this.m_nodes[leaf].parent = newParent + this.m_nodes[this.m_nodeCapacity - 1] = new b2TreeNode(); + this.m_nodes[this.m_nodeCapacity - 1].parent = b2_nullNode; + this.m_nodes[this.m_nodeCapacity - 1].height = -1; + this.m_freeList = this.m_nodeCount + } + var nodeId = this.m_freeList; + this.m_freeList = this.m_nodes[nodeId].parent; + this.m_nodes[nodeId].parent = b2_nullNode; + this.m_nodes[nodeId].child1 = b2_nullNode; + this.m_nodes[nodeId].child2 = b2_nullNode; + this.m_nodes[nodeId].height = 0; + this.m_nodes[nodeId].userData = null; + ++this.m_nodeCount; + return nodeId + }, + FreeNode: function (nodeId) { + this.m_nodes[nodeId].parent = this.m_freeList; + this.m_nodes[nodeId].height = -1; + this.m_freeList = nodeId; + --this.m_nodeCount + }, + InsertLeaf: function (leaf) { + ++this.m_insertionCount; + if (this.m_root == b2_nullNode) { + this.m_root = leaf; + this.m_nodes[this.m_root].parent = b2_nullNode; + return + } + var leafAABB = this.m_nodes[leaf].aabb; + var index = this.m_root; + while (this.m_nodes[index].IsLeaf() == false) { + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + var area = this.m_nodes[index].aabb.GetPerimeter(); + var combinedAABB = new b2AABB(); + combinedAABB.Combine(this.m_nodes[index].aabb, leafAABB); + var combinedArea = combinedAABB.GetPerimeter(); + var cost = 2 * combinedArea; + var inheritanceCost = 2 * (combinedArea - area); + var cost1; + var aabb; + if (this.m_nodes[child1].IsLeaf()) { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child1].aabb); + cost1 = aabb.GetPerimeter() + inheritanceCost } else { - this.m_nodes[newParent].child1 = sibling; - this.m_nodes[newParent].child2 = leaf; - this.m_nodes[sibling].parent = newParent; - this.m_nodes[leaf].parent = newParent; - this.m_root = newParent + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child1].aabb); + var oldArea = this.m_nodes[child1].aabb.GetPerimeter(); + var newArea = aabb.GetPerimeter(); + cost1 = (newArea - oldArea) + inheritanceCost } - index = this.m_nodes[leaf].parent; + var cost2; + if (this.m_nodes[child2].IsLeaf()) { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child2].aabb); + cost2 = aabb.GetPerimeter() + inheritanceCost + } else { + aabb = new b2AABB(); + aabb.Combine(leafAABB, this.m_nodes[child2].aabb); + var oldArea = this.m_nodes[child2].aabb.GetPerimeter(); + var newArea = aabb.GetPerimeter(); + cost2 = newArea - oldArea + inheritanceCost + } + if (cost < cost1 && cost < cost2) { + break + } + if (cost1 < cost2) { + index = child1 + } else { + index = child2 + } + } + var sibling = index; + var oldParent = this.m_nodes[sibling].parent; + var newParent = this.AllocateNode(); + this.m_nodes[newParent].parent = oldParent; + this.m_nodes[newParent].userData = null; + this.m_nodes[newParent].aabb.Combine(leafAABB, this.m_nodes[sibling].aabb); + this.m_nodes[newParent].height = this.m_nodes[sibling].height + 1; + if (oldParent != b2_nullNode) { + if (this.m_nodes[oldParent].child1 == sibling) { + this.m_nodes[oldParent].child1 = newParent + } else { + this.m_nodes[oldParent].child2 = newParent + } + this.m_nodes[newParent].child1 = sibling; + this.m_nodes[newParent].child2 = leaf; + this.m_nodes[sibling].parent = newParent; + this.m_nodes[leaf].parent = newParent + } else { + this.m_nodes[newParent].child1 = sibling; + this.m_nodes[newParent].child2 = leaf; + this.m_nodes[sibling].parent = newParent; + this.m_nodes[leaf].parent = newParent; + this.m_root = newParent + } + index = this.m_nodes[leaf].parent; + while (index != b2_nullNode) { + index = this.Balance(index); + var child1 = this.m_nodes[index].child1; + var child2 = this.m_nodes[index].child2; + this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); + this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + index = this.m_nodes[index].parent + } + }, + RemoveLeaf: function (leaf) { + if (leaf == this.m_root) { + this.m_root = b2_nullNode; + return + } + var parent = this.m_nodes[leaf].parent; + var grandParent = this.m_nodes[parent].parent; + var sibling; + if (this.m_nodes[parent].child1 == leaf) { + sibling = this.m_nodes[parent].child2 + } else { + sibling = this.m_nodes[parent].child1 + } + if (grandParent != b2_nullNode) { + if (this.m_nodes[grandParent].child1 == parent) { + this.m_nodes[grandParent].child1 = sibling + } else { + this.m_nodes[grandParent].child2 = sibling + } + this.m_nodes[sibling].parent = grandParent; + this.FreeNode(parent); + var index = grandParent; while (index != b2_nullNode) { index = this.Balance(index); var child1 = this.m_nodes[index].child1; var child2 = this.m_nodes[index].child2; - this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); index = this.m_nodes[index].parent } - }, - RemoveLeaf: function (leaf) { - if (leaf == this.m_root) { - this.m_root = b2_nullNode; - return - } - var parent = this.m_nodes[leaf].parent; - var grandParent = this.m_nodes[parent].parent; - var sibling; - if (this.m_nodes[parent].child1 == leaf) { - sibling = this.m_nodes[parent].child2 - } else { - sibling = this.m_nodes[parent].child1 - } - if (grandParent != b2_nullNode) { - if (this.m_nodes[grandParent].child1 == parent) { - this.m_nodes[grandParent].child1 = sibling - } else { - this.m_nodes[grandParent].child2 = sibling - } - this.m_nodes[sibling].parent = grandParent; - this.FreeNode(parent); - var index = grandParent; - while (index != b2_nullNode) { - index = this.Balance(index); - var child1 = this.m_nodes[index].child1; - var child2 = this.m_nodes[index].child2; - this.m_nodes[index].aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); - this.m_nodes[index].height = 1 + b2Max(this.m_nodes[child1].height, this.m_nodes[child2].height); - index = this.m_nodes[index].parent - } - } else { - this.m_root = sibling; - this.m_nodes[sibling].parent = b2_nullNode; - this.FreeNode(parent) - } - }, - Balance: function (iA) { - var A = this.m_nodes[iA]; - if (A.IsLeaf() || A.height < 2) { - return iA - } - var iB = A.child1; - var iC = A.child2; - var B = this.m_nodes[iB]; - var C = this.m_nodes[iC]; - var balance = C.height - B.height; - if (balance > 1) { - var iF = C.child1; - var iG = C.child2; - var F = this.m_nodes[iF]; - var G = this.m_nodes[iG]; - C.child1 = iA; - C.parent = A.parent; - A.parent = iC; - if (C.parent != b2_nullNode) { - if (this.m_nodes[C.parent].child1 == iA) { - this.m_nodes[C.parent].child1 = iC - } else { - this.m_nodes[C.parent].child2 = iC - } - } else { - this.m_root = iC - } - if (F.height > G.height) { - C.child2 = iF; - A.child2 = iG; - G.parent = iA; - A.aabb.Combine(B.aabb, G.aabb); - C.aabb.Combine(A.aabb, F.aabb); - A.height = 1 + b2Max(B.height, G.height); - C.height = 1 + b2Max(A.height, F.height) - } else { - C.child2 = iG; - A.child2 = iF; - F.parent = iA; - A.aabb.Combine(B.aabb, F.aabb); - C.aabb.Combine(A.aabb, G.aabb); - A.height = 1 + b2Max(B.height, F.height); - C.height = 1 + b2Max(A.height, G.height) - } - return iC - } - if (balance < -1) { - var iD = B.child1; - var iE = B.child2; - var D = this.m_nodes[iD]; - var E = this.m_nodes[iE]; - B.child1 = iA; - B.parent = A.parent; - A.parent = iB; - if (B.parent != b2_nullNode) { - if (this.m_nodes[B.parent].child1 == iA) { - this.m_nodes[B.parent].child1 = iB - } else { - this.m_nodes[B.parent].child2 = iB - } - } else { - this.m_root = iB - } - if (D.height > E.height) { - B.child2 = iD; - A.child1 = iE; - E.parent = iA; - A.aabb.Combine(C.aabb, E.aabb); - B.aabb.Combine(A.aabb, D.aabb); - A.height = 1 + b2Max(C.height, E.height); - B.height = 1 + b2Max(A.height, D.height) - } else { - B.child2 = iE; - A.child1 = iD; - D.parent = iA; - A.aabb.Combine(C.aabb, D.aabb); - B.aabb.Combine(A.aabb, E.aabb); - A.height = 1 + b2Max(C.height, D.height); - B.height = 1 + b2Max(A.height, E.height) - } - return iB - } - return iA - }, - ComputeHeight: function (nodeId) { - if (typeof (nodeId) === "undefined") { - nodeId = this.m_root - } - var node = this.m_nodes[nodeId]; - if (node.IsLeaf()) { - return 0 - } - var height1 = this.ComputeHeight(node.child1); - var height2 = this.ComputeHeight(node.child2); - return 1 + b2Max(height1, height2) - }, - ValidateStructure: function (index) { - if (index == b2_nullNode) { - return - } - var node = this.m_nodes[index]; - var child1 = node.child1; - var child2 = node.child2; - if (node.IsLeaf()) { - return - } - this.ValidateStructure(child1); - this.ValidateStructure(child2) - }, - ValidateMetrics: function (index) { - if (index == b2_nullNode) { - return - } - var node = this.m_nodes[index]; - var child1 = node.child1; - var child2 = node.child2; - if (node.IsLeaf()) { - return - } - var height1 = this.m_nodes[child1].height; - var height2 = this.m_nodes[child2].height; - var height; - height = 1 + b2Max(height1, height2); - var aabb = new b2AABB(); - aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); - this.ValidateMetrics(child1); - this.ValidateMetrics(child2) + } else { + this.m_root = sibling; + this.m_nodes[sibling].parent = b2_nullNode; + this.FreeNode(parent) } - }; - "use strict"; - - function b2TOIInput() { - this.proxyA = new b2DistanceProxy(); - this.proxyB = new b2DistanceProxy(); - this.sweepA = new b2Sweep(); - this.sweepB = new b2Sweep(); - this.tMax = 0 + }, + Balance: function (iA) { + var A = this.m_nodes[iA]; + if (A.IsLeaf() || A.height < 2) { + return iA + } + var iB = A.child1; + var iC = A.child2; + var B = this.m_nodes[iB]; + var C = this.m_nodes[iC]; + var balance = C.height - B.height; + if (balance > 1) { + var iF = C.child1; + var iG = C.child2; + var F = this.m_nodes[iF]; + var G = this.m_nodes[iG]; + C.child1 = iA; + C.parent = A.parent; + A.parent = iC; + if (C.parent != b2_nullNode) { + if (this.m_nodes[C.parent].child1 == iA) { + this.m_nodes[C.parent].child1 = iC + } else { + this.m_nodes[C.parent].child2 = iC + } + } else { + this.m_root = iC + } + if (F.height > G.height) { + C.child2 = iF; + A.child2 = iG; + G.parent = iA; + A.aabb.Combine(B.aabb, G.aabb); + C.aabb.Combine(A.aabb, F.aabb); + A.height = 1 + b2Max(B.height, G.height); + C.height = 1 + b2Max(A.height, F.height) + } else { + C.child2 = iG; + A.child2 = iF; + F.parent = iA; + A.aabb.Combine(B.aabb, F.aabb); + C.aabb.Combine(A.aabb, G.aabb); + A.height = 1 + b2Max(B.height, F.height); + C.height = 1 + b2Max(A.height, G.height) + } + return iC + } + if (balance < -1) { + var iD = B.child1; + var iE = B.child2; + var D = this.m_nodes[iD]; + var E = this.m_nodes[iE]; + B.child1 = iA; + B.parent = A.parent; + A.parent = iB; + if (B.parent != b2_nullNode) { + if (this.m_nodes[B.parent].child1 == iA) { + this.m_nodes[B.parent].child1 = iB + } else { + this.m_nodes[B.parent].child2 = iB + } + } else { + this.m_root = iB + } + if (D.height > E.height) { + B.child2 = iD; + A.child1 = iE; + E.parent = iA; + A.aabb.Combine(C.aabb, E.aabb); + B.aabb.Combine(A.aabb, D.aabb); + A.height = 1 + b2Max(C.height, E.height); + B.height = 1 + b2Max(A.height, D.height) + } else { + B.child2 = iE; + A.child1 = iD; + D.parent = iA; + A.aabb.Combine(C.aabb, D.aabb); + B.aabb.Combine(A.aabb, E.aabb); + A.height = 1 + b2Max(C.height, D.height); + B.height = 1 + b2Max(A.height, E.height) + } + return iB + } + return iA + }, + ComputeHeight: function (nodeId) { + if (typeof (nodeId) === "undefined") { + nodeId = this.m_root + } + var node = this.m_nodes[nodeId]; + if (node.IsLeaf()) { + return 0 + } + var height1 = this.ComputeHeight(node.child1); + var height2 = this.ComputeHeight(node.child2); + return 1 + b2Max(height1, height2) + }, + ValidateStructure: function (index) { + if (index == b2_nullNode) { + return + } + var node = this.m_nodes[index]; + var child1 = node.child1; + var child2 = node.child2; + if (node.IsLeaf()) { + return + } + this.ValidateStructure(child1); + this.ValidateStructure(child2) + }, + ValidateMetrics: function (index) { + if (index == b2_nullNode) { + return + } + var node = this.m_nodes[index]; + var child1 = node.child1; + var child2 = node.child2; + if (node.IsLeaf()) { + return + } + var height1 = this.m_nodes[child1].height; + var height2 = this.m_nodes[child2].height; + var height; + height = 1 + b2Max(height1, height2); + var aabb = new b2AABB(); + aabb.Combine(this.m_nodes[child1].aabb, this.m_nodes[child2].aabb); + this.ValidateMetrics(child1); + this.ValidateMetrics(child2) } +}; +"use strict"; - function b2TOIOutput() { - this.state = 0; - this.t = 0 - } - b2TOIOutput.e_unknown = 0; - b2TOIOutput.e_failed = 1; - b2TOIOutput.e_overlapped = 2; - b2TOIOutput.e_touching = 3; - b2TOIOutput.e_separated = 4; +function b2TOIInput() { + this.proxyA = new b2DistanceProxy(); + this.proxyB = new b2DistanceProxy(); + this.sweepA = new b2Sweep(); + this.sweepB = new b2Sweep(); + this.tMax = 0 +} - function b2SeparationFunction() { - this.m_proxyA = null; - this.m_proxyB = null; - this.m_sweepA = null; - this.m_sweepB = null; - this.m_type = 0; - this.m_localPoint = new b2Vec2(); - this.m_axis = new b2Vec2() - } - var _local_xfA = new b2Transform(); - var _local_xfB = new b2Transform(); - b2SeparationFunction.prototype = { - Initialize: function (cache, proxyA, sweepA, proxyB, sweepB, t1) { - this.m_proxyA = proxyA; - this.m_proxyB = proxyB; - var count = cache.count; - this.m_sweepA = sweepA; - this.m_sweepB = sweepB; - this.m_sweepA.GetTransform(_local_xfA, t1); - this.m_sweepB.GetTransform(_local_xfB, t1); - if (count == 1) { - this.m_type = b2SeparationFunction.e_points; - var localPointA = this.m_proxyA.GetVertex(cache.indexA[0]); +function b2TOIOutput() { + this.state = 0; + this.t = 0 +} +b2TOIOutput.e_unknown = 0; +b2TOIOutput.e_failed = 1; +b2TOIOutput.e_overlapped = 2; +b2TOIOutput.e_touching = 3; +b2TOIOutput.e_separated = 4; + +function b2SeparationFunction() { + this.m_proxyA = null; + this.m_proxyB = null; + this.m_sweepA = null; + this.m_sweepB = null; + this.m_type = 0; + this.m_localPoint = new b2Vec2(); + this.m_axis = new b2Vec2() +} +var _local_xfA = new b2Transform(); +var _local_xfB = new b2Transform(); +b2SeparationFunction.prototype = { + Initialize: function (cache, proxyA, sweepA, proxyB, sweepB, t1) { + this.m_proxyA = proxyA; + this.m_proxyB = proxyB; + var count = cache.count; + this.m_sweepA = sweepA; + this.m_sweepB = sweepB; + this.m_sweepA.GetTransform(_local_xfA, t1); + this.m_sweepB.GetTransform(_local_xfB, t1); + if (count == 1) { + this.m_type = b2SeparationFunction.e_points; + var localPointA = this.m_proxyA.GetVertex(cache.indexA[0]); + var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + this.m_axis.x = pointBx - pointAx; + this.m_axis.y = pointBy - pointAy; + var s = this.m_axis.Normalize(); + return s + } else { + if (cache.indexA[0] == cache.indexA[1]) { + this.m_type = b2SeparationFunction.e_faceB; + var localPointB1 = proxyB.GetVertex(cache.indexB[0]); + var localPointB2 = proxyB.GetVertex(cache.indexB[1]); + this.m_axis.x = 1 * (localPointB2.y - localPointB1.y); + this.m_axis.y = -1 * (localPointB2.x - localPointB1.x); + this.m_axis.Normalize(); + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + this.m_localPoint.x = 0.5 * (localPointB1.x + localPointB2.x); + this.m_localPoint.y = 0.5 * (localPointB1.y + localPointB2.y); + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var localPointA = proxyA.GetVertex(cache.indexA[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var s = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; + if (s < 0) { + this.m_axis.x = -this.m_axis.x; + this.m_axis.y = -this.m_axis.y; + s = -s + } + return s + } else { + this.m_type = b2SeparationFunction.e_faceA; + var localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]); + var localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]); + this.m_axis.x = 1 * (localPointA2.y - localPointA1.y); + this.m_axis.y = -1 * (localPointA2.x - localPointA1.x); + this.m_axis.Normalize(); + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + this.m_localPoint.x = 0.5 * (localPointA1.x + localPointA2.x); + this.m_localPoint.y = 0.5 * (localPointA1.y + localPointA2.y); + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var s = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + if (s < 0) { + this.m_axis.x = -this.m_axis.x; + this.m_axis.y = -this.m_axis.y; + s = -s + } + return s + } + } + }, + FindMinSeparation: function (indices, t) { + this.m_sweepA.GetTransform(_local_xfA, t); + this.m_sweepB.GetTransform(_local_xfB, t); + switch (this.m_type) { + case b2SeparationFunction.e_points: + var axisAx = _local_xfA.q.c * this.m_axis.x + _local_xfA.q.s * this.m_axis.y; + var axisAy = -_local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var axisBx = _local_xfB.q.c * -this.m_axis.x + _local_xfB.q.s * -this.m_axis.y; + var axisBy = -_local_xfB.q.s * -this.m_axis.x + _local_xfB.q.c * -this.m_axis.y; + indices[0] = this.m_proxyA.GetSupport(axisAx, axisAy); + indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); + var localPointA = this.m_proxyA.GetVertex(indices[0]); + var localPointB = this.m_proxyB.GetVertex(indices[1]); var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; - this.m_axis.x = pointBx - pointAx; - this.m_axis.y = pointBy - pointAy; - var s = this.m_axis.Normalize(); - return s - } else { - if (cache.indexA[0] == cache.indexA[1]) { - this.m_type = b2SeparationFunction.e_faceB; - var localPointB1 = proxyB.GetVertex(cache.indexB[0]); - var localPointB2 = proxyB.GetVertex(cache.indexB[1]); - this.m_axis.x = 1 * (localPointB2.y - localPointB1.y); - this.m_axis.y = -1 * (localPointB2.x - localPointB1.x); - this.m_axis.Normalize(); - var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; - var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; - this.m_localPoint.x = 0.5 * (localPointB1.x + localPointB2.x); - this.m_localPoint.y = 0.5 * (localPointB1.y + localPointB2.y); - var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; - var localPointA = proxyA.GetVertex(cache.indexA[0]); - var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; - var s = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; - if (s < 0) { - this.m_axis.x = -this.m_axis.x; - this.m_axis.y = -this.m_axis.y; - s = -s - } - return s - } else { - this.m_type = b2SeparationFunction.e_faceA; - var localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]); - var localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]); - this.m_axis.x = 1 * (localPointA2.y - localPointA1.y); - this.m_axis.y = -1 * (localPointA2.x - localPointA1.x); - this.m_axis.Normalize(); - var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; - var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; - this.m_localPoint.x = 0.5 * (localPointA1.x + localPointA2.x); - this.m_localPoint.y = 0.5 * (localPointA1.y + localPointA2.y); - var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; - var localPointB = this.m_proxyB.GetVertex(cache.indexB[0]); - var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; - var s = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; - if (s < 0) { - this.m_axis.x = -this.m_axis.x; - this.m_axis.y = -this.m_axis.y; - s = -s - } - return s - } - } - }, - FindMinSeparation: function (indices, t) { - this.m_sweepA.GetTransform(_local_xfA, t); - this.m_sweepB.GetTransform(_local_xfB, t); - switch (this.m_type) { - case b2SeparationFunction.e_points: - var axisAx = _local_xfA.q.c * this.m_axis.x + _local_xfA.q.s * this.m_axis.y; - var axisAy = -_local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; - var axisBx = _local_xfB.q.c * -this.m_axis.x + _local_xfB.q.s * -this.m_axis.y; - var axisBy = -_local_xfB.q.s * -this.m_axis.x + _local_xfB.q.c * -this.m_axis.y; - indices[0] = this.m_proxyA.GetSupport(axisAx, axisAy); - indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); - var localPointA = this.m_proxyA.GetVertex(indices[0]); - var localPointB = this.m_proxyB.GetVertex(indices[1]); - var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; - var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; - return (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; - case b2SeparationFunction.e_faceA: - var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; - var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; - var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; - var axisBx = _local_xfB.q.c * -normalx + _local_xfB.q.s * -normaly; - var axisBy = -_local_xfB.q.s * -normalx + _local_xfB.q.c * -normaly; - indices[0] = -1; - indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); - var localPointB = this.m_proxyB.GetVertex(indices[1]); - var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; - return (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; - case b2SeparationFunction.e_faceB: - var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; - var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; - var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; - var axisAx = _local_xfA.q.c * -normalx + _local_xfA.q.s * -normaly; - var axisBy = -_local_xfA.q.s * -normalx + _local_xfA.q.c * -normaly; - indices[1] = -1; - indices[0] = this.m_proxyA.GetSupport(axisAx, axisBy); - var localPointA = this.m_proxyA.GetVertex(indices[0]); - var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; - return (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly - } - }, - Evaluate: function (indexA, indexB, t) { - this.m_sweepA.GetTransform(_local_xfA, t); - this.m_sweepB.GetTransform(_local_xfB, t); - switch (this.m_type) { - case b2SeparationFunction.e_points: - var localPointA = this.m_proxyA.GetVertex(indexA); - var localPointB = this.m_proxyB.GetVertex(indexB); - var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; - var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; - var separation = (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; - return separation; - case b2SeparationFunction.e_faceA: - var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; - var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; - var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; - var localPointB = this.m_proxyB.GetVertex(indexB); - var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; - var separation = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; - return separation; - case b2SeparationFunction.e_faceB: - var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; - var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; - var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; - var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; - var localPointA = this.m_proxyA.GetVertex(indexA); - var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; - var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; - var separation = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; - return separation - } + return (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; + case b2SeparationFunction.e_faceA: + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var axisBx = _local_xfB.q.c * -normalx + _local_xfB.q.s * -normaly; + var axisBy = -_local_xfB.q.s * -normalx + _local_xfB.q.c * -normaly; + indices[0] = -1; + indices[1] = this.m_proxyB.GetSupport(axisBx, axisBy); + var localPointB = this.m_proxyB.GetVertex(indices[1]); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + return (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + case b2SeparationFunction.e_faceB: + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var axisAx = _local_xfA.q.c * -normalx + _local_xfA.q.s * -normaly; + var axisBy = -_local_xfA.q.s * -normalx + _local_xfA.q.c * -normaly; + indices[1] = -1; + indices[0] = this.m_proxyA.GetSupport(axisAx, axisBy); + var localPointA = this.m_proxyA.GetVertex(indices[0]); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + return (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly } - }; - b2SeparationFunction.e_points = 0; - b2SeparationFunction.e_faceA = 1; - b2SeparationFunction.e_faceB = 2; - var profile_toi = b2Profiler.create("toi", "solveTOI"); + }, + Evaluate: function (indexA, indexB, t) { + this.m_sweepA.GetTransform(_local_xfA, t); + this.m_sweepB.GetTransform(_local_xfB, t); + switch (this.m_type) { + case b2SeparationFunction.e_points: + var localPointA = this.m_proxyA.GetVertex(indexA); + var localPointB = this.m_proxyB.GetVertex(indexB); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var separation = (pointBx - pointAx) * this.m_axis.x + (pointBy - pointAy) * this.m_axis.y; + return separation; + case b2SeparationFunction.e_faceA: + var normalx = _local_xfA.q.c * this.m_axis.x - _local_xfA.q.s * this.m_axis.y; + var normaly = _local_xfA.q.s * this.m_axis.x + _local_xfA.q.c * this.m_axis.y; + var pointAx = (_local_xfA.q.c * this.m_localPoint.x - _local_xfA.q.s * this.m_localPoint.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * this.m_localPoint.x + _local_xfA.q.c * this.m_localPoint.y) + _local_xfA.p.y; + var localPointB = this.m_proxyB.GetVertex(indexB); + var pointBx = (_local_xfB.q.c * localPointB.x - _local_xfB.q.s * localPointB.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * localPointB.x + _local_xfB.q.c * localPointB.y) + _local_xfB.p.y; + var separation = (pointBx - pointAx) * normalx + (pointBy - pointAy) * normaly; + return separation; + case b2SeparationFunction.e_faceB: + var normalx = _local_xfB.q.c * this.m_axis.x - _local_xfB.q.s * this.m_axis.y; + var normaly = _local_xfB.q.s * this.m_axis.x + _local_xfB.q.c * this.m_axis.y; + var pointBx = (_local_xfB.q.c * this.m_localPoint.x - _local_xfB.q.s * this.m_localPoint.y) + _local_xfB.p.x; + var pointBy = (_local_xfB.q.s * this.m_localPoint.x + _local_xfB.q.c * this.m_localPoint.y) + _local_xfB.p.y; + var localPointA = this.m_proxyA.GetVertex(indexA); + var pointAx = (_local_xfA.q.c * localPointA.x - _local_xfA.q.s * localPointA.y) + _local_xfA.p.x; + var pointAy = (_local_xfA.q.s * localPointA.x + _local_xfA.q.c * localPointA.y) + _local_xfA.p.y; + var separation = (pointAx - pointBx) * normalx + (pointAy - pointBy) * normaly; + return separation + } + } +}; +b2SeparationFunction.e_points = 0; +b2SeparationFunction.e_faceA = 1; +b2SeparationFunction.e_faceB = 2; +var profile_toi = b2Profiler.create("toi", "solveTOI"); - function b2TimeOfImpact(output, input) { - profile_toi.start(); - ++b2TimeOfImpact.b2_toiCalls; - output.state = b2TOIOutput.e_unknown; - output.t = input.tMax; - var proxyA = input.proxyA; - var proxyB = input.proxyB; - b2TimeOfImpact._temp_sweepA.Assign(input.sweepA); - b2TimeOfImpact._temp_sweepB.Assign(input.sweepB); - b2TimeOfImpact._temp_sweepA.Normalize(); - b2TimeOfImpact._temp_sweepB.Normalize(); - var tMax = input.tMax; - var totalRadius = proxyA.m_radius + proxyB.m_radius; - var target = b2Max(b2_linearSlop, totalRadius - 3 * b2_linearSlop); - var tolerance = 0.25 * b2_linearSlop; - var t1 = 0; - var k_maxIterations = 20; - var iter = 0; - var cache = new b2SimplexCache(); - cache.count = 0; - var distanceInput = new b2DistanceInput(); - distanceInput.proxyA.Assign(input.proxyA); - distanceInput.proxyB.Assign(input.proxyB); - distanceInput.useRadii = false; +function b2TimeOfImpact(output, input) { + profile_toi.start(); + ++b2TimeOfImpact.b2_toiCalls; + output.state = b2TOIOutput.e_unknown; + output.t = input.tMax; + var proxyA = input.proxyA; + var proxyB = input.proxyB; + b2TimeOfImpact._temp_sweepA.Assign(input.sweepA); + b2TimeOfImpact._temp_sweepB.Assign(input.sweepB); + b2TimeOfImpact._temp_sweepA.Normalize(); + b2TimeOfImpact._temp_sweepB.Normalize(); + var tMax = input.tMax; + var totalRadius = proxyA.m_radius + proxyB.m_radius; + var target = b2Max(b2_linearSlop, totalRadius - 3 * b2_linearSlop); + var tolerance = 0.25 * b2_linearSlop; + var t1 = 0; + var k_maxIterations = 20; + var iter = 0; + var cache = new b2SimplexCache(); + cache.count = 0; + var distanceInput = new b2DistanceInput(); + distanceInput.proxyA.Assign(input.proxyA); + distanceInput.proxyB.Assign(input.proxyB); + distanceInput.useRadii = false; + for (;;) { + b2TimeOfImpact._temp_sweepA.GetTransform(distanceInput.transformA, t1); + b2TimeOfImpact._temp_sweepB.GetTransform(distanceInput.transformB, t1); + var distanceOutput = new b2DistanceOutput(); + b2DistanceFunc(distanceOutput, cache, distanceInput); + if (distanceOutput.distance <= 0) { + output.state = b2TOIOutput.e_overlapped; + output.t = 0; + break + } + if (distanceOutput.distance < target + tolerance) { + output.state = b2TOIOutput.e_touching; + output.t = t1; + break + } + var fcn = new b2SeparationFunction(); + fcn.Initialize(cache, proxyA, b2TimeOfImpact._temp_sweepA, proxyB, b2TimeOfImpact._temp_sweepB, t1); + var done = false; + var t2 = tMax; + var pushBackIter = 0; for (;;) { - b2TimeOfImpact._temp_sweepA.GetTransform(distanceInput.transformA, t1); - b2TimeOfImpact._temp_sweepB.GetTransform(distanceInput.transformB, t1); - var distanceOutput = new b2DistanceOutput(); - b2DistanceFunc(distanceOutput, cache, distanceInput); - if (distanceOutput.distance <= 0) { - output.state = b2TOIOutput.e_overlapped; - output.t = 0; + var indices = []; + var s2 = fcn.FindMinSeparation(indices, t2); + if (s2 > target + tolerance) { + output.state = b2TOIOutput.e_separated; + output.t = tMax; + done = true; break } - if (distanceOutput.distance < target + tolerance) { - output.state = b2TOIOutput.e_touching; - output.t = t1; + if (s2 > target - tolerance) { + t1 = t2; break } - var fcn = new b2SeparationFunction(); - fcn.Initialize(cache, proxyA, b2TimeOfImpact._temp_sweepA, proxyB, b2TimeOfImpact._temp_sweepB, t1); - var done = false; - var t2 = tMax; - var pushBackIter = 0; - for (;;) { - var indices = []; - var s2 = fcn.FindMinSeparation(indices, t2); - if (s2 > target + tolerance) { - output.state = b2TOIOutput.e_separated; - output.t = tMax; - done = true; - break - } - if (s2 > target - tolerance) { - t1 = t2; - break - } - var s1 = fcn.Evaluate(indices[0], indices[1], t1); - if (s1 < target - tolerance) { - output.state = b2TOIOutput.e_failed; - output.t = t1; - done = true; - break - } - if (s1 <= target + tolerance) { - output.state = b2TOIOutput.e_touching; - output.t = t1; - done = true; - break - } - var rootIterCount = 0; - var a1 = t1, - a2 = t2; - for (;;) { - var t; - if (rootIterCount & 1) { - t = a1 + (target - s1) * (a2 - a1) / (s2 - s1) - } else { - t = 0.5 * (a1 + a2) - }++rootIterCount; - ++b2TimeOfImpact.b2_toiRootIters; - var s = fcn.Evaluate(indices[0], indices[1], t); - if (b2Abs(s - target) < tolerance) { - t2 = t; - break - } - if (s > target) { - a1 = t; - s1 = s - } else { - a2 = t; - s2 = s - } - if (rootIterCount == 50) { - break - } - } - b2TimeOfImpact.b2_toiMaxRootIters = b2Max(b2TimeOfImpact.b2_toiMaxRootIters, rootIterCount); - ++pushBackIter; - if (pushBackIter == b2_maxPolygonVertices) { - break - } - }++iter; - ++b2TimeOfImpact.b2_toiIters; - if (done) { - break - } - if (iter == k_maxIterations) { + var s1 = fcn.Evaluate(indices[0], indices[1], t1); + if (s1 < target - tolerance) { output.state = b2TOIOutput.e_failed; output.t = t1; + done = true; break } - } - b2TimeOfImpact.b2_toiMaxIters = b2Max(b2TimeOfImpact.b2_toiMaxIters, iter); - profile_toi.stop(); - b2TimeOfImpact.b2_toiMaxTime = b2Max(b2TimeOfImpact.b2_toiMaxTime, profile_toi.elapsedTime); - b2TimeOfImpact.b2_toiTime += profile_toi.elapsedTime - } - b2TimeOfImpact._temp_sweepA = new b2Sweep(); - b2TimeOfImpact._temp_sweepB = new b2Sweep(); - b2TimeOfImpact.b2_toiTime = 0; - b2TimeOfImpact.b2_toiMaxTime = 0; - b2TimeOfImpact.b2_toiCalls = 0; - b2TimeOfImpact.b2_toiIters = 0; - b2TimeOfImpact.b2_toiMaxIters = 0; - b2TimeOfImpact.b2_toiRootIters = 0; - b2TimeOfImpact.b2_toiMaxRootIters = 0; - "use strict"; - - function b2BodyDef() { - this.type = b2Body.b2_staticBody; - this.position = new b2Vec2(0, 0); - this.angle = 0; - this.linearVelocity = new b2Vec2(0, 0); - this.angularVelocity = 0; - this.linearDamping = 0; - this.angularDamping = 0; - this.allowSleep = true; - this.awake = true; - this.fixedRotation = false; - this.bullet = false; - this.active = true; - this.userData = null; - this.gravityScale = 1; - Object.seal(this) - } - b2BodyDef.prototype = { - _deserialize: function (data) { - this.type = data.type; - this.position._deserialize(data.position); - this.angle = data.angle; - this.linearVelocity._deserialize(data.linearVelocity); - this.angularVelocity = data.angularVelocity; - this.linearDamping = data.linearDamping; - this.angularDamping = data.angularDamping; - this.allowSleep = data.allowSleep; - this.awake = data.awake; - this.fixedRotation = data.fixedRotation; - this.bullet = data.bullet; - this.active = data.active; - this.gravityScale = data.gravityScale - } - }; - - function b2Body(bd, world) { - this.m_islandIndex = 0; - this.m_flags = 0; - if (bd.bullet) { - this.m_flags |= b2Body.e_bulletFlag - } - if (bd.fixedRotation) { - this.m_flags |= b2Body.e_fixedRotationFlag - } - if (bd.allowSleep) { - this.m_flags |= b2Body.e_autoSleepFlag - } - if (bd.awake) { - this.m_flags |= b2Body.e_awakeFlag - } - if (bd.active) { - this.m_flags |= b2Body.e_activeFlag - } - this.m_world = world; - this.m_xf = new b2Transform(); - this.m_xf.p.Assign(bd.position); - this.m_xf.q.Set(bd.angle); - this.m_sweep = new b2Sweep(); - this.m_sweep.localCenter.SetZero(); - this.m_sweep.c0.Assign(this.m_xf.p); - this.m_sweep.c.Assign(this.m_xf.p); - this.m_sweep.a0 = bd.angle; - this.m_sweep.a = bd.angle; - this.m_sweep.alpha0 = 0; - this.m_jointList = null; - this.m_contactList = null; - this.m_prev = null; - this.m_next = null; - this.m_linearVelocity = bd.linearVelocity.Clone(); - this.m_angularVelocity = bd.angularVelocity; - this.m_linearDamping = bd.linearDamping; - this.m_angularDamping = bd.angularDamping; - this.m_gravityScale = bd.gravityScale; - this.m_force = new b2Vec2(); - this.m_torque = 0; - this.m_sleepTime = 0; - this.m_type = bd.type; - if (this.m_type == b2Body.b2_dynamicBody) { - this.m_mass = 1; - this.m_invMass = 1 - } else { - this.m_mass = 0; - this.m_invMass = 0 - } - this.m_I = 0; - this.m_invI = 0; - this.m_userData = bd.userData; - this.m_fixtureList = null; - this.m_fixtureCount = 0 - } - b2Body.b2_staticBody = 0; - b2Body.b2_kinematicBody = 1; - b2Body.b2_dynamicBody = 2; - b2Body.e_islandFlag = 1; - b2Body.e_awakeFlag = 2; - b2Body.e_autoSleepFlag = 4; - b2Body.e_bulletFlag = 8; - b2Body.e_fixedRotationFlag = 16; - b2Body.e_activeFlag = 32; - b2Body.e_toiFlag = 64; - b2Body.m_local_oldCenter = new b2Vec2(); - b2Body.m_local_xf1 = new b2Transform(); - b2Body.prototype = { - CreateFixture: function (def, density) { - if (typeof (density) !== "undefined") { - var ndef = new b2FixtureDef(); - ndef.shape = def; - ndef.density = density; - return this.CreateFixture(ndef) + if (s1 <= target + tolerance) { + output.state = b2TOIOutput.e_touching; + output.t = t1; + done = true; + break } - if (this.m_world.IsLocked() == true) { - return null - } - var fixture = new b2Fixture(); - fixture.Create(this, def); - if (this.m_flags & b2Body.e_activeFlag) { - var broadPhase = this.m_world.m_contactManager.m_broadPhase; - fixture.CreateProxies(broadPhase, this.m_xf) - } - fixture.m_next = this.m_fixtureList; - this.m_fixtureList = fixture; - ++this.m_fixtureCount; - fixture.m_body = this; - if (fixture.m_density > 0) { - this.ResetMassData() - } - this.m_world.m_flags |= b2World.e_newFixture; - return fixture - }, - DestroyFixture: function (fixture) { - if (this.m_world.IsLocked() == true) { - return - } - var node = this.m_fixtureList; - var found = false; - while (node != null) { - if (node == fixture) { - this.m_fixtureList = node = fixture.m_next; - found = true; + var rootIterCount = 0; + var a1 = t1, + a2 = t2; + for (;;) { + var t; + if (rootIterCount & 1) { + t = a1 + (target - s1) * (a2 - a1) / (s2 - s1) + } else { + t = 0.5 * (a1 + a2) + }++rootIterCount; + ++b2TimeOfImpact.b2_toiRootIters; + var s = fcn.Evaluate(indices[0], indices[1], t); + if (b2Abs(s - target) < tolerance) { + t2 = t; break } - node = node.m_next - } - 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.m_world.m_contactManager.Destroy(c) + if (s > target) { + a1 = t; + s1 = s + } else { + a2 = t; + s2 = s + } + if (rootIterCount == 50) { + break } } - if (this.m_flags & b2Body.e_activeFlag) { - var broadPhase = this.m_world.m_contactManager.m_broadPhase; - fixture.DestroyProxies(broadPhase) + b2TimeOfImpact.b2_toiMaxRootIters = b2Max(b2TimeOfImpact.b2_toiMaxRootIters, rootIterCount); + ++pushBackIter; + if (pushBackIter == b2_maxPolygonVertices) { + break } - fixture.Destroy(); - fixture.m_body = null; - fixture.m_next = null; - --this.m_fixtureCount; + }++iter; + ++b2TimeOfImpact.b2_toiIters; + if (done) { + break + } + if (iter == k_maxIterations) { + output.state = b2TOIOutput.e_failed; + output.t = t1; + break + } + } + b2TimeOfImpact.b2_toiMaxIters = b2Max(b2TimeOfImpact.b2_toiMaxIters, iter); + profile_toi.stop(); + b2TimeOfImpact.b2_toiMaxTime = b2Max(b2TimeOfImpact.b2_toiMaxTime, profile_toi.elapsedTime); + b2TimeOfImpact.b2_toiTime += profile_toi.elapsedTime +} +b2TimeOfImpact._temp_sweepA = new b2Sweep(); +b2TimeOfImpact._temp_sweepB = new b2Sweep(); +b2TimeOfImpact.b2_toiTime = 0; +b2TimeOfImpact.b2_toiMaxTime = 0; +b2TimeOfImpact.b2_toiCalls = 0; +b2TimeOfImpact.b2_toiIters = 0; +b2TimeOfImpact.b2_toiMaxIters = 0; +b2TimeOfImpact.b2_toiRootIters = 0; +b2TimeOfImpact.b2_toiMaxRootIters = 0; +"use strict"; + +function b2BodyDef() { + this.type = b2Body.b2_staticBody; + this.position = new b2Vec2(0, 0); + this.angle = 0; + this.linearVelocity = new b2Vec2(0, 0); + this.angularVelocity = 0; + this.linearDamping = 0; + this.angularDamping = 0; + this.allowSleep = true; + this.awake = true; + this.fixedRotation = false; + this.bullet = false; + this.active = true; + this.userData = null; + this.gravityScale = 1; + Object.seal(this) +} +b2BodyDef.prototype = { + _deserialize: function (data) { + this.type = data.type; + this.position._deserialize(data.position); + this.angle = data.angle; + this.linearVelocity._deserialize(data.linearVelocity); + this.angularVelocity = data.angularVelocity; + this.linearDamping = data.linearDamping; + this.angularDamping = data.angularDamping; + this.allowSleep = data.allowSleep; + this.awake = data.awake; + this.fixedRotation = data.fixedRotation; + this.bullet = data.bullet; + this.active = data.active; + this.gravityScale = data.gravityScale + } +}; + +function b2Body(bd, world) { + this.m_islandIndex = 0; + this.m_flags = 0; + if (bd.bullet) { + this.m_flags |= b2Body.e_bulletFlag + } + if (bd.fixedRotation) { + this.m_flags |= b2Body.e_fixedRotationFlag + } + if (bd.allowSleep) { + this.m_flags |= b2Body.e_autoSleepFlag + } + if (bd.awake) { + this.m_flags |= b2Body.e_awakeFlag + } + if (bd.active) { + this.m_flags |= b2Body.e_activeFlag + } + this.m_world = world; + this.m_xf = new b2Transform(); + this.m_xf.p.Assign(bd.position); + this.m_xf.q.Set(bd.angle); + this.m_sweep = new b2Sweep(); + this.m_sweep.localCenter.SetZero(); + this.m_sweep.c0.Assign(this.m_xf.p); + this.m_sweep.c.Assign(this.m_xf.p); + this.m_sweep.a0 = bd.angle; + this.m_sweep.a = bd.angle; + this.m_sweep.alpha0 = 0; + this.m_jointList = null; + this.m_contactList = null; + this.m_prev = null; + this.m_next = null; + this.m_linearVelocity = bd.linearVelocity.Clone(); + this.m_angularVelocity = bd.angularVelocity; + this.m_linearDamping = bd.linearDamping; + this.m_angularDamping = bd.angularDamping; + this.m_gravityScale = bd.gravityScale; + this.m_force = new b2Vec2(); + this.m_torque = 0; + this.m_sleepTime = 0; + this.m_type = bd.type; + if (this.m_type == b2Body.b2_dynamicBody) { + this.m_mass = 1; + this.m_invMass = 1 + } else { + this.m_mass = 0; + this.m_invMass = 0 + } + this.m_I = 0; + this.m_invI = 0; + this.m_userData = bd.userData; + this.m_fixtureList = null; + this.m_fixtureCount = 0 +} +b2Body.b2_staticBody = 0; +b2Body.b2_kinematicBody = 1; +b2Body.b2_dynamicBody = 2; +b2Body.e_islandFlag = 1; +b2Body.e_awakeFlag = 2; +b2Body.e_autoSleepFlag = 4; +b2Body.e_bulletFlag = 8; +b2Body.e_fixedRotationFlag = 16; +b2Body.e_activeFlag = 32; +b2Body.e_toiFlag = 64; +b2Body.m_local_oldCenter = new b2Vec2(); +b2Body.m_local_xf1 = new b2Transform(); +b2Body.prototype = { + CreateFixture: function (def, density) { + if (typeof (density) !== "undefined") { + var ndef = new b2FixtureDef(); + ndef.shape = def; + ndef.density = density; + return this.CreateFixture(ndef) + } + if (this.m_world.IsLocked() == true) { + return null + } + var fixture = new b2Fixture(); + fixture.Create(this, def); + if (this.m_flags & b2Body.e_activeFlag) { + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + fixture.CreateProxies(broadPhase, this.m_xf) + } + fixture.m_next = this.m_fixtureList; + this.m_fixtureList = fixture; + ++this.m_fixtureCount; + fixture.m_body = this; + if (fixture.m_density > 0) { this.ResetMassData() - }, - SetTransform: function (position, angle) { - if (this.m_world.IsLocked() == true) { - return + } + this.m_world.m_flags |= b2World.e_newFixture; + return fixture + }, + DestroyFixture: function (fixture) { + if (this.m_world.IsLocked() == true) { + return + } + var node = this.m_fixtureList; + var found = false; + while (node != null) { + if (node == fixture) { + this.m_fixtureList = node = fixture.m_next; + found = true; + break } - this.m_xf.q.Set(angle); - this.m_xf.p.Assign(position); - this.m_sweep.c.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); - this.m_sweep.a = angle; + node = node.m_next + } + 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.m_world.m_contactManager.Destroy(c) + } + } + if (this.m_flags & b2Body.e_activeFlag) { + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + fixture.DestroyProxies(broadPhase) + } + fixture.Destroy(); + fixture.m_body = null; + fixture.m_next = null; + --this.m_fixtureCount; + this.ResetMassData() + }, + SetTransform: function (position, angle) { + if (this.m_world.IsLocked() == true) { + return + } + this.m_xf.q.Set(angle); + this.m_xf.p.Assign(position); + this.m_sweep.c.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.a = angle; + this.m_sweep.c0.Assign(this.m_sweep.c); + this.m_sweep.a0 = angle; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.Synchronize(broadPhase, this.m_xf, this.m_xf) + } + }, + GetTransform: function () { + return this.m_xf + }, + GetPosition: function () { + return this.m_xf.p + }, + GetAngle: function () { + return this.m_sweep.a + }, + GetWorldCenter: function () { + return this.m_sweep.c + }, + GetLocalCenter: function () { + return this.m_sweep.localCenter + }, + SetLinearVelocity: function (v) { + if (this.m_type == b2Body.b2_staticBody) { + return + } + if (b2Dot_v2_v2(v, v) > 0) { + this.SetAwake(true) + } + this.m_linearVelocity = v + }, + GetLinearVelocity: function () { + return this.m_linearVelocity + }, + SetAngularVelocity: function (w) { + if (this.m_type == b2Body.b2_staticBody) { + return + } + if (w * w > 0) { + this.SetAwake(true) + } + this.m_angularVelocity = w + }, + GetAngularVelocity: function () { + return this.m_angularVelocity + }, + ApplyForce: function (force, point, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_force.Add(force); + this.m_torque += b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), force) + } + }, + ApplyForceToCenter: function (force, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_force.Add(force) + } + }, + ApplyTorque: function (torque, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_torque += torque + } + }, + ApplyLinearImpulse: function (impulse, point, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_linearVelocity.Add(b2Vec2.Multiply(this.m_invMass, impulse)); + this.m_angularVelocity += this.m_invI * b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), impulse) + } + }, + ApplyAngularImpulse: function (impulse, wake) { + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { + this.SetAwake(true) + } + if (this.m_flags & b2Body.e_awakeFlag) { + this.m_angularVelocity += this.m_invI * impulse + } + }, + GetMass: function () { + return this.m_mass + }, + GetInertia: function () { + return this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter) + }, + GetMassData: function (data) { + data.mass = this.m_mass; + data.I = this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter); + data.center = this.m_sweep.localCenter + }, + SetMassData: function (massData) { + if (this.m_world.IsLocked() == true) { + return + } + if (this.m_type != b2Body.b2_dynamicBody) { + return + } + this.m_invMass = 0; + this.m_I = 0; + this.m_invI = 0; + this.m_mass = massData.mass; + if (this.m_mass <= 0) { + this.m_mass = 1 + } + this.m_invMass = 1 / this.m_mass; + if (massData.I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { + this.m_I = massData.I - this.m_mass * b2Dot_v2_v2(massData.center, massData.center); + this.m_invI = 1 / this.m_I + } + b2Body.m_local_oldCenter.Assign(this.m_sweep.c); + this.m_sweep.localCenter.Assign(massData.center); + this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) + }, + ResetMassData: function () { + this.m_mass = 0; + this.m_invMass = 0; + this.m_I = 0; + this.m_invI = 0; + this.m_sweep.localCenter.SetZero(); + if (this.m_type == b2Body.b2_staticBody || this.m_type == b2Body.b2_kinematicBody) { + this.m_sweep.c0.Assign(this.m_xf.p); + this.m_sweep.c.Assign(this.m_xf.p); + this.m_sweep.a0 = this.m_sweep.a; + return + } + var localCenter = new b2Vec2(0, 0); + for (var f = this.m_fixtureList; f; f = f.m_next) { + if (f.m_density == 0) { + continue + } + var massData = new b2MassData(); + f.GetMassData(massData); + this.m_mass += massData.mass; + localCenter.Add(b2Vec2.Multiply(massData.mass, massData.center)); + this.m_I += massData.I + } + if (this.m_mass > 0) { + this.m_invMass = 1 / this.m_mass; + localCenter.Multiply(this.m_invMass) + } else { + this.m_mass = 1; + this.m_invMass = 1 + } + if (this.m_I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { + this.m_I -= this.m_mass * b2Dot_v2_v2(localCenter, localCenter); + this.m_invI = 1 / this.m_I + } else { + this.m_I = 0; + this.m_invI = 0 + } + b2Body.m_local_oldCenter.Assign(this.m_sweep.c); + this.m_sweep.localCenter.Assign(localCenter); + this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) + }, + GetWorldPoint: function (localPoint) { + return b2Mul_t_v2(this.m_xf, localPoint) + }, + GetWorldVector: function (localVector) { + return b2Mul_r_v2(this.m_xf.q, localVector) + }, + GetLocalPoint: function (worldPoint) { + return b2MulT_t_v2(this.m_xf, worldPoint) + }, + GetLocalVector: function (worldVector) { + return b2MulT_r_v2(this.m_xf.q, worldVector) + }, + GetLinearVelocityFromWorldPoint: function (worldPoint) { + return b2Vec2.Add(this.m_linearVelocity, b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(worldPoint, this.m_sweep.c))) + }, + GetLinearVelocityFromLocalPoint: function (localPoint) { + return this.GetLinearVelocityFromWorldPoint(this.GetWorldPoint(localPoint)) + }, + GetLinearDamping: function () { + return this.m_linearDamping + }, + SetLinearDamping: function (linearDamping) { + this.m_linearDamping = linearDamping + }, + GetAngularDamping: function () { + return this.m_angularDamping + }, + SetAngularDamping: function (angularDamping) { + this.m_angularDamping = angularDamping + }, + GetGravityScale: function () { + return this.m_gravityScale + }, + SetGravityScale: function (scale) { + this.m_gravityScale = scale + }, + SetType: function (type) { + if (this.m_world.IsLocked() == true) { + return + } + if (this.m_type == type) { + return + } + this.m_type = type; + this.ResetMassData(); + if (this.m_type == b2Body.b2_staticBody) { + this.m_linearVelocity.SetZero(); + this.m_angularVelocity = 0; + this.m_sweep.a0 = this.m_sweep.a; this.m_sweep.c0.Assign(this.m_sweep.c); - this.m_sweep.a0 = angle; + this.SynchronizeFixtures() + } + this.SetAwake(true); + this.m_force.SetZero(); + this.m_torque = 0; + var ce = this.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_world.m_contactManager.Destroy(ce0.contact) + } + this.m_contactList = null; + var broadPhase = this.m_world.m_contactManager.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) + } + } + }, + GetType: function () { + return this.m_type + }, + SetBullet: function (flag) { + if (flag) { + this.m_flags |= b2Body.e_bulletFlag + } else { + this.m_flags &= ~b2Body.e_bulletFlag + } + }, + IsBullet: function () { + return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag + }, + SetSleepingAllowed: function (flag) { + if (flag) { + this.m_flags |= b2Body.e_autoSleepFlag + } else { + this.m_flags &= ~b2Body.e_autoSleepFlag; + this.SetAwake(true) + } + }, + IsSleepingAllowed: function () { + return (this.m_flags & b2Body.e_autoSleepFlag) == b2Body.e_autoSleepFlag + }, + SetAwake: function (flag) { + if (flag) { + if ((this.m_flags & b2Body.e_awakeFlag) == 0) { + this.m_flags |= b2Body.e_awakeFlag; + this.m_sleepTime = 0 + } + } else { + this.m_flags &= ~b2Body.e_awakeFlag; + this.m_sleepTime = 0; + this.m_linearVelocity.SetZero(); + this.m_angularVelocity = 0; + this.m_force.SetZero(); + this.m_torque = 0 + } + }, + IsAwake: function () { + return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag + }, + SetActive: function (flag) { + if (flag == this.IsActive()) { + return + } + if (flag) { + this.m_flags |= b2Body.e_activeFlag; var broadPhase = this.m_world.m_contactManager.m_broadPhase; for (var f = this.m_fixtureList; f; f = f.m_next) { - f.Synchronize(broadPhase, this.m_xf, this.m_xf) + f.CreateProxies(broadPhase, this.m_xf) } - }, - GetTransform: function () { - return this.m_xf - }, - GetPosition: function () { - return this.m_xf.p - }, - GetAngle: function () { - return this.m_sweep.a - }, - GetWorldCenter: function () { - return this.m_sweep.c - }, - GetLocalCenter: function () { - return this.m_sweep.localCenter - }, - SetLinearVelocity: function (v) { - if (this.m_type == b2Body.b2_staticBody) { - return - } - if (b2Dot_v2_v2(v, v) > 0) { - this.SetAwake(true) - } - this.m_linearVelocity = v - }, - GetLinearVelocity: function () { - return this.m_linearVelocity - }, - SetAngularVelocity: function (w) { - if (this.m_type == b2Body.b2_staticBody) { - return - } - if (w * w > 0) { - this.SetAwake(true) - } - this.m_angularVelocity = w - }, - GetAngularVelocity: function () { - return this.m_angularVelocity - }, - ApplyForce: function (force, point, wake) { - if (this.m_type != b2Body.b2_dynamicBody) { - return - } - if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { - this.SetAwake(true) - } - if (this.m_flags & b2Body.e_awakeFlag) { - this.m_force.Add(force); - this.m_torque += b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), force) - } - }, - ApplyForceToCenter: function (force, wake) { - if (this.m_type != b2Body.b2_dynamicBody) { - return - } - if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { - this.SetAwake(true) - } - if (this.m_flags & b2Body.e_awakeFlag) { - this.m_force.Add(force) - } - }, - ApplyTorque: function (torque, wake) { - if (this.m_type != b2Body.b2_dynamicBody) { - return - } - if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { - this.SetAwake(true) - } - if (this.m_flags & b2Body.e_awakeFlag) { - this.m_torque += torque - } - }, - ApplyLinearImpulse: function (impulse, point, wake) { - if (this.m_type != b2Body.b2_dynamicBody) { - return - } - if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { - this.SetAwake(true) - } - if (this.m_flags & b2Body.e_awakeFlag) { - this.m_linearVelocity.Add(b2Vec2.Multiply(this.m_invMass, impulse)); - this.m_angularVelocity += this.m_invI * b2Cross_v2_v2(b2Vec2.Subtract(point, this.m_sweep.c), impulse) - } - }, - ApplyAngularImpulse: function (impulse, wake) { - if (this.m_type != b2Body.b2_dynamicBody) { - return - } - if (wake && (this.m_flags & b2Body.e_awakeFlag) == 0) { - this.SetAwake(true) - } - if (this.m_flags & b2Body.e_awakeFlag) { - this.m_angularVelocity += this.m_invI * impulse - } - }, - GetMass: function () { - return this.m_mass - }, - GetInertia: function () { - return this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter) - }, - GetMassData: function (data) { - data.mass = this.m_mass; - data.I = this.m_I + this.m_mass * b2Dot_v2_v2(this.m_sweep.localCenter, this.m_sweep.localCenter); - data.center = this.m_sweep.localCenter - }, - SetMassData: function (massData) { - if (this.m_world.IsLocked() == true) { - return - } - if (this.m_type != b2Body.b2_dynamicBody) { - return - } - this.m_invMass = 0; - this.m_I = 0; - this.m_invI = 0; - this.m_mass = massData.mass; - if (this.m_mass <= 0) { - this.m_mass = 1 - } - this.m_invMass = 1 / this.m_mass; - if (massData.I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { - this.m_I = massData.I - this.m_mass * b2Dot_v2_v2(massData.center, massData.center); - this.m_invI = 1 / this.m_I - } - b2Body.m_local_oldCenter.Assign(this.m_sweep.c); - this.m_sweep.localCenter.Assign(massData.center); - this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); - this.m_sweep.c.Assign(this.m_sweep.c0); - this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) - }, - ResetMassData: function () { - this.m_mass = 0; - this.m_invMass = 0; - this.m_I = 0; - this.m_invI = 0; - this.m_sweep.localCenter.SetZero(); - if (this.m_type == b2Body.b2_staticBody || this.m_type == b2Body.b2_kinematicBody) { - this.m_sweep.c0.Assign(this.m_xf.p); - this.m_sweep.c.Assign(this.m_xf.p); - this.m_sweep.a0 = this.m_sweep.a; - return - } - var localCenter = new b2Vec2(0, 0); + } else { + this.m_flags &= ~b2Body.e_activeFlag; + var broadPhase = this.m_world.m_contactManager.m_broadPhase; for (var f = this.m_fixtureList; f; f = f.m_next) { - if (f.m_density == 0) { - continue - } - var massData = new b2MassData(); - f.GetMassData(massData); - this.m_mass += massData.mass; - localCenter.Add(b2Vec2.Multiply(massData.mass, massData.center)); - this.m_I += massData.I + f.DestroyProxies(broadPhase) } - if (this.m_mass > 0) { - this.m_invMass = 1 / this.m_mass; - localCenter.Multiply(this.m_invMass) - } else { - this.m_mass = 1; - this.m_invMass = 1 - } - if (this.m_I > 0 && (this.m_flags & b2Body.e_fixedRotationFlag) == 0) { - this.m_I -= this.m_mass * b2Dot_v2_v2(localCenter, localCenter); - this.m_invI = 1 / this.m_I - } else { - this.m_I = 0; - this.m_invI = 0 - } - b2Body.m_local_oldCenter.Assign(this.m_sweep.c); - this.m_sweep.localCenter.Assign(localCenter); - this.m_sweep.c0.Assign(b2Mul_t_v2(this.m_xf, this.m_sweep.localCenter)); - this.m_sweep.c.Assign(this.m_sweep.c0); - this.m_linearVelocity.Add(b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(this.m_sweep.c, b2Body.m_local_oldCenter))) - }, - GetWorldPoint: function (localPoint) { - return b2Mul_t_v2(this.m_xf, localPoint) - }, - GetWorldVector: function (localVector) { - return b2Mul_r_v2(this.m_xf.q, localVector) - }, - GetLocalPoint: function (worldPoint) { - return b2MulT_t_v2(this.m_xf, worldPoint) - }, - GetLocalVector: function (worldVector) { - return b2MulT_r_v2(this.m_xf.q, worldVector) - }, - GetLinearVelocityFromWorldPoint: function (worldPoint) { - return b2Vec2.Add(this.m_linearVelocity, b2Cross_f_v2(this.m_angularVelocity, b2Vec2.Subtract(worldPoint, this.m_sweep.c))) - }, - GetLinearVelocityFromLocalPoint: function (localPoint) { - return this.GetLinearVelocityFromWorldPoint(this.GetWorldPoint(localPoint)) - }, - GetLinearDamping: function () { - return this.m_linearDamping - }, - SetLinearDamping: function (linearDamping) { - this.m_linearDamping = linearDamping - }, - GetAngularDamping: function () { - return this.m_angularDamping - }, - SetAngularDamping: function (angularDamping) { - this.m_angularDamping = angularDamping - }, - GetGravityScale: function () { - return this.m_gravityScale - }, - SetGravityScale: function (scale) { - this.m_gravityScale = scale - }, - SetType: function (type) { - if (this.m_world.IsLocked() == true) { - return - } - if (this.m_type == type) { - return - } - this.m_type = type; - this.ResetMassData(); - if (this.m_type == b2Body.b2_staticBody) { - this.m_linearVelocity.SetZero(); - this.m_angularVelocity = 0; - this.m_sweep.a0 = this.m_sweep.a; - this.m_sweep.c0.Assign(this.m_sweep.c); - this.SynchronizeFixtures() - } - this.SetAwake(true); - this.m_force.SetZero(); - this.m_torque = 0; var ce = this.m_contactList; while (ce) { var ce0 = ce; ce = ce.next; this.m_world.m_contactManager.Destroy(ce0.contact) } - this.m_contactList = null; - var broadPhase = this.m_world.m_contactManager.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) - } - } - }, - GetType: function () { - return this.m_type - }, - SetBullet: function (flag) { - if (flag) { - this.m_flags |= b2Body.e_bulletFlag - } else { - this.m_flags &= ~b2Body.e_bulletFlag - } - }, - IsBullet: function () { - return (this.m_flags & b2Body.e_bulletFlag) == b2Body.e_bulletFlag - }, - SetSleepingAllowed: function (flag) { - if (flag) { - this.m_flags |= b2Body.e_autoSleepFlag - } else { - this.m_flags &= ~b2Body.e_autoSleepFlag; - this.SetAwake(true) - } - }, - IsSleepingAllowed: function () { - return (this.m_flags & b2Body.e_autoSleepFlag) == b2Body.e_autoSleepFlag - }, - SetAwake: function (flag) { - if (flag) { - if ((this.m_flags & b2Body.e_awakeFlag) == 0) { - this.m_flags |= b2Body.e_awakeFlag; - this.m_sleepTime = 0 - } - } else { - this.m_flags &= ~b2Body.e_awakeFlag; - this.m_sleepTime = 0; - this.m_linearVelocity.SetZero(); - this.m_angularVelocity = 0; - this.m_force.SetZero(); - this.m_torque = 0 - } - }, - IsAwake: function () { - return (this.m_flags & b2Body.e_awakeFlag) == b2Body.e_awakeFlag - }, - SetActive: function (flag) { - if (flag == this.IsActive()) { - return - } - if (flag) { - this.m_flags |= b2Body.e_activeFlag; - var broadPhase = this.m_world.m_contactManager.m_broadPhase; - for (var f = this.m_fixtureList; f; f = f.m_next) { - f.CreateProxies(broadPhase, this.m_xf) - } - } else { - this.m_flags &= ~b2Body.e_activeFlag; - var broadPhase = this.m_world.m_contactManager.m_broadPhase; - for (var f = this.m_fixtureList; f; f = f.m_next) { - f.DestroyProxies(broadPhase) - } - var ce = this.m_contactList; - while (ce) { - var ce0 = ce; - ce = ce.next; - this.m_world.m_contactManager.Destroy(ce0.contact) - } - this.m_contactList = null - } - }, - IsActive: function () { - return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag - }, - SetFixedRotation: function (flag) { - var status = (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag; - if (status == flag) { - return - } - if (flag) { - this.m_flags |= b2Body.e_fixedRotationFlag - } else { - this.m_flags &= ~b2Body.e_fixedRotationFlag - } - this.m_angularVelocity = 0; - this.ResetMassData() - }, - IsFixedRotation: function () { - return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag - }, - GetFixtureList: function () { - return this.m_fixtureList - }, - GetJointList: function () { - return this.m_jointList - }, - GetContactList: function () { - return this.m_contactList - }, - GetNext: function () { - return this.m_next - }, - GetUserData: function () { - return this.m_userData - }, - SetUserData: function (data) { - this.m_userData = data - }, - GetWorld: function () { - return this.m_world - }, - SynchronizeFixtures: function () { - b2Body.m_local_xf1.q.Set(this.m_sweep.a0); - b2Body.m_local_xf1.p.Assign(b2Vec2.Subtract(this.m_sweep.c0, b2Mul_r_v2(b2Body.m_local_xf1.q, this.m_sweep.localCenter))); - var broadPhase = this.m_world.m_contactManager.m_broadPhase; - for (var f = this.m_fixtureList; f; f = f.m_next) { - f.Synchronize(broadPhase, b2Body.m_local_xf1, this.m_xf) - } - }, - SynchronizeTransform: function () { - this.m_xf.q.Set(this.m_sweep.a); - this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) - }, - ShouldCollide: function (other) { - if (this.m_type != b2Body.b2_dynamicBody && other.m_type != b2Body.b2_dynamicBody) { - return false - } - for (var jn = this.m_jointList; jn; jn = jn.next) { - if (jn.other == other) { - if (jn.joint.m_collideConnected == false) { - return false - } - } - } - return true - }, - Advance: function (alpha) { - this.m_sweep.Advance(alpha); - this.m_sweep.c.Assign(this.m_sweep.c0); - this.m_sweep.a = this.m_sweep.a0; - this.m_xf.q.Set(this.m_sweep.a); - this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) - }, - _serialize: function (out) { - var obj = out || {}; - obj.fixtures = null; - obj.type = this.m_type; - obj.position = this.GetPosition()._serialize(); - obj.angle = this.GetAngle(); - obj.linearVelocity = this.GetLinearVelocity()._serialize(); - obj.angularVelocity = this.GetAngularVelocity(); - obj.linearDamping = this.GetLinearDamping(); - obj.angularDamping = this.GetAngularDamping(); - obj.allowSleep = this.IsSleepingAllowed(); - obj.awake = this.IsAwake(); - obj.fixedRotation = this.IsFixedRotation(); - obj.bullet = this.IsBullet(); - obj.active = this.IsActive(); - obj.gravityScale = this.GetGravityScale(); - return obj + this.m_contactList = null } - }; - "use strict"; - - function b2Filter() { - this.categoryBits = 1; - this.maskBits = 65535; - this.groupIndex = 0 - } - b2Filter.prototype = { - Clone: function () { - var filter = new b2Filter(); - filter.categoryBits = this.categoryBits; - filter.maskBits = this.maskBits; - filter.groupIndex = this.groupIndex; - return filter - }, - Assign: function (filter) { - this.categoryBits = filter.categoryBits; - this.maskBits = filter.maskBits; - this.groupIndex = filter.groupIndex - }, - _serialize: function (out) { - var obj = out || {}; - obj.categoryBits = this.categoryBits; - obj.maskBits = this.maskBits; - obj.groupIndex = this.groupIndex; - return obj - }, - _deserialize: function (data) { - this.categoryBits = data.categoryBits; - this.maskBits = data.maskBits; - this.groupIndex = data.groupIndex + }, + IsActive: function () { + return (this.m_flags & b2Body.e_activeFlag) == b2Body.e_activeFlag + }, + SetFixedRotation: function (flag) { + var status = (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag; + if (status == flag) { + return } - }; - - function b2FixtureDef() { - this.shape = null; - this.userData = null; - this.friction = 0.2; - this.restitution = 0; - this.density = 0; - this.isSensor = false; - this.filter = new b2Filter(); - Object.seal(this) - } - b2FixtureDef.prototype = { - _deserialize: function (data) { - this.friction = data.friction; - this.restitution = data.restitution; - this.density = data.density; - this.isSensor = data.isSensor; - this.filter._deserialize(data.filter) + if (flag) { + this.m_flags |= b2Body.e_fixedRotationFlag + } else { + this.m_flags &= ~b2Body.e_fixedRotationFlag } - }; - - function b2FixtureProxy() { - this.aabb = new b2AABB(); - this.fixture = null; - this.childIndex = 0; - this.proxyId = 0 + this.m_angularVelocity = 0; + this.ResetMassData() + }, + IsFixedRotation: function () { + return (this.m_flags & b2Body.e_fixedRotationFlag) == b2Body.e_fixedRotationFlag + }, + GetFixtureList: function () { + return this.m_fixtureList + }, + GetJointList: function () { + return this.m_jointList + }, + GetContactList: function () { + return this.m_contactList + }, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + GetWorld: function () { + return this.m_world + }, + SynchronizeFixtures: function () { + b2Body.m_local_xf1.q.Set(this.m_sweep.a0); + b2Body.m_local_xf1.p.Assign(b2Vec2.Subtract(this.m_sweep.c0, b2Mul_r_v2(b2Body.m_local_xf1.q, this.m_sweep.localCenter))); + var broadPhase = this.m_world.m_contactManager.m_broadPhase; + for (var f = this.m_fixtureList; f; f = f.m_next) { + f.Synchronize(broadPhase, b2Body.m_local_xf1, this.m_xf) + } + }, + SynchronizeTransform: function () { + this.m_xf.q.Set(this.m_sweep.a); + this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) + }, + ShouldCollide: function (other) { + if (this.m_type != b2Body.b2_dynamicBody && other.m_type != b2Body.b2_dynamicBody) { + return false + } + for (var jn = this.m_jointList; jn; jn = jn.next) { + if (jn.other == other) { + if (jn.joint.m_collideConnected == false) { + return false + } + } + } + return true + }, + Advance: function (alpha) { + this.m_sweep.Advance(alpha); + this.m_sweep.c.Assign(this.m_sweep.c0); + this.m_sweep.a = this.m_sweep.a0; + this.m_xf.q.Set(this.m_sweep.a); + this.m_xf.p.Assign(b2Vec2.Subtract(this.m_sweep.c, b2Mul_r_v2(this.m_xf.q, this.m_sweep.localCenter))) + }, + _serialize: function (out) { + var obj = out || {}; + obj.fixtures = null; + obj.type = this.m_type; + obj.position = this.GetPosition()._serialize(); + obj.angle = this.GetAngle(); + obj.linearVelocity = this.GetLinearVelocity()._serialize(); + obj.angularVelocity = this.GetAngularVelocity(); + obj.linearDamping = this.GetLinearDamping(); + obj.angularDamping = this.GetAngularDamping(); + obj.allowSleep = this.IsSleepingAllowed(); + obj.awake = this.IsAwake(); + obj.fixedRotation = this.IsFixedRotation(); + obj.bullet = this.IsBullet(); + obj.active = this.IsActive(); + obj.gravityScale = this.GetGravityScale(); + return obj } +}; +"use strict"; - function b2Fixture() { - this.m_userData = null; - this.m_body = null; +function b2Filter() { + this.categoryBits = 1; + this.maskBits = 65535; + this.groupIndex = 0 +} +b2Filter.prototype = { + Clone: function () { + var filter = new b2Filter(); + filter.categoryBits = this.categoryBits; + filter.maskBits = this.maskBits; + filter.groupIndex = this.groupIndex; + return filter + }, + Assign: function (filter) { + this.categoryBits = filter.categoryBits; + this.maskBits = filter.maskBits; + this.groupIndex = filter.groupIndex + }, + _serialize: function (out) { + var obj = out || {}; + obj.categoryBits = this.categoryBits; + obj.maskBits = this.maskBits; + obj.groupIndex = this.groupIndex; + return obj + }, + _deserialize: function (data) { + this.categoryBits = data.categoryBits; + this.maskBits = data.maskBits; + this.groupIndex = data.groupIndex + } +}; + +function b2FixtureDef() { + this.shape = null; + this.userData = null; + this.friction = 0.2; + this.restitution = 0; + this.density = 0; + this.isSensor = false; + this.filter = new b2Filter(); + Object.seal(this) +} +b2FixtureDef.prototype = { + _deserialize: function (data) { + this.friction = data.friction; + this.restitution = data.restitution; + this.density = data.density; + this.isSensor = data.isSensor; + this.filter._deserialize(data.filter) + } +}; + +function b2FixtureProxy() { + this.aabb = new b2AABB(); + this.fixture = null; + this.childIndex = 0; + this.proxyId = 0 +} + +function b2Fixture() { + this.m_userData = null; + this.m_body = null; + this.m_next = null; + this.m_proxies = null; + this.m_proxyCount = 0; + this.m_shape = null; + this.m_density = 0; + this.m_filter = new b2Filter(); + this.m_isSensor = false; + this.m_friction = 0; + this.m_restitution = 0 +} +b2Fixture.prototype = { + GetType: function () { + return this.m_shape.GetType() + }, + GetShape: function () { + return this.m_shape + }, + SetSensor: function (sensor) { + if (sensor != this.m_isSensor) { + this.m_body.SetAwake(true); + this.m_isSensor = sensor + } + }, + IsSensor: function () { + return this.m_isSensor + }, + SetFilterData: function (filter) { + this.m_filter = filter; + this.Refilter() + }, + GetFilterData: function () { + return this.m_filter + }, + Refilter: function () { + if (this.m_body == null) { + return + } + 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 + } + var broadPhase = world.m_contactManager.m_broadPhase; + for (var i = 0; i < this.m_proxyCount; ++i) { + broadPhase.TouchProxy(this.m_proxies[i].proxyId) + } + }, + GetBody: function () { + return this.m_body + }, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + TestPoint: function (p) { + return this.m_shape.TestPoint(this.m_body.GetTransform(), p) + }, + RayCast: function (output, input, childIndex) { + return this.m_shape.RayCast(output, input, this.m_body.GetTransform(), childIndex) + }, + GetMassData: function (massData) { + this.m_shape.ComputeMass(massData, this.m_density) + }, + SetDensity: function (density) { + this.m_density = density + }, + GetDensity: function () { + return this.m_density + }, + GetFriction: function () { + return this.m_friction + }, + SetFriction: function (friction) { + this.m_friction = friction + }, + GetRestitution: function () { + return this.m_restitution + }, + SetRestitution: function (restitution) { + this.m_restitution = restitution + }, + GetAABB: function (childIndex) { + return this.m_proxies[childIndex].aabb + }, + Create: function (body, def) { + this.m_userData = def.userData; + this.m_friction = def.friction; + this.m_restitution = def.restitution; + this.m_body = body; this.m_next = null; - this.m_proxies = null; + this.m_filter.Assign(def.filter); + this.m_isSensor = def.isSensor; + this.m_shape = def.shape.Clone(); + var childCount = this.m_shape.GetChildCount(); + this.m_proxies = new Array(childCount); + for (var i = 0; i < childCount; ++i) { + this.m_proxies[i] = new b2FixtureProxy(); + this.m_proxies[i].fixture = null; + this.m_proxies[i].proxyId = b2BroadPhase.e_nullProxy + } this.m_proxyCount = 0; - this.m_shape = null; - this.m_density = 0; - this.m_filter = new b2Filter(); - this.m_isSensor = false; - this.m_friction = 0; - this.m_restitution = 0 + this.m_density = def.density + }, + Destroy: function () { + this.m_proxies = null; + this.m_shape = null + }, + CreateProxies: function (broadPhase, xf) { + 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); + proxy.fixture = this; + proxy.childIndex = i + } + }, + DestroyProxies: function (broadPhase) { + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + broadPhase.DestroyProxy(proxy.proxyId); + proxy.proxyId = b2BroadPhase.e_nullProxy + } + this.m_proxyCount = 0 + }, + Synchronize: function (broadPhase, transform1, transform2) { + if (this.m_proxyCount == 0) { + return + } + for (var i = 0; i < this.m_proxyCount; ++i) { + var proxy = this.m_proxies[i]; + var aabb1 = new b2AABB(), + aabb2 = new b2AABB(); + this.m_shape.ComputeAABB(aabb1, transform1, proxy.childIndex); + this.m_shape.ComputeAABB(aabb2, transform2, proxy.childIndex); + proxy.aabb.Combine(aabb1, aabb2); + var displacement = b2Vec2.Subtract(transform2.p, transform1.p); + broadPhase.MoveProxy(proxy.proxyId, proxy.aabb, displacement) + } + }, + _serialize: function (out) { + var obj = out || {}; + obj.shape = null; + obj.friction = this.m_friction; + obj.restitution = this.m_restitution; + obj.density = this.m_density; + obj.isSensor = this.m_isSensor; + obj.filter = this.m_filter._serialize(); + return obj } - b2Fixture.prototype = { - GetType: function () { - return this.m_shape.GetType() - }, - GetShape: function () { - return this.m_shape - }, - SetSensor: function (sensor) { - if (sensor != this.m_isSensor) { - this.m_body.SetAwake(true); - this.m_isSensor = sensor +}; +"use strict"; + +function b2DestructionListener() {} +b2DestructionListener.prototype = { + SayGoodbyeJoint: function (joint) {}, + SayGoodbyeFixture: function (fixture) {} +}; + +function b2ContactFilter() {} +b2ContactFilter.prototype = { + ShouldCollide: function (fixtureA, fixtureB) { + var filterA = fixtureA.GetFilterData(); + var filterB = fixtureB.GetFilterData(); + if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) { + return filterA.groupIndex > 0 + } + var collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; + return collide + } +}; + +function b2ContactImpulse() { + this.normalImpulses = new Array(b2_maxManifoldPoints); + this.tangentImpulses = new Array(b2_maxManifoldPoints); + this.count = 0 +} + +function b2ContactListener() {} +b2ContactListener.prototype = { + BeginContact: function (contact) {}, + EndContact: function (contact) {}, + PreSolve: function (contact, oldManifold) {}, + PostSolve: function (contact, impulse) {} +}; + +function b2QueryCallback() {} +b2QueryCallback.prototype = { + ReportFixture: function (fixture) {} +}; + +function b2RayCastCallback() {} +b2RayCastCallback.prototype = { + ReportFixture: function (fixture, point, normal, fraction) {} +}; +"use strict"; + +function b2TimeStep() { + this.dt = 0; + this.inv_dt = 0; + this.dtRatio = 0; + this.velocityIterations = 0; + this.positionIterations = 0; + this.warmStarting = false +} + +function b2Position() { + this.c = new b2Vec2(); + this.a = 0 +} + +function b2Velocity() { + this.v = new b2Vec2(); + this.w = 0 +} + +function b2SolverData() { + this.step = new b2TimeStep(); + this.positions = null; + this.velocities = null +} +"use strict"; +var profile_world_step = b2Profiler.create("step"); +var profile_world_collide = b2Profiler.create("collide", "step"); +var profile_world_solve = b2Profiler.create("solve", "step"); +var profile_world_solveTOI = b2Profiler.create("solveTOI", "step"); +var profile_world_broadphase = b2Profiler.create("broadphase", "step"); + +function b2World(gravity) { + this.m_contactManager = new b2ContactManager(); + this.m_destructionListener = null; + this.g_debugDraw = null; + this.m_bodyList = null; + this.m_jointList = null; + this.m_bodyCount = 0; + this.m_jointCount = 0; + this.m_warmStarting = true; + this.m_continuousPhysics = true; + this.m_subStepping = false; + this.m_stepComplete = true; + this.m_allowSleep = true; + this.m_gravity = gravity; + this.m_flags = b2World.e_clearForces; + this.m_inv_dt0 = 0; + this.p_step = new b2TimeStep(); + this.p_island = new b2Island() +} + +function b2WorldQueryWrapper() { + this.broadPhase = null; + this.callback = null +} +b2WorldQueryWrapper.prototype = { + QueryCallback: function (proxyId) { + var proxy = this.broadPhase.GetUserData(proxyId); + return this.callback.ReportFixture(proxy.fixture) + } +}; + +function b2WorldRayCastWrapper() { + this.broadPhase = null; + this.callback = null +} +b2WorldRayCastWrapper.prototype = { + RayCastCallback: function (input, proxyId) { + var userData = this.broadPhase.GetUserData(proxyId); + var proxy = userData; + var fixture = proxy.fixture; + var index = proxy.childIndex; + var output = new b2RayCastOutput(); + var hit = fixture.RayCast(output, input, index); + if (hit) { + var fraction = output.fraction; + var point = b2Vec2.Add(b2Vec2.Multiply((1 - fraction), input.p1), b2Vec2.Multiply(fraction, input.p2)); + return this.callback.ReportFixture(fixture, point, output.normal, fraction) + } + return input.maxFraction + } +}; +b2World.m_local_sweep_backupA = new b2Sweep(); +b2World.m_local_sweep_backupB = new b2Sweep(); +b2World.m_local_sweep_backupC = new b2Sweep(); +b2World.prototype = { + Destroy: function () { + var b = this.m_bodyList; + while (b) { + var bNext = b.m_next; + var f = b.m_fixtureList; + while (f) { + var fNext = f.m_next; + f.m_proxyCount = 0; + f.Destroy(); + f = fNext } - }, - IsSensor: function () { - return this.m_isSensor - }, - SetFilterData: function (filter) { - this.m_filter = filter; - this.Refilter() - }, - GetFilterData: function () { - return this.m_filter - }, - Refilter: function () { - if (this.m_body == null) { - return + b = bNext + } + }, + SetDestructionListener: function (listener) { + this.m_destructionListener = listener + }, + SetContactFilter: function (filter) { + this.m_contactManager.m_contactFilter = filter + }, + SetContactListener: function (listener) { + this.m_contactManager.m_contactListener = listener + }, + SetDebugDraw: function (debugDraw) { + this.g_debugDraw = debugDraw + }, + CreateBody: function (def) { + if (this.IsLocked()) { + return null + } + var b = new b2Body(def, this); + b.m_prev = null; + b.m_next = this.m_bodyList; + if (this.m_bodyList) { + this.m_bodyList.m_prev = b + } + this.m_bodyList = b; + ++this.m_bodyCount; + return b + }, + DestroyBody: function (b) { + if (this.IsLocked()) { + return + } + var je = b.m_jointList; + while (je) { + var je0 = je; + je = je.next; + if (this.m_destructionListener) { + this.m_destructionListener.SayGoodbyeJoint(je0.joint) } - var edge = this.m_body.GetContactList(); + this.DestroyJoint(je0.joint); + b.m_jointList = je + } + b.m_jointList = null; + var ce = b.m_contactList; + while (ce) { + var ce0 = ce; + ce = ce.next; + this.m_contactManager.Destroy(ce0.contact) + } + b.m_contactList = null; + var f = b.m_fixtureList; + while (f) { + var f0 = f; + f = f.m_next; + if (this.m_destructionListener) { + this.m_destructionListener.SayGoodbyeFixture(f0) + } + f0.DestroyProxies(this.m_contactManager.m_broadPhase); + f0.Destroy(); + b.m_fixtureList = f; + b.m_fixtureCount -= 1 + } + b.m_fixtureList = null; + b.m_fixtureCount = 0; + 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 + }, + CreateJoint: function (def) { + if (this.IsLocked()) { + return null + } + var j = b2Joint.Create(def); + j.m_prev = null; + j.m_next = this.m_jointList; + if (this.m_jointList) { + this.m_jointList.m_prev = j + } + this.m_jointList = j; + ++this.m_jointCount; + j.m_edgeA.joint = j; + j.m_edgeA.other = j.m_bodyB; + j.m_edgeA.prev = null; + j.m_edgeA.next = j.m_bodyA.m_jointList; + if (j.m_bodyA.m_jointList) { + j.m_bodyA.m_jointList.prev = j.m_edgeA + } + j.m_bodyA.m_jointList = j.m_edgeA; + j.m_edgeB.joint = j; + j.m_edgeB.other = j.m_bodyA; + j.m_edgeB.prev = null; + j.m_edgeB.next = j.m_bodyB.m_jointList; + if (j.m_bodyB.m_jointList) { + j.m_bodyB.m_jointList.prev = j.m_edgeB + } + j.m_bodyB.m_jointList = j.m_edgeB; + var bodyA = def.bodyA; + var bodyB = def.bodyB; + if (def.collideConnected == false) { + var edge = bodyB.GetContactList(); while (edge) { - var contact = edge.contact; - var fixtureA = contact.GetFixtureA(); - var fixtureB = contact.GetFixtureB(); - if (fixtureA == this || fixtureB == this) { - contact.FlagForFiltering() + if (edge.other == bodyA) { + edge.contact.FlagForFiltering() } edge = edge.next } - var world = this.m_body.GetWorld(); - if (world == null) { - return - } - var broadPhase = world.m_contactManager.m_broadPhase; - for (var i = 0; i < this.m_proxyCount; ++i) { - broadPhase.TouchProxy(this.m_proxies[i].proxyId) - } - }, - GetBody: function () { - return this.m_body - }, - GetNext: function () { - return this.m_next - }, - GetUserData: function () { - return this.m_userData - }, - SetUserData: function (data) { - this.m_userData = data - }, - TestPoint: function (p) { - return this.m_shape.TestPoint(this.m_body.GetTransform(), p) - }, - RayCast: function (output, input, childIndex) { - return this.m_shape.RayCast(output, input, this.m_body.GetTransform(), childIndex) - }, - GetMassData: function (massData) { - this.m_shape.ComputeMass(massData, this.m_density) - }, - SetDensity: function (density) { - this.m_density = density - }, - GetDensity: function () { - return this.m_density - }, - GetFriction: function () { - return this.m_friction - }, - SetFriction: function (friction) { - this.m_friction = friction - }, - GetRestitution: function () { - return this.m_restitution - }, - SetRestitution: function (restitution) { - this.m_restitution = restitution - }, - GetAABB: function (childIndex) { - return this.m_proxies[childIndex].aabb - }, - Create: function (body, def) { - this.m_userData = def.userData; - this.m_friction = def.friction; - this.m_restitution = def.restitution; - this.m_body = body; - this.m_next = null; - this.m_filter.Assign(def.filter); - this.m_isSensor = def.isSensor; - this.m_shape = def.shape.Clone(); - var childCount = this.m_shape.GetChildCount(); - this.m_proxies = new Array(childCount); - for (var i = 0; i < childCount; ++i) { - this.m_proxies[i] = new b2FixtureProxy(); - this.m_proxies[i].fixture = null; - this.m_proxies[i].proxyId = b2BroadPhase.e_nullProxy - } - this.m_proxyCount = 0; - this.m_density = def.density - }, - Destroy: function () { - this.m_proxies = null; - this.m_shape = null - }, - CreateProxies: function (broadPhase, xf) { - 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); - proxy.fixture = this; - proxy.childIndex = i - } - }, - DestroyProxies: function (broadPhase) { - for (var i = 0; i < this.m_proxyCount; ++i) { - var proxy = this.m_proxies[i]; - broadPhase.DestroyProxy(proxy.proxyId); - proxy.proxyId = b2BroadPhase.e_nullProxy - } - this.m_proxyCount = 0 - }, - Synchronize: function (broadPhase, transform1, transform2) { - if (this.m_proxyCount == 0) { - return - } - for (var i = 0; i < this.m_proxyCount; ++i) { - var proxy = this.m_proxies[i]; - var aabb1 = new b2AABB(), - aabb2 = new b2AABB(); - this.m_shape.ComputeAABB(aabb1, transform1, proxy.childIndex); - this.m_shape.ComputeAABB(aabb2, transform2, proxy.childIndex); - proxy.aabb.Combine(aabb1, aabb2); - var displacement = b2Vec2.Subtract(transform2.p, transform1.p); - broadPhase.MoveProxy(proxy.proxyId, proxy.aabb, displacement) - } - }, - _serialize: function (out) { - var obj = out || {}; - obj.shape = null; - obj.friction = this.m_friction; - obj.restitution = this.m_restitution; - obj.density = this.m_density; - obj.isSensor = this.m_isSensor; - obj.filter = this.m_filter._serialize(); - return obj } - }; - "use strict"; - - function b2DestructionListener() {} - b2DestructionListener.prototype = { - SayGoodbyeJoint: function (joint) {}, - SayGoodbyeFixture: function (fixture) {} - }; - - function b2ContactFilter() {} - b2ContactFilter.prototype = { - ShouldCollide: function (fixtureA, fixtureB) { - var filterA = fixtureA.GetFilterData(); - var filterB = fixtureB.GetFilterData(); - if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) { - return filterA.groupIndex > 0 - } - var collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; - return collide + return j + }, + DestroyJoint: function (j) { + if (this.IsLocked()) { + return } - }; - - function b2ContactImpulse() { - this.normalImpulses = new Array(b2_maxManifoldPoints); - this.tangentImpulses = new Array(b2_maxManifoldPoints); - this.count = 0 - } - - function b2ContactListener() {} - b2ContactListener.prototype = { - BeginContact: function (contact) {}, - EndContact: function (contact) {}, - PreSolve: function (contact, oldManifold) {}, - PostSolve: function (contact, impulse) {} - }; - - function b2QueryCallback() {} - b2QueryCallback.prototype = { - ReportFixture: function (fixture) {} - }; - - function b2RayCastCallback() {} - b2RayCastCallback.prototype = { - ReportFixture: function (fixture, point, normal, fraction) {} - }; - "use strict"; - - function b2TimeStep() { - this.dt = 0; - this.inv_dt = 0; - this.dtRatio = 0; - this.velocityIterations = 0; - this.positionIterations = 0; - this.warmStarting = false - } - - function b2Position() { - this.c = new b2Vec2(); - this.a = 0 - } - - function b2Velocity() { - this.v = new b2Vec2(); - this.w = 0 - } - - function b2SolverData() { - this.step = new b2TimeStep(); - this.positions = null; - this.velocities = null - } - "use strict"; - var profile_world_step = b2Profiler.create("step"); - var profile_world_collide = b2Profiler.create("collide", "step"); - var profile_world_solve = b2Profiler.create("solve", "step"); - var profile_world_solveTOI = b2Profiler.create("solveTOI", "step"); - var profile_world_broadphase = b2Profiler.create("broadphase", "step"); - - function b2World(gravity) { - this.m_contactManager = new b2ContactManager(); - this.m_destructionListener = null; - this.g_debugDraw = null; - this.m_bodyList = null; - this.m_jointList = null; - this.m_bodyCount = 0; - this.m_jointCount = 0; - this.m_warmStarting = true; - this.m_continuousPhysics = true; - this.m_subStepping = false; - this.m_stepComplete = true; - this.m_allowSleep = true; - this.m_gravity = gravity; - this.m_flags = b2World.e_clearForces; - this.m_inv_dt0 = 0; - this.p_step = new b2TimeStep(); - this.p_island = new b2Island() - } - - function b2WorldQueryWrapper() { - this.broadPhase = null; - this.callback = null - } - b2WorldQueryWrapper.prototype = { - QueryCallback: function (proxyId) { - var proxy = this.broadPhase.GetUserData(proxyId); - return this.callback.ReportFixture(proxy.fixture) + var collideConnected = j.m_collideConnected; + if (j.m_prev) { + j.m_prev.m_next = j.m_next } - }; - - function b2WorldRayCastWrapper() { - this.broadPhase = null; - this.callback = null - } - b2WorldRayCastWrapper.prototype = { - RayCastCallback: function (input, proxyId) { - var userData = this.broadPhase.GetUserData(proxyId); - var proxy = userData; - var fixture = proxy.fixture; - var index = proxy.childIndex; - var output = new b2RayCastOutput(); - var hit = fixture.RayCast(output, input, index); - if (hit) { - var fraction = output.fraction; - var point = b2Vec2.Add(b2Vec2.Multiply((1 - fraction), input.p1), b2Vec2.Multiply(fraction, input.p2)); - return this.callback.ReportFixture(fixture, point, output.normal, fraction) - } - return input.maxFraction + if (j.m_next) { + j.m_next.m_prev = j.m_prev } - }; - b2World.m_local_sweep_backupA = new b2Sweep(); - b2World.m_local_sweep_backupB = new b2Sweep(); - b2World.m_local_sweep_backupC = new b2Sweep(); - b2World.prototype = { - Destroy: function () { - var b = this.m_bodyList; - while (b) { - var bNext = b.m_next; - var f = b.m_fixtureList; - while (f) { - var fNext = f.m_next; - f.m_proxyCount = 0; - f.Destroy(); - f = fNext + if (j == this.m_jointList) { + this.m_jointList = j.m_next + } + var bodyA = j.m_bodyA; + var bodyB = j.m_bodyB; + bodyA.SetAwake(true); + bodyB.SetAwake(true); + if (j.m_edgeA.prev) { + j.m_edgeA.prev.next = j.m_edgeA.next + } + if (j.m_edgeA.next) { + j.m_edgeA.next.prev = j.m_edgeA.prev + } + if (j.m_edgeA == bodyA.m_jointList) { + bodyA.m_jointList = j.m_edgeA.next + } + j.m_edgeA.prev = null; + j.m_edgeA.next = null; + if (j.m_edgeB.prev) { + j.m_edgeB.prev.next = j.m_edgeB.next + } + if (j.m_edgeB.next) { + j.m_edgeB.next.prev = j.m_edgeB.prev + } + if (j.m_edgeB == bodyB.m_jointList) { + bodyB.m_jointList = j.m_edgeB.next + } + j.m_edgeB.prev = null; + j.m_edgeB.next = null; + b2Joint.Destroy(j); + --this.m_jointCount; + if (collideConnected == false) { + var edge = bodyB.GetContactList(); + while (edge) { + if (edge.other == bodyA) { + edge.contact.FlagForFiltering() } - b = bNext + edge = edge.next } - }, - SetDestructionListener: function (listener) { - this.m_destructionListener = listener - }, - SetContactFilter: function (filter) { - this.m_contactManager.m_contactFilter = filter - }, - SetContactListener: function (listener) { - this.m_contactManager.m_contactListener = listener - }, - SetDebugDraw: function (debugDraw) { - this.g_debugDraw = debugDraw - }, - CreateBody: function (def) { - if (this.IsLocked()) { - return null - } - var b = new b2Body(def, this); - b.m_prev = null; - b.m_next = this.m_bodyList; - if (this.m_bodyList) { - this.m_bodyList.m_prev = b - } - this.m_bodyList = b; - ++this.m_bodyCount; - return b - }, - DestroyBody: function (b) { - if (this.IsLocked()) { - return - } - var je = b.m_jointList; - while (je) { - var je0 = je; - je = je.next; - if (this.m_destructionListener) { - this.m_destructionListener.SayGoodbyeJoint(je0.joint) - } - this.DestroyJoint(je0.joint); - b.m_jointList = je - } - b.m_jointList = null; - var ce = b.m_contactList; - while (ce) { - var ce0 = ce; - ce = ce.next; - this.m_contactManager.Destroy(ce0.contact) - } - b.m_contactList = null; - var f = b.m_fixtureList; - while (f) { - var f0 = f; - f = f.m_next; - if (this.m_destructionListener) { - this.m_destructionListener.SayGoodbyeFixture(f0) - } - f0.DestroyProxies(this.m_contactManager.m_broadPhase); - f0.Destroy(); - b.m_fixtureList = f; - b.m_fixtureCount -= 1 - } - b.m_fixtureList = null; - b.m_fixtureCount = 0; - 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 - }, - CreateJoint: function (def) { - if (this.IsLocked()) { - return null - } - var j = b2Joint.Create(def); - j.m_prev = null; - j.m_next = this.m_jointList; - if (this.m_jointList) { - this.m_jointList.m_prev = j - } - this.m_jointList = j; - ++this.m_jointCount; - j.m_edgeA.joint = j; - j.m_edgeA.other = j.m_bodyB; - j.m_edgeA.prev = null; - j.m_edgeA.next = j.m_bodyA.m_jointList; - if (j.m_bodyA.m_jointList) { - j.m_bodyA.m_jointList.prev = j.m_edgeA - } - j.m_bodyA.m_jointList = j.m_edgeA; - j.m_edgeB.joint = j; - j.m_edgeB.other = j.m_bodyA; - j.m_edgeB.prev = null; - j.m_edgeB.next = j.m_bodyB.m_jointList; - if (j.m_bodyB.m_jointList) { - j.m_bodyB.m_jointList.prev = j.m_edgeB - } - j.m_bodyB.m_jointList = j.m_edgeB; - var bodyA = def.bodyA; - var bodyB = def.bodyB; - if (def.collideConnected == false) { - var edge = bodyB.GetContactList(); - while (edge) { - if (edge.other == bodyA) { - edge.contact.FlagForFiltering() - } - edge = edge.next - } - } - return j - }, - DestroyJoint: function (j) { - if (this.IsLocked()) { - return - } - var collideConnected = j.m_collideConnected; - if (j.m_prev) { - j.m_prev.m_next = j.m_next - } - if (j.m_next) { - j.m_next.m_prev = j.m_prev - } - if (j == this.m_jointList) { - this.m_jointList = j.m_next - } - var bodyA = j.m_bodyA; - var bodyB = j.m_bodyB; - bodyA.SetAwake(true); - bodyB.SetAwake(true); - if (j.m_edgeA.prev) { - j.m_edgeA.prev.next = j.m_edgeA.next - } - if (j.m_edgeA.next) { - j.m_edgeA.next.prev = j.m_edgeA.prev - } - if (j.m_edgeA == bodyA.m_jointList) { - bodyA.m_jointList = j.m_edgeA.next - } - j.m_edgeA.prev = null; - j.m_edgeA.next = null; - if (j.m_edgeB.prev) { - j.m_edgeB.prev.next = j.m_edgeB.next - } - if (j.m_edgeB.next) { - j.m_edgeB.next.prev = j.m_edgeB.prev - } - if (j.m_edgeB == bodyB.m_jointList) { - bodyB.m_jointList = j.m_edgeB.next - } - j.m_edgeB.prev = null; - j.m_edgeB.next = null; - b2Joint.Destroy(j); - --this.m_jointCount; - if (collideConnected == false) { - var edge = bodyB.GetContactList(); - while (edge) { - if (edge.other == bodyA) { - edge.contact.FlagForFiltering() - } - edge = edge.next - } - } - }, - Step: function (dt, velocityIterations, positionIterations) { - profile_world_step.start(); - if (this.m_flags & b2World.e_newFixture) { - this.m_contactManager.FindNewContacts(); - this.m_flags &= ~b2World.e_newFixture - } - this.m_flags |= b2World.e_locked; - this.p_step.dt = dt; - this.p_step.velocityIterations = velocityIterations; - this.p_step.positionIterations = positionIterations; - if (dt > 0) { - this.p_step.inv_dt = 1 / dt - } else { - this.p_step.inv_dt = 0 - } - this.p_step.dtRatio = this.m_inv_dt0 * dt; - this.p_step.warmStarting = this.m_warmStarting; - profile_world_collide.start(); - this.m_contactManager.Collide(); - profile_world_collide.stop(); - if (this.m_stepComplete && this.p_step.dt > 0) { - profile_world_solve.start(); - this.Solve(this.p_step); - profile_world_solve.stop() - } - if (this.m_continuousPhysics && this.p_step.dt > 0) { - profile_world_solveTOI.start(); - this.SolveTOI(this.p_step); - profile_world_solveTOI.stop() - } - if (this.p_step.dt > 0) { - this.m_inv_dt0 = this.p_step.inv_dt - } - if (this.m_flags & b2World.e_clearForces) { - this.ClearForces() - } - this.m_flags &= ~b2World.e_locked; - profile_world_step.stop() - }, - ClearForces: function () { - for (var body = this.m_bodyList; body; body = body.GetNext()) { - body.m_force.x = body.m_force.y = 0; - body.m_torque = 0 - } - }, - DrawDebugData: function () { - if (this.g_debugDraw == null) { - return - } - var flags = this.g_debugDraw.GetFlags(); - if (flags & b2Draw.e_shapeBit) { - for (var b = this.m_bodyList; b; b = b.GetNext()) { - var xf = b.GetTransform(); - for (var f = b.GetFixtureList(); f; f = f.GetNext()) { - if (b.IsActive() == false) { - this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.3)) + } + }, + Step: function (dt, velocityIterations, positionIterations) { + profile_world_step.start(); + if (this.m_flags & b2World.e_newFixture) { + this.m_contactManager.FindNewContacts(); + this.m_flags &= ~b2World.e_newFixture + } + this.m_flags |= b2World.e_locked; + this.p_step.dt = dt; + this.p_step.velocityIterations = velocityIterations; + this.p_step.positionIterations = positionIterations; + if (dt > 0) { + this.p_step.inv_dt = 1 / dt + } else { + this.p_step.inv_dt = 0 + } + this.p_step.dtRatio = this.m_inv_dt0 * dt; + this.p_step.warmStarting = this.m_warmStarting; + profile_world_collide.start(); + this.m_contactManager.Collide(); + profile_world_collide.stop(); + if (this.m_stepComplete && this.p_step.dt > 0) { + profile_world_solve.start(); + this.Solve(this.p_step); + profile_world_solve.stop() + } + if (this.m_continuousPhysics && this.p_step.dt > 0) { + profile_world_solveTOI.start(); + this.SolveTOI(this.p_step); + profile_world_solveTOI.stop() + } + if (this.p_step.dt > 0) { + this.m_inv_dt0 = this.p_step.inv_dt + } + if (this.m_flags & b2World.e_clearForces) { + this.ClearForces() + } + this.m_flags &= ~b2World.e_locked; + profile_world_step.stop() + }, + ClearForces: function () { + for (var body = this.m_bodyList; body; body = body.GetNext()) { + body.m_force.x = body.m_force.y = 0; + body.m_torque = 0 + } + }, + DrawDebugData: function () { + if (this.g_debugDraw == null) { + return + } + var flags = this.g_debugDraw.GetFlags(); + if (flags & b2Draw.e_shapeBit) { + for (var b = this.m_bodyList; b; b = b.GetNext()) { + var xf = b.GetTransform(); + for (var f = b.GetFixtureList(); f; f = f.GetNext()) { + if (b.IsActive() == false) { + this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.3)) + } else { + if (b.GetType() == b2Body.b2_staticBody) { + this.DrawShape(f, xf, new b2Color(0.5, 0.9, 0.5)) } else { - if (b.GetType() == b2Body.b2_staticBody) { - this.DrawShape(f, xf, new b2Color(0.5, 0.9, 0.5)) + if (b.GetType() == b2Body.b2_kinematicBody) { + this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.9)) } else { - if (b.GetType() == b2Body.b2_kinematicBody) { - this.DrawShape(f, xf, new b2Color(0.5, 0.5, 0.9)) + if (b.IsAwake() == false) { + this.DrawShape(f, xf, new b2Color(0.6, 0.6, 0.6)) } else { - if (b.IsAwake() == false) { - this.DrawShape(f, xf, new b2Color(0.6, 0.6, 0.6)) - } else { - this.DrawShape(f, xf, new b2Color(0.9, 0.7, 0.7)) - } + this.DrawShape(f, xf, new b2Color(0.9, 0.7, 0.7)) } } } } } } - if (flags & b2Draw.e_jointBit) { - for (var j = this.m_jointList; j; j = j.GetNext()) { - this.DrawJoint(j) + } + if (flags & b2Draw.e_jointBit) { + for (var j = this.m_jointList; j; j = j.GetNext()) { + this.DrawJoint(j) + } + } + if (flags & b2Draw.e_pairBit) { + var color = new b2Color(0.3, 0.9, 0.9); + for (var c = this.m_contactManager.m_contactList; c; c = c.GetNext()) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var cA = fixtureA.GetAABB(c.GetChildIndexA()).GetCenter(); + var cB = fixtureB.GetAABB(c.GetChildIndexB()).GetCenter(); + this.g_debugDraw.DrawSegment(cA, cB, color) + } + } + if (flags & b2Draw.e_aabbBit) { + var color = new b2Color(0.9, 0.3, 0.9); + var bp = this.m_contactManager.m_broadPhase; + for (var b = this.m_bodyList; b; b = b.GetNext()) { + if (b.IsActive() == false) { + continue + } + for (var f = b.GetFixtureList(); f; f = f.GetNext()) { + for (var i = 0; i < f.m_proxyCount; ++i) { + var proxy = f.m_proxies[i]; + var aabb = bp.GetFatAABB(proxy.proxyId); + var vs = []; + vs[0] = new b2Vec2(aabb.lowerBound.x, aabb.lowerBound.y); + vs[1] = new b2Vec2(aabb.upperBound.x, aabb.lowerBound.y); + vs[2] = new b2Vec2(aabb.upperBound.x, aabb.upperBound.y); + vs[3] = new b2Vec2(aabb.lowerBound.x, aabb.upperBound.y); + this.g_debugDraw.DrawPolygon(vs, 4, color) + } } } - if (flags & b2Draw.e_pairBit) { - var color = new b2Color(0.3, 0.9, 0.9); - for (var c = this.m_contactManager.m_contactList; c; c = c.GetNext()) { - var fixtureA = c.GetFixtureA(); - var fixtureB = c.GetFixtureB(); - var cA = fixtureA.GetAABB(c.GetChildIndexA()).GetCenter(); - var cB = fixtureB.GetAABB(c.GetChildIndexB()).GetCenter(); - this.g_debugDraw.DrawSegment(cA, cB, color) - } + } + if (flags & b2Draw.e_centerOfMassBit) { + for (var b = this.m_bodyList; b; b = b.GetNext()) { + var xf = b.GetTransform().Clone(); + xf.p = b.GetWorldCenter(); + this.g_debugDraw.DrawTransform(xf) } - if (flags & b2Draw.e_aabbBit) { - var color = new b2Color(0.9, 0.3, 0.9); - var bp = this.m_contactManager.m_broadPhase; - for (var b = this.m_bodyList; b; b = b.GetNext()) { - if (b.IsActive() == false) { + } + }, + QueryAABB: function (callback, aabb) { + var wrapper = new b2WorldQueryWrapper(); + wrapper.broadPhase = this.m_contactManager.m_broadPhase; + wrapper.callback = callback; + this.m_contactManager.m_broadPhase.Query(wrapper, aabb) + }, + RayCast: function (callback, point1, point2) { + var wrapper = new b2WorldRayCastWrapper(); + wrapper.broadPhase = this.m_contactManager.m_broadPhase; + wrapper.callback = callback; + var input = new b2RayCastInput(); + input.maxFraction = 1; + input.p1 = point1; + input.p2 = point2; + this.m_contactManager.m_broadPhase.RayCast(wrapper, input) + }, + GetBodyList: function () { + return this.m_bodyList + }, + GetJointList: function () { + return this.m_jointList + }, + GetContactList: function () { + return this.m_contactManager.m_contactList + }, + 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) + } + } + }, + GetAllowSleeping: function () { + return this.m_allowSleep + }, + SetWarmStarting: function (flag) { + this.m_warmStarting = flag + }, + GetWarmStarting: function () { + return this.m_warmStarting + }, + SetContinuousPhysics: function (flag) { + this.m_continuousPhysics = flag + }, + GetContinuousPhysics: function () { + return this.m_continuousPhysics + }, + SetSubStepping: function (flag) { + this.m_subStepping = flag + }, + GetSubStepping: function () { + return this.m_subStepping + }, + GetProxyCount: function () { + return this.m_contactManager.m_broadPhase.GetProxyCount() + }, + GetBodyCount: function () { + return this.m_bodyCount + }, + GetJointCount: function () { + return this.m_jointCount + }, + GetContactCount: function () { + return this.m_contactManager.m_contactCount + }, + GetTreeHeight: function () { + return this.m_contactManager.m_broadPhase.GetTreeHeight() + }, + GetTreeBalance: function () { + return this.m_contactManager.m_broadPhase.GetTreeBalance() + }, + GetTreeQuality: function () { + return this.m_contactManager.m_broadPhase.GetTreeQuality() + }, + SetGravity: function (gravity) { + this.m_gravity = gravity + }, + GetGravity: function () { + return this.m_gravity + }, + IsLocked: function () { + return (this.m_flags & b2World.e_locked) == b2World.e_locked + }, + SetAutoClearForces: function (flag) { + if (flag) { + this.m_flags |= b2World.e_clearForces + } else { + this.m_flags &= ~b2World.e_clearForces + } + }, + GetAutoClearForces: function () { + return (this.m_flags & b2World.e_clearForces) == b2World.e_clearForces + }, + ShiftOrigin: function (newOrigin) { + if ((this.m_flags & b2World.e_locked) == b2World.e_locked) { + return + } + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_xf.p.Subtract(newOrigin); + b.m_sweep.c0.Subtract(newOrigin); + b.m_sweep.c.Subtract(newOrigin) + } + for (var j = this.m_jointList; j; j = j.m_next) { + j.ShiftOrigin(newOrigin) + } + this.m_contactManager.m_broadPhase.ShiftOrigin(newOrigin) + }, + GetContactManager: function () { + return this.m_contactManager + }, + Solve: function (step) { + this.p_island.Initialize(this.m_bodyCount, this.m_contactManager.m_contactCount, this.m_jointCount, this.m_contactManager.m_contactListener); + for (var b = this.m_bodyList; b; b = b.m_next) { + b.m_flags &= ~b2Body.e_islandFlag + } + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + c.m_flags &= ~b2Contact.e_islandFlag + } + for (var j = this.m_jointList; j; j = j.m_next) { + j.m_islandFlag = false + } + var stackSize = this.m_bodyCount; + var stack = new Array(stackSize); + for (var seed = this.m_bodyList; seed; seed = seed.m_next) { + if (seed.m_flags & b2Body.e_islandFlag) { + continue + } + if (seed.IsAwake() == false || seed.IsActive() == false) { + continue + } + if (seed.GetType() == b2Body.b2_staticBody) { + continue + } + this.p_island.Clear(); + var stackCount = 0; + stack[stackCount++] = seed; + seed.m_flags |= b2Body.e_islandFlag; + while (stackCount > 0) { + var b = stack[--stackCount]; + this.p_island.AddBody(b); + b.SetAwake(true); + if (b.GetType() == b2Body.b2_staticBody) { + continue + } + for (var ce = b.m_contactList; ce; ce = ce.next) { + var contact = ce.contact; + if (contact.m_flags & b2Contact.e_islandFlag) { continue } - for (var f = b.GetFixtureList(); f; f = f.GetNext()) { - for (var i = 0; i < f.m_proxyCount; ++i) { - var proxy = f.m_proxies[i]; - var aabb = bp.GetFatAABB(proxy.proxyId); - var vs = []; - vs[0] = new b2Vec2(aabb.lowerBound.x, aabb.lowerBound.y); - vs[1] = new b2Vec2(aabb.upperBound.x, aabb.lowerBound.y); - vs[2] = new b2Vec2(aabb.upperBound.x, aabb.upperBound.y); - vs[3] = new b2Vec2(aabb.lowerBound.x, aabb.upperBound.y); - this.g_debugDraw.DrawPolygon(vs, 4, color) - } + if (contact.IsEnabled() == false || contact.IsTouching() == false) { + continue } + var sensorA = contact.m_fixtureA.m_isSensor; + var sensorB = contact.m_fixtureB.m_isSensor; + if (sensorA || sensorB) { + continue + } + this.p_island.AddContact(contact); + contact.m_flags |= b2Contact.e_islandFlag; + var other = ce.other; + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + stack[stackCount++] = other; + other.m_flags |= b2Body.e_islandFlag + } + for (var je = b.m_jointList; je; je = je.next) { + if (je.joint.m_islandFlag == true) { + continue + } + var other = je.other; + if (other.IsActive() == false) { + continue + } + this.p_island.AddJoint(je.joint); + je.joint.m_islandFlag = true; + if (other.m_flags & b2Body.e_islandFlag) { + continue + } + stack[stackCount++] = other; + other.m_flags |= b2Body.e_islandFlag } } - if (flags & b2Draw.e_centerOfMassBit) { - for (var b = this.m_bodyList; b; b = b.GetNext()) { - var xf = b.GetTransform().Clone(); - xf.p = b.GetWorldCenter(); - this.g_debugDraw.DrawTransform(xf) + this.p_island.Solve(step, this.m_gravity, this.m_allowSleep); + for (var i = 0; i < this.p_island.m_bodyCount; ++i) { + var b = this.p_island.m_bodies[i]; + if (b.GetType() == b2Body.b2_staticBody) { + b.m_flags &= ~b2Body.e_islandFlag } } - }, - QueryAABB: function (callback, aabb) { - var wrapper = new b2WorldQueryWrapper(); - wrapper.broadPhase = this.m_contactManager.m_broadPhase; - wrapper.callback = callback; - this.m_contactManager.m_broadPhase.Query(wrapper, aabb) - }, - RayCast: function (callback, point1, point2) { - var wrapper = new b2WorldRayCastWrapper(); - wrapper.broadPhase = this.m_contactManager.m_broadPhase; - wrapper.callback = callback; - var input = new b2RayCastInput(); - input.maxFraction = 1; - input.p1 = point1; - input.p2 = point2; - this.m_contactManager.m_broadPhase.RayCast(wrapper, input) - }, - GetBodyList: function () { - return this.m_bodyList - }, - GetJointList: function () { - return this.m_jointList - }, - GetContactList: function () { - return this.m_contactManager.m_contactList - }, - SetAllowSleeping: function (flag) { - if (flag == this.m_allowSleep) { - return + } + profile_world_broadphase.start(); + for (var b = this.m_bodyList; b; b = b.GetNext()) { + if ((b.m_flags & b2Body.e_islandFlag) == 0) { + continue } - this.m_allowSleep = flag; - if (this.m_allowSleep == false) { - for (var b = this.m_bodyList; b; b = b.m_next) { - b.SetAwake(true) - } - } - }, - GetAllowSleeping: function () { - return this.m_allowSleep - }, - SetWarmStarting: function (flag) { - this.m_warmStarting = flag - }, - GetWarmStarting: function () { - return this.m_warmStarting - }, - SetContinuousPhysics: function (flag) { - this.m_continuousPhysics = flag - }, - GetContinuousPhysics: function () { - return this.m_continuousPhysics - }, - SetSubStepping: function (flag) { - this.m_subStepping = flag - }, - GetSubStepping: function () { - return this.m_subStepping - }, - GetProxyCount: function () { - return this.m_contactManager.m_broadPhase.GetProxyCount() - }, - GetBodyCount: function () { - return this.m_bodyCount - }, - GetJointCount: function () { - return this.m_jointCount - }, - GetContactCount: function () { - return this.m_contactManager.m_contactCount - }, - GetTreeHeight: function () { - return this.m_contactManager.m_broadPhase.GetTreeHeight() - }, - GetTreeBalance: function () { - return this.m_contactManager.m_broadPhase.GetTreeBalance() - }, - GetTreeQuality: function () { - return this.m_contactManager.m_broadPhase.GetTreeQuality() - }, - SetGravity: function (gravity) { - this.m_gravity = gravity - }, - GetGravity: function () { - return this.m_gravity - }, - IsLocked: function () { - return (this.m_flags & b2World.e_locked) == b2World.e_locked - }, - SetAutoClearForces: function (flag) { - if (flag) { - this.m_flags |= b2World.e_clearForces - } else { - this.m_flags &= ~b2World.e_clearForces - } - }, - GetAutoClearForces: function () { - return (this.m_flags & b2World.e_clearForces) == b2World.e_clearForces - }, - ShiftOrigin: function (newOrigin) { - if ((this.m_flags & b2World.e_locked) == b2World.e_locked) { - return + if (b.GetType() == b2Body.b2_staticBody) { + continue } + b.SynchronizeFixtures() + } + this.m_contactManager.FindNewContacts(); + profile_world_broadphase.stop() + }, + SolveTOI: function (step) { + this.p_island.Initialize(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, this.m_contactManager.m_contactListener); + if (this.m_stepComplete) { for (var b = this.m_bodyList; b; b = b.m_next) { - b.m_xf.p.Subtract(newOrigin); - b.m_sweep.c0.Subtract(newOrigin); - b.m_sweep.c.Subtract(newOrigin) - } - for (var j = this.m_jointList; j; j = j.m_next) { - j.ShiftOrigin(newOrigin) - } - this.m_contactManager.m_broadPhase.ShiftOrigin(newOrigin) - }, - GetContactManager: function () { - return this.m_contactManager - }, - Solve: function (step) { - this.p_island.Initialize(this.m_bodyCount, this.m_contactManager.m_contactCount, this.m_jointCount, this.m_contactManager.m_contactListener); - for (var b = this.m_bodyList; b; b = b.m_next) { - b.m_flags &= ~b2Body.e_islandFlag + b.m_flags &= ~b2Body.e_islandFlag; + b.m_sweep.alpha0 = 0 } for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { - c.m_flags &= ~b2Contact.e_islandFlag + c.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag); + c.m_toiCount = 0; + c.m_toi = 1 } - for (var j = this.m_jointList; j; j = j.m_next) { - j.m_islandFlag = false - } - var stackSize = this.m_bodyCount; - var stack = new Array(stackSize); - for (var seed = this.m_bodyList; seed; seed = seed.m_next) { - if (seed.m_flags & b2Body.e_islandFlag) { + } + for (;;) { + var minContact = null; + var minAlpha = 1; + for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { + if (c.IsEnabled() == false) { continue } - if (seed.IsAwake() == false || seed.IsActive() == false) { + if (c.m_toiCount > b2_maxSubSteps) { continue } - if (seed.GetType() == b2Body.b2_staticBody) { - continue - } - this.p_island.Clear(); - var stackCount = 0; - stack[stackCount++] = seed; - seed.m_flags |= b2Body.e_islandFlag; - while (stackCount > 0) { - var b = stack[--stackCount]; - this.p_island.AddBody(b); - b.SetAwake(true); - if (b.GetType() == b2Body.b2_staticBody) { + var alpha = 1; + if (c.m_flags & b2Contact.e_toiFlag) { + alpha = c.m_toi + } else { + var fA = c.GetFixtureA(); + var fB = c.GetFixtureB(); + if (fA.IsSensor() || fB.IsSensor()) { continue } - for (var ce = b.m_contactList; ce; ce = ce.next) { + var bA = fA.GetBody(); + var bB = fB.GetBody(); + var typeA = bA.m_type; + var typeB = bB.m_type; + var activeA = bA.IsAwake() && typeA != b2Body.b2_staticBody; + var activeB = bB.IsAwake() && typeB != b2Body.b2_staticBody; + if (activeA == false && activeB == false) { + continue + } + var collideA = bA.IsBullet() || typeA != b2Body.b2_dynamicBody; + var collideB = bB.IsBullet() || typeB != b2Body.b2_dynamicBody; + if (collideA == false && collideB == false) { + continue + } + 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) + } + } + var indexA = c.GetChildIndexA(); + var indexB = c.GetChildIndexB(); + var input = new b2TOIInput(); + input.proxyA.Set(fA.GetShape(), indexA); + input.proxyB.Set(fB.GetShape(), indexB); + input.sweepA.Assign(bA.m_sweep); + input.sweepB.Assign(bB.m_sweep); + input.tMax = 1; + var output = new b2TOIOutput(); + b2TimeOfImpact(output, input); + var beta = output.t; + if (output.state == b2TOIOutput.e_touching) { + alpha = b2Min(alpha0 + (1 - alpha0) * beta, 1) + } else { + alpha = 1 + } + c.m_toi = alpha; + c.m_flags |= b2Contact.e_toiFlag + } + if (alpha < minAlpha) { + minContact = c; + minAlpha = alpha + } + } + if (minContact == null || 1 - 10 * b2_epsilon < minAlpha) { + this.m_stepComplete = true; + break + } + var fA = minContact.GetFixtureA(); + var fB = minContact.GetFixtureB(); + var bA = fA.GetBody(); + var bB = fB.GetBody(); + b2World.m_local_sweep_backupA.Assign(bA.m_sweep); + b2World.m_local_sweep_backupB.Assign(bB.m_sweep); + bA.Advance(minAlpha); + bB.Advance(minAlpha); + minContact.Update(this.m_contactManager.m_contactListener); + minContact.m_flags &= ~b2Contact.e_toiFlag; + ++minContact.m_toiCount; + if (minContact.IsEnabled() == false || minContact.IsTouching() == false) { + minContact.SetEnabled(false); + bA.m_sweep.Assign(b2World.m_local_sweep_backupA); + bB.m_sweep.Assign(b2World.m_local_sweep_backupB); + bA.SynchronizeTransform(); + bB.SynchronizeTransform(); + continue + } + bA.SetAwake(true); + bB.SetAwake(true); + this.p_island.Clear(); + this.p_island.AddBody(bA); + this.p_island.AddBody(bB); + this.p_island.AddContact(minContact); + bA.m_flags |= b2Body.e_islandFlag; + bB.m_flags |= b2Body.e_islandFlag; + minContact.m_flags |= b2Contact.e_islandFlag; + var bodies = [bA, bB]; + for (var i = 0; i < 2; ++i) { + var body = bodies[i]; + if (body.m_type == b2Body.b2_dynamicBody) { + for (var ce = body.m_contactList; ce; ce = ce.next) { + if (this.p_island.m_bodyCount == this.p_island.m_bodyCapacity) { + break + } + if (this.p_island.m_contactCount == this.p_island.m_contactCapacity) { + break + } var contact = ce.contact; if (contact.m_flags & b2Contact.e_islandFlag) { continue } - if (contact.IsEnabled() == false || contact.IsTouching() == false) { + var other = ce.other; + if (other.m_type == b2Body.b2_dynamicBody && body.IsBullet() == false && other.IsBullet() == false) { continue } var sensorA = contact.m_fixtureA.m_isSensor; @@ -5484,2082 +5666,1914 @@ if (sensorA || sensorB) { continue } - this.p_island.AddContact(contact); + b2World.m_local_sweep_backupC.Assign(other.m_sweep); + if ((other.m_flags & b2Body.e_islandFlag) == 0) { + other.Advance(minAlpha) + } + contact.Update(this.m_contactManager.m_contactListener); + if (contact.IsEnabled() == false) { + other.m_sweep.Assign(b2World.m_local_sweep_backupC); + other.SynchronizeTransform(); + continue + } + if (contact.IsTouching() == false) { + other.m_sweep.Assign(b2World.m_local_sweep_backupC); + other.SynchronizeTransform(); + continue + } contact.m_flags |= b2Contact.e_islandFlag; - var other = ce.other; + this.p_island.AddContact(contact); if (other.m_flags & b2Body.e_islandFlag) { continue } - stack[stackCount++] = other; - other.m_flags |= b2Body.e_islandFlag - } - for (var je = b.m_jointList; je; je = je.next) { - if (je.joint.m_islandFlag == true) { - continue + other.m_flags |= b2Body.e_islandFlag; + if (other.m_type != b2Body.b2_staticBody) { + other.SetAwake(true) } - var other = je.other; - if (other.IsActive() == false) { - continue - } - this.p_island.AddJoint(je.joint); - je.joint.m_islandFlag = true; - if (other.m_flags & b2Body.e_islandFlag) { - continue - } - stack[stackCount++] = other; - other.m_flags |= b2Body.e_islandFlag - } - } - this.p_island.Solve(step, this.m_gravity, this.m_allowSleep); - for (var i = 0; i < this.p_island.m_bodyCount; ++i) { - var b = this.p_island.m_bodies[i]; - if (b.GetType() == b2Body.b2_staticBody) { - b.m_flags &= ~b2Body.e_islandFlag + this.p_island.AddBody(other) } } } - profile_world_broadphase.start(); - for (var b = this.m_bodyList; b; b = b.GetNext()) { - if ((b.m_flags & b2Body.e_islandFlag) == 0) { + var subStep = new b2TimeStep(); + subStep.dt = (1 - minAlpha) * step.dt; + subStep.inv_dt = 1 / subStep.dt; + subStep.dtRatio = 1; + subStep.positionIterations = 20; + subStep.velocityIterations = step.velocityIterations; + subStep.warmStarting = false; + this.p_island.SolveTOI(subStep, bA.m_islandIndex, bB.m_islandIndex); + for (var i = 0; i < this.p_island.m_bodyCount; ++i) { + var body = this.p_island.m_bodies[i]; + body.m_flags &= ~b2Body.e_islandFlag; + if (body.m_type != b2Body.b2_dynamicBody) { continue } - if (b.GetType() == b2Body.b2_staticBody) { - continue + body.SynchronizeFixtures(); + for (var ce = body.m_contactList; ce; ce = ce.next) { + ce.contact.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag) } - b.SynchronizeFixtures() } this.m_contactManager.FindNewContacts(); - profile_world_broadphase.stop() - }, - SolveTOI: function (step) { - this.p_island.Initialize(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, this.m_contactManager.m_contactListener); - if (this.m_stepComplete) { - for (var b = this.m_bodyList; b; b = b.m_next) { - b.m_flags &= ~b2Body.e_islandFlag; - b.m_sweep.alpha0 = 0 - } - for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { - c.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag); - c.m_toiCount = 0; - c.m_toi = 1 - } - } - for (;;) { - var minContact = null; - var minAlpha = 1; - for (var c = this.m_contactManager.m_contactList; c; c = c.m_next) { - if (c.IsEnabled() == false) { - continue - } - if (c.m_toiCount > b2_maxSubSteps) { - continue - } - var alpha = 1; - if (c.m_flags & b2Contact.e_toiFlag) { - alpha = c.m_toi - } else { - var fA = c.GetFixtureA(); - var fB = c.GetFixtureB(); - if (fA.IsSensor() || fB.IsSensor()) { - continue - } - var bA = fA.GetBody(); - var bB = fB.GetBody(); - var typeA = bA.m_type; - var typeB = bB.m_type; - var activeA = bA.IsAwake() && typeA != b2Body.b2_staticBody; - var activeB = bB.IsAwake() && typeB != b2Body.b2_staticBody; - if (activeA == false && activeB == false) { - continue - } - var collideA = bA.IsBullet() || typeA != b2Body.b2_dynamicBody; - var collideB = bB.IsBullet() || typeB != b2Body.b2_dynamicBody; - if (collideA == false && collideB == false) { - continue - } - 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) - } - } - var indexA = c.GetChildIndexA(); - var indexB = c.GetChildIndexB(); - var input = new b2TOIInput(); - input.proxyA.Set(fA.GetShape(), indexA); - input.proxyB.Set(fB.GetShape(), indexB); - input.sweepA.Assign(bA.m_sweep); - input.sweepB.Assign(bB.m_sweep); - input.tMax = 1; - var output = new b2TOIOutput(); - b2TimeOfImpact(output, input); - var beta = output.t; - if (output.state == b2TOIOutput.e_touching) { - alpha = b2Min(alpha0 + (1 - alpha0) * beta, 1) - } else { - alpha = 1 - } - c.m_toi = alpha; - c.m_flags |= b2Contact.e_toiFlag - } - if (alpha < minAlpha) { - minContact = c; - minAlpha = alpha - } - } - if (minContact == null || 1 - 10 * b2_epsilon < minAlpha) { - this.m_stepComplete = true; - break - } - var fA = minContact.GetFixtureA(); - var fB = minContact.GetFixtureB(); - var bA = fA.GetBody(); - var bB = fB.GetBody(); - b2World.m_local_sweep_backupA.Assign(bA.m_sweep); - b2World.m_local_sweep_backupB.Assign(bB.m_sweep); - bA.Advance(minAlpha); - bB.Advance(minAlpha); - minContact.Update(this.m_contactManager.m_contactListener); - minContact.m_flags &= ~b2Contact.e_toiFlag; - ++minContact.m_toiCount; - if (minContact.IsEnabled() == false || minContact.IsTouching() == false) { - minContact.SetEnabled(false); - bA.m_sweep.Assign(b2World.m_local_sweep_backupA); - bB.m_sweep.Assign(b2World.m_local_sweep_backupB); - bA.SynchronizeTransform(); - bB.SynchronizeTransform(); - continue - } - bA.SetAwake(true); - bB.SetAwake(true); - this.p_island.Clear(); - this.p_island.AddBody(bA); - this.p_island.AddBody(bB); - this.p_island.AddContact(minContact); - bA.m_flags |= b2Body.e_islandFlag; - bB.m_flags |= b2Body.e_islandFlag; - minContact.m_flags |= b2Contact.e_islandFlag; - var bodies = [bA, bB]; - for (var i = 0; i < 2; ++i) { - var body = bodies[i]; - if (body.m_type == b2Body.b2_dynamicBody) { - for (var ce = body.m_contactList; ce; ce = ce.next) { - if (this.p_island.m_bodyCount == this.p_island.m_bodyCapacity) { - break - } - if (this.p_island.m_contactCount == this.p_island.m_contactCapacity) { - break - } - var contact = ce.contact; - if (contact.m_flags & b2Contact.e_islandFlag) { - continue - } - var other = ce.other; - if (other.m_type == b2Body.b2_dynamicBody && body.IsBullet() == false && other.IsBullet() == false) { - continue - } - var sensorA = contact.m_fixtureA.m_isSensor; - var sensorB = contact.m_fixtureB.m_isSensor; - if (sensorA || sensorB) { - continue - } - b2World.m_local_sweep_backupC.Assign(other.m_sweep); - if ((other.m_flags & b2Body.e_islandFlag) == 0) { - other.Advance(minAlpha) - } - contact.Update(this.m_contactManager.m_contactListener); - if (contact.IsEnabled() == false) { - other.m_sweep.Assign(b2World.m_local_sweep_backupC); - other.SynchronizeTransform(); - continue - } - if (contact.IsTouching() == false) { - other.m_sweep.Assign(b2World.m_local_sweep_backupC); - other.SynchronizeTransform(); - continue - } - contact.m_flags |= b2Contact.e_islandFlag; - this.p_island.AddContact(contact); - if (other.m_flags & b2Body.e_islandFlag) { - continue - } - other.m_flags |= b2Body.e_islandFlag; - if (other.m_type != b2Body.b2_staticBody) { - other.SetAwake(true) - } - this.p_island.AddBody(other) - } - } - } - var subStep = new b2TimeStep(); - subStep.dt = (1 - minAlpha) * step.dt; - subStep.inv_dt = 1 / subStep.dt; - subStep.dtRatio = 1; - subStep.positionIterations = 20; - subStep.velocityIterations = step.velocityIterations; - subStep.warmStarting = false; - this.p_island.SolveTOI(subStep, bA.m_islandIndex, bB.m_islandIndex); - for (var i = 0; i < this.p_island.m_bodyCount; ++i) { - var body = this.p_island.m_bodies[i]; - body.m_flags &= ~b2Body.e_islandFlag; - if (body.m_type != b2Body.b2_dynamicBody) { - continue - } - body.SynchronizeFixtures(); - for (var ce = body.m_contactList; ce; ce = ce.next) { - ce.contact.m_flags &= ~(b2Contact.e_toiFlag | b2Contact.e_islandFlag) - } - } - this.m_contactManager.FindNewContacts(); - if (this.m_subStepping) { - this.m_stepComplete = false; - break - } - } - }, - DrawJoint: function (joint) { - var bodyA = joint.GetBodyA(); - var bodyB = joint.GetBodyB(); - var xf1 = bodyA.GetTransform(); - var xf2 = bodyB.GetTransform(); - var x1 = xf1.p; - var x2 = xf2.p; - var p1 = joint.GetAnchorA(); - var p2 = joint.GetAnchorB(); - var color = new b2Color(0.5, 0.8, 0.8); - switch (joint.GetType()) { - case b2Joint.e_distanceJoint: - this.g_debugDraw.DrawSegment(p1, p2, color); - break; - case b2Joint.e_pulleyJoint: - var pulley = joint; - var s1 = pulley.GetGroundAnchorA(); - var s2 = pulley.GetGroundAnchorB(); - this.g_debugDraw.DrawSegment(s1, p1, color); - this.g_debugDraw.DrawSegment(s2, p2, color); - this.g_debugDraw.DrawSegment(s1, s2, color); - break; - case b2Joint.e_mouseJoint: - break; - case b2Joint.e_motorJoint: - this.g_debugDraw.DrawPoint(joint.GetLinearOffset(), 5, color); - default: - this.g_debugDraw.DrawSegment(x1, p1, color); - this.g_debugDraw.DrawSegment(p1, p2, color); - this.g_debugDraw.DrawSegment(x2, p2, color) - } - }, - DrawShape: function (fixture, xf, color) { - switch (fixture.GetType()) { - case b2Shape.e_circle: - var circle = fixture.GetShape(); - var center = b2Mul_t_v2(xf, circle.m_p); - var radius = circle.m_radius; - var axis = b2Mul_r_v2(xf.q, new b2Vec2(1, 0)); - this.g_debugDraw.DrawSolidCircle(center, radius, axis, color); - break; - case b2Shape.e_edge: - var edge = fixture.GetShape(); - var v1 = b2Mul_t_v2(xf, edge.m_vertex1); - var v2 = b2Mul_t_v2(xf, edge.m_vertex2); - this.g_debugDraw.DrawSegment(v1, v2, color); - break; - case b2Shape.e_chain: - var chain = fixture.GetShape(); - var count = chain.m_count; - var vertices = chain.m_vertices; - var v1 = b2Mul_t_v2(xf, vertices[0]); - for (var i = 1; i < count; ++i) { - var v2 = b2Mul_t_v2(xf, vertices[i]); - this.g_debugDraw.DrawSegment(v1, v2, color); - v1 = v2 - } - break; - case b2Shape.e_polygon: - var poly = fixture.GetShape(); - var vertexCount = poly.m_count; - var vertices = new Array(b2_maxPolygonVertices); - for (var i = 0; i < vertexCount; ++i) { - vertices[i] = b2Mul_t_v2(xf, poly.m_vertices[i]) - } - this.g_debugDraw.DrawSolidPolygon(vertices, vertexCount, color); - break; - default: - break + if (this.m_subStepping) { + this.m_stepComplete = false; + break } } - }; - b2World.e_newFixture = 1; - b2World.e_locked = 2; - b2World.e_clearForces = 4; - "use strict"; - - function b2MixFriction(friction1, friction2) { - return b2Sqrt(friction1 * friction2) + }, + DrawJoint: function (joint) { + var bodyA = joint.GetBodyA(); + var bodyB = joint.GetBodyB(); + var xf1 = bodyA.GetTransform(); + var xf2 = bodyB.GetTransform(); + var x1 = xf1.p; + var x2 = xf2.p; + var p1 = joint.GetAnchorA(); + var p2 = joint.GetAnchorB(); + var color = new b2Color(0.5, 0.8, 0.8); + switch (joint.GetType()) { + case b2Joint.e_distanceJoint: + this.g_debugDraw.DrawSegment(p1, p2, color); + break; + case b2Joint.e_pulleyJoint: + var pulley = joint; + var s1 = pulley.GetGroundAnchorA(); + var s2 = pulley.GetGroundAnchorB(); + this.g_debugDraw.DrawSegment(s1, p1, color); + this.g_debugDraw.DrawSegment(s2, p2, color); + this.g_debugDraw.DrawSegment(s1, s2, color); + break; + case b2Joint.e_mouseJoint: + break; + case b2Joint.e_motorJoint: + this.g_debugDraw.DrawPoint(joint.GetLinearOffset(), 5, color); + default: + this.g_debugDraw.DrawSegment(x1, p1, color); + this.g_debugDraw.DrawSegment(p1, p2, color); + this.g_debugDraw.DrawSegment(x2, p2, color) + } + }, + DrawShape: function (fixture, xf, color) { + switch (fixture.GetType()) { + case b2Shape.e_circle: + var circle = fixture.GetShape(); + var center = b2Mul_t_v2(xf, circle.m_p); + var radius = circle.m_radius; + var axis = b2Mul_r_v2(xf.q, new b2Vec2(1, 0)); + this.g_debugDraw.DrawSolidCircle(center, radius, axis, color); + break; + case b2Shape.e_edge: + var edge = fixture.GetShape(); + var v1 = b2Mul_t_v2(xf, edge.m_vertex1); + var v2 = b2Mul_t_v2(xf, edge.m_vertex2); + this.g_debugDraw.DrawSegment(v1, v2, color); + break; + case b2Shape.e_chain: + var chain = fixture.GetShape(); + var count = chain.m_count; + var vertices = chain.m_vertices; + var v1 = b2Mul_t_v2(xf, vertices[0]); + for (var i = 1; i < count; ++i) { + var v2 = b2Mul_t_v2(xf, vertices[i]); + this.g_debugDraw.DrawSegment(v1, v2, color); + v1 = v2 + } + break; + case b2Shape.e_polygon: + var poly = fixture.GetShape(); + var vertexCount = poly.m_count; + var vertices = new Array(b2_maxPolygonVertices); + for (var i = 0; i < vertexCount; ++i) { + vertices[i] = b2Mul_t_v2(xf, poly.m_vertices[i]) + } + this.g_debugDraw.DrawSolidPolygon(vertices, vertexCount, color); + break; + default: + break + } } +}; +b2World.e_newFixture = 1; +b2World.e_locked = 2; +b2World.e_clearForces = 4; +"use strict"; - function b2MixRestitution(restitution1, restitution2) { - return restitution1 > restitution2 ? restitution1 : restitution2 - } +function b2MixFriction(friction1, friction2) { + return b2Sqrt(friction1 * friction2) +} - function b2ContactRegister() { - this.fcn = null; - this.primary = false - } +function b2MixRestitution(restitution1, restitution2) { + return restitution1 > restitution2 ? restitution1 : restitution2 +} - function b2ContactEdge() { - this.other = null; - this.contact = null; - this.prev = null; - this.next = null - } +function b2ContactRegister() { + this.fcn = null; + this.primary = false +} - function b2Contact() { - this.m_nodeA = new b2ContactEdge(); - this.m_nodeB = new b2ContactEdge(); - this.m_manifold = new b2Manifold() - } - b2Contact.m_local_tempManifold = new b2Manifold(); - b2Contact.prototype = { - Create: function (fA, indexA, fB, indexB) { - this.m_toi = 0; - this.m_flags = b2Contact.e_enabledFlag; - this.m_fixtureA = fA || null; - this.m_fixtureB = fB || null; - this.m_indexA = indexA || 0; - this.m_indexB = indexB || 0; - this.m_manifold.pointCount = 0; - this.m_prev = null; - this.m_next = null; - this.m_nodeA.contact = null; - this.m_nodeA.prev = null; - this.m_nodeA.next = null; - this.m_nodeA.other = null; - this.m_nodeB.contact = null; - this.m_nodeB.prev = null; - this.m_nodeB.next = null; - this.m_nodeB.other = null; - this.m_toiCount = 0; - if (fA) { - this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction); - this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) - } else { - this.m_friction = 0; - this.m_restitution = 0 - } - this.m_tangentSpeed = 0 - }, - GetManifold: function () { - return this.m_manifold - }, - GetWorldManifold: function (worldManifold) { - var bodyA = this.m_fixtureA.GetBody(); - var bodyB = this.m_fixtureB.GetBody(); +function b2ContactEdge() { + this.other = null; + this.contact = null; + this.prev = null; + this.next = null +} + +function b2Contact() { + this.m_nodeA = new b2ContactEdge(); + this.m_nodeB = new b2ContactEdge(); + this.m_manifold = new b2Manifold() +} +b2Contact.m_local_tempManifold = new b2Manifold(); +b2Contact.prototype = { + Create: function (fA, indexA, fB, indexB) { + this.m_toi = 0; + this.m_flags = b2Contact.e_enabledFlag; + this.m_fixtureA = fA || null; + this.m_fixtureB = fB || null; + this.m_indexA = indexA || 0; + this.m_indexB = indexB || 0; + this.m_manifold.pointCount = 0; + this.m_prev = null; + this.m_next = null; + this.m_nodeA.contact = null; + this.m_nodeA.prev = null; + this.m_nodeA.next = null; + this.m_nodeA.other = null; + this.m_nodeB.contact = null; + this.m_nodeB.prev = null; + this.m_nodeB.next = null; + this.m_nodeB.other = null; + this.m_toiCount = 0; + if (fA) { + this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction); + this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) + } else { + this.m_friction = 0; + this.m_restitution = 0 + } + this.m_tangentSpeed = 0 + }, + GetManifold: function () { + return this.m_manifold + }, + 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(); + worldManifold.Initialize(this.m_manifold, bodyA.GetTransform(), shapeA.m_radius, bodyB.GetTransform(), shapeB.m_radius) + }, + IsTouching: function () { + return (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag + }, + SetEnabled: function (flag) { + if (flag) { + this.m_flags |= b2Contact.e_enabledFlag + } else { + this.m_flags &= ~b2Contact.e_enabledFlag + } + }, + IsEnabled: function () { + return (this.m_flags & b2Contact.e_enabledFlag) == b2Contact.e_enabledFlag + }, + GetNext: function () { + return this.m_next + }, + GetFixtureA: function () { + return this.m_fixtureA + }, + GetChildIndexA: function () { + return this.m_indexA + }, + GetFixtureB: function () { + return this.m_fixtureB + }, + GetChildIndexB: function () { + return this.m_indexB + }, + SetFriction: function (friction) { + this.m_friction = friction + }, + GetFriction: function () { + return this.m_friction + }, + ResetFriction: function () { + this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction) + }, + SetRestitution: function (restitution) { + this.m_restitution = restitution + }, + GetRestitution: function () { + return this.m_restitution + }, + ResetRestitution: function () { + this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) + }, + SetTangentSpeed: function (speed) { + this.m_tangentSpeed = speed + }, + GetTangentSpeed: function () { + return this.m_tangentSpeed + }, + Evaluate: function (manifold, xfA, xfB) {}, + FlagForFiltering: function () { + this.m_flags |= b2Contact.e_filterFlag + }, + m_oldManifold: null, + Update: function (listener) { + b2Contact.m_local_tempManifold.Assign(this.m_manifold); + this.m_flags |= b2Contact.e_enabledFlag; + var touching = false; + var wasTouching = (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_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(); + if (sensor) { var shapeA = this.m_fixtureA.GetShape(); var shapeB = this.m_fixtureB.GetShape(); - worldManifold.Initialize(this.m_manifold, bodyA.GetTransform(), shapeA.m_radius, bodyB.GetTransform(), shapeB.m_radius) - }, - IsTouching: function () { - return (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_touchingFlag - }, - SetEnabled: function (flag) { - if (flag) { - this.m_flags |= b2Contact.e_enabledFlag - } else { - this.m_flags &= ~b2Contact.e_enabledFlag - } - }, - IsEnabled: function () { - return (this.m_flags & b2Contact.e_enabledFlag) == b2Contact.e_enabledFlag - }, - GetNext: function () { - return this.m_next - }, - GetFixtureA: function () { - return this.m_fixtureA - }, - GetChildIndexA: function () { - return this.m_indexA - }, - GetFixtureB: function () { - return this.m_fixtureB - }, - GetChildIndexB: function () { - return this.m_indexB - }, - SetFriction: function (friction) { - this.m_friction = friction - }, - GetFriction: function () { - return this.m_friction - }, - ResetFriction: function () { - this.m_friction = b2MixFriction(this.m_fixtureA.m_friction, this.m_fixtureB.m_friction) - }, - SetRestitution: function (restitution) { - this.m_restitution = restitution - }, - GetRestitution: function () { - return this.m_restitution - }, - ResetRestitution: function () { - this.m_restitution = b2MixRestitution(this.m_fixtureA.m_restitution, this.m_fixtureB.m_restitution) - }, - SetTangentSpeed: function (speed) { - this.m_tangentSpeed = speed - }, - GetTangentSpeed: function () { - return this.m_tangentSpeed - }, - Evaluate: function (manifold, xfA, xfB) {}, - FlagForFiltering: function () { - this.m_flags |= b2Contact.e_filterFlag - }, - m_oldManifold: null, - Update: function (listener) { - b2Contact.m_local_tempManifold.Assign(this.m_manifold); - this.m_flags |= b2Contact.e_enabledFlag; - var touching = false; - var wasTouching = (this.m_flags & b2Contact.e_touchingFlag) == b2Contact.e_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(); - if (sensor) { - var shapeA = this.m_fixtureA.GetShape(); - var shapeB = this.m_fixtureB.GetShape(); - touching = b2TestShapeOverlap(shapeA, this.m_indexA, shapeB, this.m_indexB, xfA, xfB); - this.m_manifold.pointCount = 0 - } else { - this.Evaluate(this.m_manifold, xfA, xfB); - touching = this.m_manifold.pointCount > 0; - for (var i = 0; i < this.m_manifold.pointCount; ++i) { - var mp2 = this.m_manifold.points[i]; - mp2.normalImpulse = 0; - mp2.tangentImpulse = 0; - var id2 = mp2.id; - for (var j = 0; j < b2Contact.m_local_tempManifold.pointCount; ++j) { - var mp1 = b2Contact.m_local_tempManifold.points[j]; - if (mp1.id.Get() == id2.Get()) { - mp2.normalImpulse = mp1.normalImpulse; - mp2.tangentImpulse = mp1.tangentImpulse; - break - } + touching = b2TestShapeOverlap(shapeA, this.m_indexA, shapeB, this.m_indexB, xfA, xfB); + this.m_manifold.pointCount = 0 + } else { + this.Evaluate(this.m_manifold, xfA, xfB); + touching = this.m_manifold.pointCount > 0; + for (var i = 0; i < this.m_manifold.pointCount; ++i) { + var mp2 = this.m_manifold.points[i]; + mp2.normalImpulse = 0; + mp2.tangentImpulse = 0; + var id2 = mp2.id; + for (var j = 0; j < b2Contact.m_local_tempManifold.pointCount; ++j) { + var mp1 = b2Contact.m_local_tempManifold.points[j]; + if (mp1.id.Get() == id2.Get()) { + mp2.normalImpulse = mp1.normalImpulse; + mp2.tangentImpulse = mp1.tangentImpulse; + break } } - if (touching != wasTouching) { - bodyA.SetAwake(true); - bodyB.SetAwake(true) - } } - if (touching) { - this.m_flags |= b2Contact.e_touchingFlag - } else { - this.m_flags &= ~b2Contact.e_touchingFlag - } - 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, b2Contact.m_local_tempManifold) - } - } - }; - b2Contact.e_islandFlag = 1; - b2Contact.e_touchingFlag = 2; - b2Contact.e_enabledFlag = 4; - b2Contact.e_filterFlag = 8; - b2Contact.e_bulletHitFlag = 16; - b2Contact.e_toiFlag = 32; - - function b2CircleContact() { - this.parent.call(this) - } - b2CircleContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - b2CollideCircles(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, unused1, fixtureB, unused2) { - this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) - } - }; - b2CircleContact._extend(b2Contact); - var _local_temp_edgeShape = new b2EdgeShape(); - - function b2ChainAndCircleContact() { - this.parent.call(this) - } - b2ChainAndCircleContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - var chain = this.m_fixtureA.GetShape(); - chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); - b2CollideEdgeAndCircle(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, indexA, fixtureB, indexB) { - this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) - } - }; - b2ChainAndCircleContact._extend(b2Contact); - - function b2ChainAndPolygonContact() { - this.parent.call(this) - } - b2ChainAndPolygonContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - var chain = this.m_fixtureA.GetShape(); - chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); - b2CollideEdgeAndPolygon(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, indexA, fixtureB, indexB) { - this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) - } - }; - b2ChainAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { - return new b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB) - }; - b2ChainAndPolygonContact._extend(b2Contact); - - function b2EdgeAndCircleContact() { - this.parent.call(this) - } - b2EdgeAndCircleContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - b2CollideEdgeAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, indexA, fixtureB, indexB) { - this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) - } - }; - b2EdgeAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { - return new b2EdgeAndCircleContact(fixtureA, fixtureB) - }; - b2EdgeAndCircleContact._extend(b2Contact); - - function b2EdgeAndPolygonContact() { - this.parent.call(this) - } - b2EdgeAndPolygonContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - b2CollideEdgeAndPolygon(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, indexA, fixtureB, indexB) { - this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) - } - }; - b2EdgeAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { - return new b2EdgeAndPolygonContact(fixtureA, fixtureB) - }; - b2EdgeAndPolygonContact._extend(b2Contact); - - function b2PolygonAndCircleContact() { - this.parent.call(this) - } - b2PolygonAndCircleContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - b2CollidePolygonAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, indexA, fixtureB, indexB) { - this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) - } - }; - b2PolygonAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { - return new b2PolygonAndCircleContact(fixtureA, fixtureB) - }; - b2PolygonAndCircleContact._extend(b2Contact); - - function b2PolygonContact() { - this.parent.call(this) - } - b2PolygonContact.prototype = { - Evaluate: function (manifold, xfA, xfB) { - b2CollidePolygons(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) - }, - Create: function (fixtureA, indexA, fixtureB, indexB) { - this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) - } - }; - b2PolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { - return new b2PolygonContact(fixtureA, fixtureB) - }; - b2PolygonContact._extend(b2Contact); - b2Contact.AddType = function (fcn, type1, type2) { - if (!b2Contact.s_registers[type1]) { - b2Contact.s_registers[type1] = [] - } - b2Contact.s_registers[type1][type2] = new b2ContactRegister(); - b2Contact.s_registers[type1][type2].fcn = fcn; - b2Contact.s_registers[type1][type2].primary = true; - if (type1 != type2) { - if (!b2Contact.s_registers[type2]) { - b2Contact.s_registers[type2] = [] - } - b2Contact.s_registers[type2][type1] = new b2ContactRegister(); - b2Contact.s_registers[type2][type1].fcn = fcn; - b2Contact.s_registers[type2][type1].primary = false - } - fcn.garbage = []; - fcn.alloc = 2 - }; - b2Contact.InitializeRegisters = function () { - b2Contact.AddType(b2CircleContact, b2Shape.e_circle, b2Shape.e_circle); - b2Contact.AddType(b2PolygonAndCircleContact, b2Shape.e_polygon, b2Shape.e_circle); - b2Contact.AddType(b2PolygonContact, b2Shape.e_polygon, b2Shape.e_polygon); - b2Contact.AddType(b2EdgeAndCircleContact, b2Shape.e_edge, b2Shape.e_circle); - b2Contact.AddType(b2EdgeAndPolygonContact, b2Shape.e_edge, b2Shape.e_polygon); - b2Contact.AddType(b2ChainAndCircleContact, b2Shape.e_chain, b2Shape.e_circle); - b2Contact.AddType(b2ChainAndPolygonContact, b2Shape.e_chain, b2Shape.e_polygon) - }; - b2Contact.RetrieveGarbage = function (fcn) { - var contact; - if (contact = fcn.garbage.pop()) { - return contact - } - for (var i = 0; i < fcn.alloc - 1; ++i) { - fcn.garbage.push(new fcn()) - } - fcn.alloc += 32; - return new fcn() - }; - b2Contact.Create = function (fixtureA, indexA, fixtureB, indexB) { - if (b2Contact.s_initialized == false) { - b2Contact.InitializeRegisters(); - b2Contact.s_initialized = true - } - var type1 = fixtureA.GetType(); - var type2 = fixtureB.GetType(); - var fcn = b2Contact.s_registers[type1][type2].fcn; - if (fcn) { - var contact = b2Contact.RetrieveGarbage(fcn); - if (b2Contact.s_registers[type1][type2].primary) { - contact.Create(fixtureA, indexA, fixtureB, indexB) - } else { - contact.Create(fixtureB, indexB, fixtureA, indexA) - } - return contact - } - return null - }; - b2Contact.Destroy = function (contact) { - var fixtureA = contact.m_fixtureA; - var fixtureB = contact.m_fixtureB; - if (contact.m_manifold.pointCount > 0 && fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { - fixtureA.GetBody().SetAwake(true); - fixtureB.GetBody().SetAwake(true) - } - var typeA = fixtureA.GetType(); - var typeB = fixtureB.GetType(); - b2Contact.s_registers[typeA][typeB].fcn.garbage.push(contact) - }; - b2Contact.s_registers = []; - b2Contact.s_initialized = false; - "use strict"; - var b2_defaultFilter = new b2ContactFilter(); - var b2_defaultListener = new b2ContactListener(); - - function b2ContactManager() { - this.m_broadPhase = new b2BroadPhase(); - this.m_contactList = null; - this.m_contactCount = 0; - this.m_contactFilter = b2_defaultFilter; - this.m_contactListener = b2_defaultListener - } - b2ContactManager.prototype = { - AddPair: function (proxyUserDataA, proxyUserDataB) { - var proxyA = proxyUserDataA; - var proxyB = proxyUserDataB; - var fixtureA = proxyA.fixture; - var fixtureB = proxyB.fixture; - var indexA = proxyA.childIndex; - var indexB = proxyB.childIndex; - var bodyA = fixtureA.GetBody(); - var bodyB = fixtureB.GetBody(); - if (bodyA == bodyB) { - return - } - var edge = bodyB.GetContactList(); - 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) { - return - } - if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { - return - } - } - edge = edge.next - } - if (bodyB.ShouldCollide(bodyA) == false) { - return - } - if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { - return - } - var c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB); - if (c == null) { - return - } - fixtureA = c.GetFixtureA(); - fixtureB = c.GetFixtureB(); - indexA = c.GetChildIndexA(); - indexB = c.GetChildIndexB(); - bodyA = fixtureA.GetBody(); - bodyB = fixtureB.GetBody(); - c.m_prev = null; - c.m_next = this.m_contactList; - if (this.m_contactList != null) { - this.m_contactList.m_prev = c - } - this.m_contactList = c; - c.m_nodeA.contact = c; - c.m_nodeA.other = bodyB; - c.m_nodeA.prev = null; - c.m_nodeA.next = bodyA.m_contactList; - if (bodyA.m_contactList != null) { - bodyA.m_contactList.prev = c.m_nodeA - } - bodyA.m_contactList = c.m_nodeA; - c.m_nodeB.contact = c; - c.m_nodeB.other = bodyA; - c.m_nodeB.prev = null; - c.m_nodeB.next = bodyB.m_contactList; - if (bodyB.m_contactList != null) { - bodyB.m_contactList.prev = c.m_nodeB - } - bodyB.m_contactList = c.m_nodeB; - if (fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + if (touching != wasTouching) { bodyA.SetAwake(true); bodyB.SetAwake(true) - }++this.m_contactCount - }, - FindNewContacts: function () { - this.m_broadPhase.UpdatePairs(this) - }, - Destroy: function (c) { + } + } + if (touching) { + this.m_flags |= b2Contact.e_touchingFlag + } else { + this.m_flags &= ~b2Contact.e_touchingFlag + } + 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, b2Contact.m_local_tempManifold) + } + } +}; +b2Contact.e_islandFlag = 1; +b2Contact.e_touchingFlag = 2; +b2Contact.e_enabledFlag = 4; +b2Contact.e_filterFlag = 8; +b2Contact.e_bulletHitFlag = 16; +b2Contact.e_toiFlag = 32; + +function b2CircleContact() { + this.parent.call(this) +} +b2CircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideCircles(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, unused1, fixtureB, unused2) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2CircleContact._extend(b2Contact); +var _local_temp_edgeShape = new b2EdgeShape(); + +function b2ChainAndCircleContact() { + this.parent.call(this) +} +b2ChainAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + var chain = this.m_fixtureA.GetShape(); + chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); + b2CollideEdgeAndCircle(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) + } +}; +b2ChainAndCircleContact._extend(b2Contact); + +function b2ChainAndPolygonContact() { + this.parent.call(this) +} +b2ChainAndPolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + var chain = this.m_fixtureA.GetShape(); + chain.GetChildEdge(_local_temp_edgeShape, this.m_indexA); + b2CollideEdgeAndPolygon(manifold, _local_temp_edgeShape, xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, indexA, fixtureB, indexB) + } +}; +b2ChainAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB) +}; +b2ChainAndPolygonContact._extend(b2Contact); + +function b2EdgeAndCircleContact() { + this.parent.call(this) +} +b2EdgeAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideEdgeAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2EdgeAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2EdgeAndCircleContact(fixtureA, fixtureB) +}; +b2EdgeAndCircleContact._extend(b2Contact); + +function b2EdgeAndPolygonContact() { + this.parent.call(this) +} +b2EdgeAndPolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollideEdgeAndPolygon(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2EdgeAndPolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2EdgeAndPolygonContact(fixtureA, fixtureB) +}; +b2EdgeAndPolygonContact._extend(b2Contact); + +function b2PolygonAndCircleContact() { + this.parent.call(this) +} +b2PolygonAndCircleContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollidePolygonAndCircle(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2PolygonAndCircleContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2PolygonAndCircleContact(fixtureA, fixtureB) +}; +b2PolygonAndCircleContact._extend(b2Contact); + +function b2PolygonContact() { + this.parent.call(this) +} +b2PolygonContact.prototype = { + Evaluate: function (manifold, xfA, xfB) { + b2CollidePolygons(manifold, this.m_fixtureA.GetShape(), xfA, this.m_fixtureB.GetShape(), xfB) + }, + Create: function (fixtureA, indexA, fixtureB, indexB) { + this.parent.prototype.Create.call(this, fixtureA, 0, fixtureB, 0) + } +}; +b2PolygonContact.Create = function (fixtureA, indexA, fixtureB, indexB) { + return new b2PolygonContact(fixtureA, fixtureB) +}; +b2PolygonContact._extend(b2Contact); +b2Contact.AddType = function (fcn, type1, type2) { + if (!b2Contact.s_registers[type1]) { + b2Contact.s_registers[type1] = [] + } + b2Contact.s_registers[type1][type2] = new b2ContactRegister(); + b2Contact.s_registers[type1][type2].fcn = fcn; + b2Contact.s_registers[type1][type2].primary = true; + if (type1 != type2) { + if (!b2Contact.s_registers[type2]) { + b2Contact.s_registers[type2] = [] + } + b2Contact.s_registers[type2][type1] = new b2ContactRegister(); + b2Contact.s_registers[type2][type1].fcn = fcn; + b2Contact.s_registers[type2][type1].primary = false + } + fcn.garbage = []; + fcn.alloc = 2 +}; +b2Contact.InitializeRegisters = function () { + b2Contact.AddType(b2CircleContact, b2Shape.e_circle, b2Shape.e_circle); + b2Contact.AddType(b2PolygonAndCircleContact, b2Shape.e_polygon, b2Shape.e_circle); + b2Contact.AddType(b2PolygonContact, b2Shape.e_polygon, b2Shape.e_polygon); + b2Contact.AddType(b2EdgeAndCircleContact, b2Shape.e_edge, b2Shape.e_circle); + b2Contact.AddType(b2EdgeAndPolygonContact, b2Shape.e_edge, b2Shape.e_polygon); + b2Contact.AddType(b2ChainAndCircleContact, b2Shape.e_chain, b2Shape.e_circle); + b2Contact.AddType(b2ChainAndPolygonContact, b2Shape.e_chain, b2Shape.e_polygon) +}; +b2Contact.RetrieveGarbage = function (fcn) { + var contact; + if (contact = fcn.garbage.pop()) { + return contact + } + for (var i = 0; i < fcn.alloc - 1; ++i) { + fcn.garbage.push(new fcn()) + } + fcn.alloc += 32; + return new fcn() +}; +b2Contact.Create = function (fixtureA, indexA, fixtureB, indexB) { + if (b2Contact.s_initialized == false) { + b2Contact.InitializeRegisters(); + b2Contact.s_initialized = true + } + var type1 = fixtureA.GetType(); + var type2 = fixtureB.GetType(); + var fcn = b2Contact.s_registers[type1][type2].fcn; + if (fcn) { + var contact = b2Contact.RetrieveGarbage(fcn); + if (b2Contact.s_registers[type1][type2].primary) { + contact.Create(fixtureA, indexA, fixtureB, indexB) + } else { + contact.Create(fixtureB, indexB, fixtureA, indexA) + } + return contact + } + return null +}; +b2Contact.Destroy = function (contact) { + var fixtureA = contact.m_fixtureA; + var fixtureB = contact.m_fixtureB; + if (contact.m_manifold.pointCount > 0 && fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + fixtureA.GetBody().SetAwake(true); + fixtureB.GetBody().SetAwake(true) + } + var typeA = fixtureA.GetType(); + var typeB = fixtureB.GetType(); + b2Contact.s_registers[typeA][typeB].fcn.garbage.push(contact) +}; +b2Contact.s_registers = []; +b2Contact.s_initialized = false; +"use strict"; +var b2_defaultFilter = new b2ContactFilter(); +var b2_defaultListener = new b2ContactListener(); + +function b2ContactManager() { + this.m_broadPhase = new b2BroadPhase(); + this.m_contactList = null; + this.m_contactCount = 0; + this.m_contactFilter = b2_defaultFilter; + this.m_contactListener = b2_defaultListener +} +b2ContactManager.prototype = { + AddPair: function (proxyUserDataA, proxyUserDataB) { + var proxyA = proxyUserDataA; + var proxyB = proxyUserDataB; + var fixtureA = proxyA.fixture; + var fixtureB = proxyB.fixture; + var indexA = proxyA.childIndex; + var indexB = proxyB.childIndex; + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (bodyA == bodyB) { + return + } + var edge = bodyB.GetContactList(); + 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) { + return + } + if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) { + return + } + } + edge = edge.next + } + if (bodyB.ShouldCollide(bodyA) == false) { + return + } + if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { + return + } + var c = b2Contact.Create(fixtureA, indexA, fixtureB, indexB); + if (c == null) { + return + } + fixtureA = c.GetFixtureA(); + fixtureB = c.GetFixtureB(); + indexA = c.GetChildIndexA(); + indexB = c.GetChildIndexB(); + bodyA = fixtureA.GetBody(); + bodyB = fixtureB.GetBody(); + c.m_prev = null; + c.m_next = this.m_contactList; + if (this.m_contactList != null) { + this.m_contactList.m_prev = c + } + this.m_contactList = c; + c.m_nodeA.contact = c; + c.m_nodeA.other = bodyB; + c.m_nodeA.prev = null; + c.m_nodeA.next = bodyA.m_contactList; + if (bodyA.m_contactList != null) { + bodyA.m_contactList.prev = c.m_nodeA + } + bodyA.m_contactList = c.m_nodeA; + c.m_nodeB.contact = c; + c.m_nodeB.other = bodyA; + c.m_nodeB.prev = null; + c.m_nodeB.next = bodyB.m_contactList; + if (bodyB.m_contactList != null) { + bodyB.m_contactList.prev = c.m_nodeB + } + bodyB.m_contactList = c.m_nodeB; + if (fixtureA.IsSensor() == false && fixtureB.IsSensor() == false) { + bodyA.SetAwake(true); + bodyB.SetAwake(true) + }++this.m_contactCount + }, + FindNewContacts: function () { + this.m_broadPhase.UpdatePairs(this) + }, + Destroy: function (c) { + var fixtureA = c.GetFixtureA(); + var fixtureB = c.GetFixtureB(); + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + if (this.m_contactListener && c.IsTouching()) { + this.m_contactListener.EndContact(c) + } + if (c.m_prev) { + c.m_prev.m_next = c.m_next + } + if (c.m_next) { + c.m_next.m_prev = c.m_prev + } + if (c == this.m_contactList) { + this.m_contactList = c.m_next + } + if (c.m_nodeA.prev) { + c.m_nodeA.prev.next = c.m_nodeA.next + } + if (c.m_nodeA.next) { + c.m_nodeA.next.prev = c.m_nodeA.prev + } + if (c.m_nodeA == bodyA.m_contactList) { + bodyA.m_contactList = c.m_nodeA.next + } + if (c.m_nodeB.prev) { + c.m_nodeB.prev.next = c.m_nodeB.next + } + if (c.m_nodeB.next) { + c.m_nodeB.next.prev = c.m_nodeB.prev + } + if (c.m_nodeB == bodyB.m_contactList) { + bodyB.m_contactList = c.m_nodeB.next + } + b2Contact.Destroy(c); + --this.m_contactCount + }, + Collide: function () { + var c = this.m_contactList; + while (c) { var fixtureA = c.GetFixtureA(); var fixtureB = c.GetFixtureB(); + var indexA = c.GetChildIndexA(); + var indexB = c.GetChildIndexB(); var bodyA = fixtureA.GetBody(); var bodyB = fixtureB.GetBody(); - if (this.m_contactListener && c.IsTouching()) { - this.m_contactListener.EndContact(c) - } - if (c.m_prev) { - c.m_prev.m_next = c.m_next - } - if (c.m_next) { - c.m_next.m_prev = c.m_prev - } - if (c == this.m_contactList) { - this.m_contactList = c.m_next - } - if (c.m_nodeA.prev) { - c.m_nodeA.prev.next = c.m_nodeA.next - } - if (c.m_nodeA.next) { - c.m_nodeA.next.prev = c.m_nodeA.prev - } - if (c.m_nodeA == bodyA.m_contactList) { - bodyA.m_contactList = c.m_nodeA.next - } - if (c.m_nodeB.prev) { - c.m_nodeB.prev.next = c.m_nodeB.next - } - if (c.m_nodeB.next) { - c.m_nodeB.next.prev = c.m_nodeB.prev - } - if (c.m_nodeB == bodyB.m_contactList) { - bodyB.m_contactList = c.m_nodeB.next - } - b2Contact.Destroy(c); - --this.m_contactCount - }, - Collide: function () { - var c = this.m_contactList; - while (c) { - var fixtureA = c.GetFixtureA(); - var fixtureB = c.GetFixtureB(); - var indexA = c.GetChildIndexA(); - var indexB = c.GetChildIndexB(); - var bodyA = fixtureA.GetBody(); - var bodyB = fixtureB.GetBody(); - if (c.m_flags & b2Contact.e_filterFlag) { - if (bodyB.ShouldCollide(bodyA) == false) { - var cNuke = c; - c = cNuke.GetNext(); - this.Destroy(cNuke); - continue - } - if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { - var cNuke = c; - c = cNuke.GetNext(); - this.Destroy(cNuke); - continue - } - c.m_flags &= ~b2Contact.e_filterFlag - } - var activeA = bodyA.IsAwake() && bodyA.m_type != b2Body.b2_staticBody; - var activeB = bodyB.IsAwake() && bodyB.m_type != b2Body.b2_staticBody; - if (activeA == false && activeB == false) { - c = c.GetNext(); - continue - } - var proxyIdA = fixtureA.m_proxies[indexA].proxyId; - var proxyIdB = fixtureB.m_proxies[indexB].proxyId; - var overlap = this.m_broadPhase.TestOverlap(proxyIdA, proxyIdB); - if (overlap == false) { + if (c.m_flags & b2Contact.e_filterFlag) { + if (bodyB.ShouldCollide(bodyA) == false) { var cNuke = c; c = cNuke.GetNext(); this.Destroy(cNuke); continue } - c.Update(this.m_contactListener); - c = c.GetNext() + if (this.m_contactFilter && this.m_contactFilter.ShouldCollide(fixtureA, fixtureB) == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + c.m_flags &= ~b2Contact.e_filterFlag + } + var activeA = bodyA.IsAwake() && bodyA.m_type != b2Body.b2_staticBody; + var activeB = bodyB.IsAwake() && bodyB.m_type != b2Body.b2_staticBody; + if (activeA == false && activeB == false) { + c = c.GetNext(); + continue + } + var proxyIdA = fixtureA.m_proxies[indexA].proxyId; + var proxyIdB = fixtureB.m_proxies[indexB].proxyId; + var overlap = this.m_broadPhase.TestOverlap(proxyIdA, proxyIdB); + if (overlap == false) { + var cNuke = c; + c = cNuke.GetNext(); + this.Destroy(cNuke); + continue + } + c.Update(this.m_contactListener); + c = c.GetNext() + } + } +}; + +function b2VelocityConstraintPoint() { + this.rA = new b2Vec2(); + this.rB = new b2Vec2(); + this.normalImpulse = 0; + this.tangentImpulse = 0; + this.normalMass = 0; + this.tangentMass = 0; + this.velocityBias = 0 +} + +function b2ContactPositionConstraint() { + this.localPoints = new Array(b2_maxManifoldPoints); + this.localNormal = new b2Vec2(); + this.localPoint = new b2Vec2(); + this.indexA = 0; + this.indexB = 0; + this.invMassA = 0, this.invMassB = 0; + this.localCenterA = new b2Vec2(), this.localCenterB = new b2Vec2(); + this.invIA = 0, this.invIB = 0; + this.type = 0; + this.radiusA = 0, this.radiusB = 0; + this.pointCount = 0 +} + +function b2ContactVelocityConstraint() { + this.points = new Array(b2_maxManifoldPoints); + for (var i = 0; i < this.points.length; ++i) { + this.points[i] = new b2VelocityConstraintPoint() + } + this.normal = new b2Vec2(); + this.normalMass = new b2Mat22(); + this.K = new b2Mat22(); + this.indexA = 0; + this.indexB = 0; + this.invMassA = 0, this.invMassB = 0; + this.invIA = 0, this.invIB = 0; + this.friction = 0; + this.restitution = 0; + this.tangentSpeed = 0; + this.pointCount = 0; + this.contactIndex = 0 +} + +function b2PositionSolverManifold() { + this.normal = new b2Vec2(); + this.point = new b2Vec2(); + this.separation = 0 +} +b2PositionSolverManifold.prototype = { + Initialize: function (pc, xfA, xfB, index) { + switch (pc.type) { + case b2Manifold.e_circles: + var pointAx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; + var pointAy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; + var pointBx = (xfB.q.c * pc.localPoints[0].x - xfB.q.s * pc.localPoints[0].y) + xfB.p.x; + var pointBy = (xfB.q.s * pc.localPoints[0].x + xfB.q.c * pc.localPoints[0].y) + xfB.p.y; + this.point.x = 0.5 * (pointAx + pointBx); + this.point.y = 0.5 * (pointAy + pointBy); + this.normal.x = pointBx - pointAx; + this.normal.y = pointBy - pointAy; + var tempnx = this.normal.x; + var tempny = this.normal.y; + this.normal.Normalize(); + this.separation = (tempnx * this.normal.x + tempny * this.normal.y) - pc.radiusA - pc.radiusB; + break; + case b2Manifold.e_faceA: + this.normal.x = xfA.q.c * pc.localNormal.x - xfA.q.s * pc.localNormal.y; + this.normal.y = xfA.q.s * pc.localNormal.x + xfA.q.c * pc.localNormal.y; + var planePointx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; + var planePointy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; + var clipPointx = (xfB.q.c * pc.localPoints[index].x - xfB.q.s * pc.localPoints[index].y) + xfB.p.x; + var clipPointy = (xfB.q.s * pc.localPoints[index].x + xfB.q.c * pc.localPoints[index].y) + xfB.p.y; + this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; + this.point.x = clipPointx; + this.point.y = clipPointy; + break; + case b2Manifold.e_faceB: + this.normal.x = xfB.q.c * pc.localNormal.x - xfB.q.s * pc.localNormal.y; + this.normal.y = xfB.q.s * pc.localNormal.x + xfB.q.c * pc.localNormal.y; + var planePointx = (xfB.q.c * pc.localPoint.x - xfB.q.s * pc.localPoint.y) + xfB.p.x; + var planePointy = (xfB.q.s * pc.localPoint.x + xfB.q.c * pc.localPoint.y) + xfB.p.y; + var clipPointx = (xfA.q.c * pc.localPoints[index].x - xfA.q.s * pc.localPoints[index].y) + xfA.p.x; + var clipPointy = (xfA.q.s * pc.localPoints[index].x + xfA.q.c * pc.localPoints[index].y) + xfA.p.y; + this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; + this.point.x = clipPointx; + this.point.y = clipPointy; + this.normal.x = -this.normal.x; + this.normal.y = -this.normal.y; + break + } + } +}; + +function b2ContactSolverDef() { + this.step = new b2TimeStep(); + this.contacts = null; + this.count = 0; + this.positions = null; + this.velocities = null +} + +function b2ContactSolver() { + this.m_positionConstraints = []; + this.m_velocityConstraints = [] +} +b2ContactSolver.cs_xfA = new b2Transform(); +b2ContactSolver.cs_xfB = new b2Transform(); +b2ContactSolver.temp_solver_manifold = new b2PositionSolverManifold(); +b2ContactSolver.prototype = { + Init: function (def) { + this.m_step = def.step; + this.m_count = def.count; + this.m_positionConstraints.length = this.m_count; + this.m_velocityConstraints.length = this.m_count; + this.m_positions = def.positions; + this.m_velocities = def.velocities; + this.m_contacts = def.contacts; + for (var i = 0; i < this.m_count; ++i) { + var contact = this.m_contacts[i]; + var fixtureA = contact.m_fixtureA; + var fixtureB = contact.m_fixtureB; + var shapeA = fixtureA.GetShape(); + var shapeB = fixtureB.GetShape(); + var radiusA = shapeA.m_radius; + var radiusB = shapeB.m_radius; + var bodyA = fixtureA.GetBody(); + var bodyB = fixtureB.GetBody(); + var manifold = contact.GetManifold(); + var pointCount = manifold.pointCount; + var vc = this.m_velocityConstraints[i] || new b2ContactVelocityConstraint(); + vc.friction = contact.m_friction; + vc.restitution = contact.m_restitution; + vc.tangentSpeed = contact.m_tangentSpeed; + vc.indexA = bodyA.m_islandIndex; + vc.indexB = bodyB.m_islandIndex; + vc.invMassA = bodyA.m_invMass; + vc.invMassB = bodyB.m_invMass; + vc.invIA = bodyA.m_invI; + vc.invIB = bodyB.m_invI; + vc.contactIndex = i; + vc.pointCount = pointCount; + vc.K.SetZero(); + vc.normalMass.SetZero(); + this.m_velocityConstraints[i] = vc; + var pc = this.m_positionConstraints[i] || new b2ContactPositionConstraint(); + pc.indexA = bodyA.m_islandIndex; + pc.indexB = bodyB.m_islandIndex; + pc.invMassA = bodyA.m_invMass; + pc.invMassB = bodyB.m_invMass; + pc.localCenterA.x = bodyA.m_sweep.localCenter.x; + pc.localCenterA.y = bodyA.m_sweep.localCenter.y; + pc.localCenterB.x = bodyB.m_sweep.localCenter.x; + pc.localCenterB.y = bodyB.m_sweep.localCenter.y; + pc.invIA = bodyA.m_invI; + pc.invIB = bodyB.m_invI; + pc.localNormal.x = manifold.localNormal.x; + pc.localNormal.y = manifold.localNormal.y; + pc.localPoint.x = manifold.localPoint.x; + pc.localPoint.y = manifold.localPoint.y; + pc.pointCount = pointCount; + pc.radiusA = radiusA; + pc.radiusB = radiusB; + pc.type = manifold.type; + this.m_positionConstraints[i] = pc; + for (var j = 0; j < pointCount; ++j) { + var cp = manifold.points[j]; + var vcp = vc.points[j]; + if (this.m_step.warmStarting) { + vcp.normalImpulse = this.m_step.dtRatio * cp.normalImpulse; + vcp.tangentImpulse = this.m_step.dtRatio * cp.tangentImpulse + } else { + vcp.normalImpulse = 0; + vcp.tangentImpulse = 0 + } + vcp.rA.SetZero(); + vcp.rB.SetZero(); + vcp.normalMass = 0; + vcp.tangentMass = 0; + vcp.velocityBias = 0; + pc.localPoints[j] = cp.localPoint } } - }; - - function b2VelocityConstraintPoint() { - this.rA = new b2Vec2(); - this.rB = new b2Vec2(); - this.normalImpulse = 0; - this.tangentImpulse = 0; - this.normalMass = 0; - this.tangentMass = 0; - this.velocityBias = 0 - } - - function b2ContactPositionConstraint() { - this.localPoints = new Array(b2_maxManifoldPoints); - this.localNormal = new b2Vec2(); - this.localPoint = new b2Vec2(); - this.indexA = 0; - this.indexB = 0; - this.invMassA = 0, this.invMassB = 0; - this.localCenterA = new b2Vec2(), this.localCenterB = new b2Vec2(); - this.invIA = 0, this.invIB = 0; - this.type = 0; - this.radiusA = 0, this.radiusB = 0; - this.pointCount = 0 - } - - function b2ContactVelocityConstraint() { - this.points = new Array(b2_maxManifoldPoints); - for (var i = 0; i < this.points.length; ++i) { - this.points[i] = new b2VelocityConstraintPoint() - } - this.normal = new b2Vec2(); - this.normalMass = new b2Mat22(); - this.K = new b2Mat22(); - this.indexA = 0; - this.indexB = 0; - this.invMassA = 0, this.invMassB = 0; - this.invIA = 0, this.invIB = 0; - this.friction = 0; - this.restitution = 0; - this.tangentSpeed = 0; - this.pointCount = 0; - this.contactIndex = 0 - } - - function b2PositionSolverManifold() { - this.normal = new b2Vec2(); - this.point = new b2Vec2(); - this.separation = 0 - } - b2PositionSolverManifold.prototype = { - Initialize: function (pc, xfA, xfB, index) { - switch (pc.type) { - case b2Manifold.e_circles: - var pointAx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; - var pointAy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; - var pointBx = (xfB.q.c * pc.localPoints[0].x - xfB.q.s * pc.localPoints[0].y) + xfB.p.x; - var pointBy = (xfB.q.s * pc.localPoints[0].x + xfB.q.c * pc.localPoints[0].y) + xfB.p.y; - this.point.x = 0.5 * (pointAx + pointBx); - this.point.y = 0.5 * (pointAy + pointBy); - this.normal.x = pointBx - pointAx; - this.normal.y = pointBy - pointAy; - var tempnx = this.normal.x; - var tempny = this.normal.y; - this.normal.Normalize(); - this.separation = (tempnx * this.normal.x + tempny * this.normal.y) - pc.radiusA - pc.radiusB; - break; - case b2Manifold.e_faceA: - this.normal.x = xfA.q.c * pc.localNormal.x - xfA.q.s * pc.localNormal.y; - this.normal.y = xfA.q.s * pc.localNormal.x + xfA.q.c * pc.localNormal.y; - var planePointx = (xfA.q.c * pc.localPoint.x - xfA.q.s * pc.localPoint.y) + xfA.p.x; - var planePointy = (xfA.q.s * pc.localPoint.x + xfA.q.c * pc.localPoint.y) + xfA.p.y; - var clipPointx = (xfB.q.c * pc.localPoints[index].x - xfB.q.s * pc.localPoints[index].y) + xfB.p.x; - var clipPointy = (xfB.q.s * pc.localPoints[index].x + xfB.q.c * pc.localPoints[index].y) + xfB.p.y; - this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; - this.point.x = clipPointx; - this.point.y = clipPointy; - break; - case b2Manifold.e_faceB: - this.normal.x = xfB.q.c * pc.localNormal.x - xfB.q.s * pc.localNormal.y; - this.normal.y = xfB.q.s * pc.localNormal.x + xfB.q.c * pc.localNormal.y; - var planePointx = (xfB.q.c * pc.localPoint.x - xfB.q.s * pc.localPoint.y) + xfB.p.x; - var planePointy = (xfB.q.s * pc.localPoint.x + xfB.q.c * pc.localPoint.y) + xfB.p.y; - var clipPointx = (xfA.q.c * pc.localPoints[index].x - xfA.q.s * pc.localPoints[index].y) + xfA.p.x; - var clipPointy = (xfA.q.s * pc.localPoints[index].x + xfA.q.c * pc.localPoints[index].y) + xfA.p.y; - this.separation = ((clipPointx - planePointx) * this.normal.x + (clipPointy - planePointy) * this.normal.y) - pc.radiusA - pc.radiusB; - this.point.x = clipPointx; - this.point.y = clipPointy; - this.normal.x = -this.normal.x; - this.normal.y = -this.normal.y; - break - } - } - }; - - function b2ContactSolverDef() { - this.step = new b2TimeStep(); - this.contacts = null; - this.count = 0; - this.positions = null; - this.velocities = null - } - - function b2ContactSolver() { - this.m_positionConstraints = []; - this.m_velocityConstraints = [] - } - b2ContactSolver.cs_xfA = new b2Transform(); - b2ContactSolver.cs_xfB = new b2Transform(); - b2ContactSolver.temp_solver_manifold = new b2PositionSolverManifold(); - b2ContactSolver.prototype = { - Init: function (def) { - this.m_step = def.step; - this.m_count = def.count; - this.m_positionConstraints.length = this.m_count; - this.m_velocityConstraints.length = this.m_count; - this.m_positions = def.positions; - this.m_velocities = def.velocities; - this.m_contacts = def.contacts; - for (var i = 0; i < this.m_count; ++i) { - var contact = this.m_contacts[i]; - var fixtureA = contact.m_fixtureA; - var fixtureB = contact.m_fixtureB; - var shapeA = fixtureA.GetShape(); - var shapeB = fixtureB.GetShape(); - var radiusA = shapeA.m_radius; - var radiusB = shapeB.m_radius; - var bodyA = fixtureA.GetBody(); - var bodyB = fixtureB.GetBody(); - var manifold = contact.GetManifold(); - var pointCount = manifold.pointCount; - var vc = this.m_velocityConstraints[i] || new b2ContactVelocityConstraint(); - vc.friction = contact.m_friction; - vc.restitution = contact.m_restitution; - vc.tangentSpeed = contact.m_tangentSpeed; - vc.indexA = bodyA.m_islandIndex; - vc.indexB = bodyB.m_islandIndex; - vc.invMassA = bodyA.m_invMass; - vc.invMassB = bodyB.m_invMass; - vc.invIA = bodyA.m_invI; - vc.invIB = bodyB.m_invI; - vc.contactIndex = i; - vc.pointCount = pointCount; - vc.K.SetZero(); - vc.normalMass.SetZero(); - this.m_velocityConstraints[i] = vc; - var pc = this.m_positionConstraints[i] || new b2ContactPositionConstraint(); - pc.indexA = bodyA.m_islandIndex; - pc.indexB = bodyB.m_islandIndex; - pc.invMassA = bodyA.m_invMass; - pc.invMassB = bodyB.m_invMass; - pc.localCenterA.x = bodyA.m_sweep.localCenter.x; - pc.localCenterA.y = bodyA.m_sweep.localCenter.y; - pc.localCenterB.x = bodyB.m_sweep.localCenter.x; - pc.localCenterB.y = bodyB.m_sweep.localCenter.y; - pc.invIA = bodyA.m_invI; - pc.invIB = bodyB.m_invI; - pc.localNormal.x = manifold.localNormal.x; - pc.localNormal.y = manifold.localNormal.y; - pc.localPoint.x = manifold.localPoint.x; - pc.localPoint.y = manifold.localPoint.y; - pc.pointCount = pointCount; - pc.radiusA = radiusA; - pc.radiusB = radiusB; - pc.type = manifold.type; - this.m_positionConstraints[i] = pc; - for (var j = 0; j < pointCount; ++j) { - var cp = manifold.points[j]; - var vcp = vc.points[j]; - if (this.m_step.warmStarting) { - vcp.normalImpulse = this.m_step.dtRatio * cp.normalImpulse; - vcp.tangentImpulse = this.m_step.dtRatio * cp.tangentImpulse - } else { - vcp.normalImpulse = 0; - vcp.tangentImpulse = 0 - } - vcp.rA.SetZero(); - vcp.rB.SetZero(); - vcp.normalMass = 0; - vcp.tangentMass = 0; - vcp.velocityBias = 0; - pc.localPoints[j] = cp.localPoint + }, + InitializeVelocityConstraints: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var pc = this.m_positionConstraints[i]; + var radiusA = pc.radiusA; + var radiusB = pc.radiusB; + var manifold = this.m_contacts[vc.contactIndex].GetManifold(); + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var mB = vc.invMassB; + var iA = vc.invIA; + var iB = vc.invIB; + var localCenterA = pc.localCenterA; + var localCenterB = pc.localCenterB; + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); + b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); + b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); + b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); + var worldManifold = new b2WorldManifold(); + worldManifold.Initialize(manifold, b2ContactSolver.cs_xfA, radiusA, b2ContactSolver.cs_xfB, radiusB); + vc.normal.x = worldManifold.normal.x; + vc.normal.y = worldManifold.normal.y; + var pointCount = vc.pointCount; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + vcp.rA.x = worldManifold.points[j].x - cA.x; + vcp.rA.y = worldManifold.points[j].y - cA.y; + vcp.rB.x = worldManifold.points[j].x - cB.x; + vcp.rB.y = worldManifold.points[j].y - cB.y; + var rnA = vcp.rA.x * vc.normal.y - vcp.rA.y * vc.normal.x; + var rnB = vcp.rB.x * vc.normal.y - vcp.rB.y * vc.normal.x; + var kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + vcp.normalMass = kNormal > 0 ? 1 / kNormal : 0; + var tangentx = 1 * vc.normal.y; + var tangenty = -1 * vc.normal.x; + var rtA = vcp.rA.x * tangenty - vcp.rA.y * tangentx; + var rtB = vcp.rB.x * tangenty - vcp.rB.y * tangentx; + var kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; + vcp.tangentMass = kTangent > 0 ? 1 / kTangent : 0; + vcp.velocityBias = 0; + var vRel = vc.normal.x * (((vB.x + (-wB * vcp.rB.y)) - vA.x) - (-wA * vcp.rA.y)) + vc.normal.y * (((vB.y + (wB * vcp.rB.x)) - vA.y) - (wA * vcp.rA.x)); + if (vRel < -b2_velocityThreshold) { + vcp.velocityBias = -vc.restitution * vRel } } - }, - InitializeVelocityConstraints: function () { - for (var i = 0; i < this.m_count; ++i) { - var vc = this.m_velocityConstraints[i]; - var pc = this.m_positionConstraints[i]; - var radiusA = pc.radiusA; - var radiusB = pc.radiusB; - var manifold = this.m_contacts[vc.contactIndex].GetManifold(); - var indexA = vc.indexA; - var indexB = vc.indexB; - var mA = vc.invMassA; - var mB = vc.invMassB; - var iA = vc.invIA; - var iB = vc.invIB; - var localCenterA = pc.localCenterA; - var localCenterB = pc.localCenterB; - var cA = this.m_positions[indexA].c; - var aA = this.m_positions[indexA].a; - var vA = this.m_velocities[indexA].v; - var wA = this.m_velocities[indexA].w; - var cB = this.m_positions[indexB].c; - var aB = this.m_positions[indexB].a; - var vB = this.m_velocities[indexB].v; - var wB = this.m_velocities[indexB].w; + if (vc.pointCount == 2) { + var vcp1 = vc.points[0]; + var vcp2 = vc.points[1]; + var rn1A = vcp1.rA.x * vc.normal.y - vcp1.rA.y * vc.normal.x; + var rn1B = vcp1.rB.x * vc.normal.y - vcp1.rB.y * vc.normal.x; + var rn2A = vcp2.rA.x * vc.normal.y - vcp2.rA.y * vc.normal.x; + var rn2B = vcp2.rB.x * vc.normal.y - vcp2.rB.y * vc.normal.x; + 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; + var k_maxConditionNumber = 1000; + if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { + vc.K.ex.x = k11; + vc.K.ex.y = k12; + vc.K.ey.x = k12; + vc.K.ey.y = k22; + vc.normalMass.Assign(vc.K.GetInverse()) + } else { + vc.pointCount = 1 + } + } + } + }, + WarmStart: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var iA = vc.invIA; + var mB = vc.invMassB; + var iB = vc.invIB; + var pointCount = vc.pointCount; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + var normal = vc.normal; + var tangentx = 1 * normal.y; + var tangenty = -1 * normal.x; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + var Px = (vcp.normalImpulse * normal.x) + (vcp.tangentImpulse * tangentx); + var Py = (vcp.normalImpulse * normal.y) + (vcp.tangentImpulse * tangenty); + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vA.x -= mA * Px; + vA.y -= mA * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px); + vB.x += mB * Px; + vB.y += mB * Py + } + this.m_velocities[indexA].w = wA; + this.m_velocities[indexB].w = wB + } + }, + SolveVelocityConstraints: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var indexA = vc.indexA; + var indexB = vc.indexB; + var mA = vc.invMassA; + var iA = vc.invIA; + var mB = vc.invMassB; + var iB = vc.invIB; + var pointCount = vc.pointCount; + var vA = this.m_velocities[indexA].v; + var wA = this.m_velocities[indexA].w; + var vB = this.m_velocities[indexB].v; + var wB = this.m_velocities[indexB].w; + var normal = vc.normal; + var tangentx = 1 * normal.y; + var tangenty = -1 * normal.x; + var friction = vc.friction; + for (var j = 0; j < pointCount; ++j) { + var vcp = vc.points[j]; + var dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); + var dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); + var vt = (dvx * tangentx + dvy * tangenty) - vc.tangentSpeed; + var lambda = vcp.tangentMass * (-vt); + var maxFriction = friction * vcp.normalImpulse; + var newImpulse = b2Clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction); + lambda = newImpulse - vcp.tangentImpulse; + vcp.tangentImpulse = newImpulse; + var Px = lambda * tangentx; + var Py = lambda * tangenty; + vA.x -= mA * Px; + vA.y -= mA * Py; + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vB.x += mB * Px; + vB.y += mB * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) + } + if (vc.pointCount == 1) { + vcp = vc.points[0]; + dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); + dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); + var vn = dvx * normal.x + dvy * normal.y; + var lambda = -vcp.normalMass * (vn - vcp.velocityBias); + var newImpulse = b2Max(vcp.normalImpulse + lambda, 0); + lambda = newImpulse - vcp.normalImpulse; + vcp.normalImpulse = newImpulse; + Px = lambda * normal.x; + Py = lambda * normal.y; + vA.x -= mA * Px; + vA.y -= mA * Py; + wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); + vB.x += mB * Px; + vB.y += mB * Py; + wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) + } else { + var cp1 = vc.points[0]; + var cp2 = vc.points[1]; + var ax = cp1.normalImpulse; + var ay = cp2.normalImpulse; + var dv1x = vB.x + (-wB * cp1.rB.y) - vA.x - (-wA * cp1.rA.y); + var dv1y = vB.y + (wB * cp1.rB.x) - vA.y - (wA * cp1.rA.x); + var dv2x = vB.x + (-wB * cp2.rB.y) - vA.x - (-wA * cp2.rA.y); + var dv2y = vB.y + (wB * cp2.rB.x) - vA.y - (wA * cp2.rA.x); + var vn1 = dv1x * normal.x + dv1y * normal.y; + var vn2 = dv2x * normal.x + dv2y * normal.y; + var bx = vn1 - cp1.velocityBias; + var by = vn2 - cp2.velocityBias; + bx -= vc.K.ex.x * ax + vc.K.ey.x * ay; + by -= vc.K.ex.y * ax + vc.K.ey.y * ay; + for (;;) { + var xx = -(vc.normalMass.ex.x * bx + vc.normalMass.ey.x * by); + var xy = -(vc.normalMass.ex.y * bx + vc.normalMass.ey.y * by); + if (xx >= 0 && xy >= 0) { + var dx = xx - ax; + var dy = xy - ay; + var P1x = dx * normal.x; + var P1y = dx * normal.y; + var P2x = dy * normal.x; + var P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = -cp1.normalMass * bx; + xy = 0; + vn1 = 0; + vn2 = vc.K.ex.y * xx + by; + if (xx >= 0 && vn2 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = 0; + xy = -cp2.normalMass * by; + vn1 = vc.K.ey.x * xy + bx; + vn2 = 0; + if (xy >= 0 && vn1 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + xx = 0; + xy = 0; + vn1 = bx; + vn2 = by; + if (vn1 >= 0 && vn2 >= 0) { + dx = xx - ax; + dy = xy - ay; + P1x = dx * normal.x; + P1y = dx * normal.y; + P2x = dy * normal.x; + P2y = dy * normal.y; + vA.x -= mA * (P1x + P2x); + vA.y -= mA * (P1y + P2y); + wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); + vB.x += mB * (P1x + P2x); + vB.y += mB * (P1y + P2y); + wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); + cp1.normalImpulse = xx; + cp2.normalImpulse = xy; + break + } + break + } + } + this.m_velocities[indexA].w = wA; + this.m_velocities[indexB].w = wB + } + }, + StoreImpulses: function () { + for (var i = 0; i < this.m_count; ++i) { + var vc = this.m_velocityConstraints[i]; + var manifold = this.m_contacts[vc.contactIndex].GetManifold(); + for (var j = 0; j < vc.pointCount; ++j) { + manifold.points[j].normalImpulse = vc.points[j].normalImpulse; + manifold.points[j].tangentImpulse = vc.points[j].tangentImpulse + } + } + }, + SolvePositionConstraints: function () { + var minSeparation = 0; + for (var i = 0; i < this.m_count; ++i) { + var pc = this.m_positionConstraints[i]; + var indexA = pc.indexA; + var indexB = pc.indexB; + var localCenterA = pc.localCenterA; + var mA = pc.invMassA; + var iA = pc.invIA; + var localCenterB = pc.localCenterB; + var mB = pc.invMassB; + var iB = pc.invIB; + var pointCount = pc.pointCount; + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + for (var j = 0; j < pointCount; ++j) { b2ContactSolver.cs_xfA.q.Set(aA); b2ContactSolver.cs_xfB.q.Set(aB); b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); - var worldManifold = new b2WorldManifold(); - worldManifold.Initialize(manifold, b2ContactSolver.cs_xfA, radiusA, b2ContactSolver.cs_xfB, radiusB); - vc.normal.x = worldManifold.normal.x; - vc.normal.y = worldManifold.normal.y; - var pointCount = vc.pointCount; - for (var j = 0; j < pointCount; ++j) { - var vcp = vc.points[j]; - vcp.rA.x = worldManifold.points[j].x - cA.x; - vcp.rA.y = worldManifold.points[j].y - cA.y; - vcp.rB.x = worldManifold.points[j].x - cB.x; - vcp.rB.y = worldManifold.points[j].y - cB.y; - var rnA = vcp.rA.x * vc.normal.y - vcp.rA.y * vc.normal.x; - var rnB = vcp.rB.x * vc.normal.y - vcp.rB.y * vc.normal.x; - var kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; - vcp.normalMass = kNormal > 0 ? 1 / kNormal : 0; - var tangentx = 1 * vc.normal.y; - var tangenty = -1 * vc.normal.x; - var rtA = vcp.rA.x * tangenty - vcp.rA.y * tangentx; - var rtB = vcp.rB.x * tangenty - vcp.rB.y * tangentx; - var kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; - vcp.tangentMass = kTangent > 0 ? 1 / kTangent : 0; - vcp.velocityBias = 0; - var vRel = vc.normal.x * (((vB.x + (-wB * vcp.rB.y)) - vA.x) - (-wA * vcp.rA.y)) + vc.normal.y * (((vB.y + (wB * vcp.rB.x)) - vA.y) - (wA * vcp.rA.x)); - if (vRel < -b2_velocityThreshold) { - vcp.velocityBias = -vc.restitution * vRel - } - } - if (vc.pointCount == 2) { - var vcp1 = vc.points[0]; - var vcp2 = vc.points[1]; - var rn1A = vcp1.rA.x * vc.normal.y - vcp1.rA.y * vc.normal.x; - var rn1B = vcp1.rB.x * vc.normal.y - vcp1.rB.y * vc.normal.x; - var rn2A = vcp2.rA.x * vc.normal.y - vcp2.rA.y * vc.normal.x; - var rn2B = vcp2.rB.x * vc.normal.y - vcp2.rB.y * vc.normal.x; - 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; - var k_maxConditionNumber = 1000; - if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) { - vc.K.ex.x = k11; - vc.K.ex.y = k12; - vc.K.ey.x = k12; - vc.K.ey.y = k22; - vc.normalMass.Assign(vc.K.GetInverse()) - } else { - vc.pointCount = 1 - } - } + b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); + var normal = b2ContactSolver.temp_solver_manifold.normal; + var point = b2ContactSolver.temp_solver_manifold.point; + var separation = b2ContactSolver.temp_solver_manifold.separation; + var rAx = point.x - cA.x; + var rAy = point.y - cA.y; + var rBx = point.x - cB.x; + var rBy = point.y - cB.y; + minSeparation = b2Min(minSeparation, separation); + var C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); + var rnA = rAx * normal.y - rAy * normal.x; + var rnB = rBx * normal.y - rBy * normal.x; + var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + var impulse = K > 0 ? -C / K : 0; + var Px = impulse * normal.x; + var Py = impulse * normal.y; + cA.x -= mA * Px; + cA.y -= mA * Py; + aA -= iA * (rAx * Py - rAy * Px); + cB.x += mB * Px; + cB.y += mB * Py; + aB += iB * (rBx * Py - rBy * Px) } - }, - WarmStart: function () { - for (var i = 0; i < this.m_count; ++i) { - var vc = this.m_velocityConstraints[i]; - var indexA = vc.indexA; - var indexB = vc.indexB; - var mA = vc.invMassA; - var iA = vc.invIA; - var mB = vc.invMassB; - var iB = vc.invIB; - var pointCount = vc.pointCount; - var vA = this.m_velocities[indexA].v; - var wA = this.m_velocities[indexA].w; - var vB = this.m_velocities[indexB].v; - var wB = this.m_velocities[indexB].w; - var normal = vc.normal; - var tangentx = 1 * normal.y; - var tangenty = -1 * normal.x; - for (var j = 0; j < pointCount; ++j) { - var vcp = vc.points[j]; - var Px = (vcp.normalImpulse * normal.x) + (vcp.tangentImpulse * tangentx); - var Py = (vcp.normalImpulse * normal.y) + (vcp.tangentImpulse * tangenty); - wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); - vA.x -= mA * Px; - vA.y -= mA * Py; - wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px); - vB.x += mB * Px; - vB.y += mB * Py - } - this.m_velocities[indexA].w = wA; - this.m_velocities[indexB].w = wB - } - }, - SolveVelocityConstraints: function () { - for (var i = 0; i < this.m_count; ++i) { - var vc = this.m_velocityConstraints[i]; - var indexA = vc.indexA; - var indexB = vc.indexB; - var mA = vc.invMassA; - var iA = vc.invIA; - var mB = vc.invMassB; - var iB = vc.invIB; - var pointCount = vc.pointCount; - var vA = this.m_velocities[indexA].v; - var wA = this.m_velocities[indexA].w; - var vB = this.m_velocities[indexB].v; - var wB = this.m_velocities[indexB].w; - var normal = vc.normal; - var tangentx = 1 * normal.y; - var tangenty = -1 * normal.x; - var friction = vc.friction; - for (var j = 0; j < pointCount; ++j) { - var vcp = vc.points[j]; - var dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); - var dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); - var vt = (dvx * tangentx + dvy * tangenty) - vc.tangentSpeed; - var lambda = vcp.tangentMass * (-vt); - var maxFriction = friction * vcp.normalImpulse; - var newImpulse = b2Clamp(vcp.tangentImpulse + lambda, -maxFriction, maxFriction); - lambda = newImpulse - vcp.tangentImpulse; - vcp.tangentImpulse = newImpulse; - var Px = lambda * tangentx; - var Py = lambda * tangenty; - vA.x -= mA * Px; - vA.y -= mA * Py; - wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); - vB.x += mB * Px; - vB.y += mB * Py; - wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) - } - if (vc.pointCount == 1) { - vcp = vc.points[0]; - dvx = vB.x + (-wB * vcp.rB.y) - vA.x - (-wA * vcp.rA.y); - dvy = vB.y + (wB * vcp.rB.x) - vA.y - (wA * vcp.rA.x); - var vn = dvx * normal.x + dvy * normal.y; - var lambda = -vcp.normalMass * (vn - vcp.velocityBias); - var newImpulse = b2Max(vcp.normalImpulse + lambda, 0); - lambda = newImpulse - vcp.normalImpulse; - vcp.normalImpulse = newImpulse; - Px = lambda * normal.x; - Py = lambda * normal.y; - vA.x -= mA * Px; - vA.y -= mA * Py; - wA -= iA * (vcp.rA.x * Py - vcp.rA.y * Px); - vB.x += mB * Px; - vB.y += mB * Py; - wB += iB * (vcp.rB.x * Py - vcp.rB.y * Px) - } else { - var cp1 = vc.points[0]; - var cp2 = vc.points[1]; - var ax = cp1.normalImpulse; - var ay = cp2.normalImpulse; - var dv1x = vB.x + (-wB * cp1.rB.y) - vA.x - (-wA * cp1.rA.y); - var dv1y = vB.y + (wB * cp1.rB.x) - vA.y - (wA * cp1.rA.x); - var dv2x = vB.x + (-wB * cp2.rB.y) - vA.x - (-wA * cp2.rA.y); - var dv2y = vB.y + (wB * cp2.rB.x) - vA.y - (wA * cp2.rA.x); - var vn1 = dv1x * normal.x + dv1y * normal.y; - var vn2 = dv2x * normal.x + dv2y * normal.y; - var bx = vn1 - cp1.velocityBias; - var by = vn2 - cp2.velocityBias; - bx -= vc.K.ex.x * ax + vc.K.ey.x * ay; - by -= vc.K.ex.y * ax + vc.K.ey.y * ay; - for (;;) { - var xx = -(vc.normalMass.ex.x * bx + vc.normalMass.ey.x * by); - var xy = -(vc.normalMass.ex.y * bx + vc.normalMass.ey.y * by); - if (xx >= 0 && xy >= 0) { - var dx = xx - ax; - var dy = xy - ay; - var P1x = dx * normal.x; - var P1y = dx * normal.y; - var P2x = dy * normal.x; - var P2y = dy * normal.y; - vA.x -= mA * (P1x + P2x); - vA.y -= mA * (P1y + P2y); - wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); - vB.x += mB * (P1x + P2x); - vB.y += mB * (P1y + P2y); - wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); - cp1.normalImpulse = xx; - cp2.normalImpulse = xy; - break - } - xx = -cp1.normalMass * bx; - xy = 0; - vn1 = 0; - vn2 = vc.K.ex.y * xx + by; - if (xx >= 0 && vn2 >= 0) { - dx = xx - ax; - dy = xy - ay; - P1x = dx * normal.x; - P1y = dx * normal.y; - P2x = dy * normal.x; - P2y = dy * normal.y; - vA.x -= mA * (P1x + P2x); - vA.y -= mA * (P1y + P2y); - wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); - vB.x += mB * (P1x + P2x); - vB.y += mB * (P1y + P2y); - wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); - cp1.normalImpulse = xx; - cp2.normalImpulse = xy; - break - } - xx = 0; - xy = -cp2.normalMass * by; - vn1 = vc.K.ey.x * xy + bx; - vn2 = 0; - if (xy >= 0 && vn1 >= 0) { - dx = xx - ax; - dy = xy - ay; - P1x = dx * normal.x; - P1y = dx * normal.y; - P2x = dy * normal.x; - P2y = dy * normal.y; - vA.x -= mA * (P1x + P2x); - vA.y -= mA * (P1y + P2y); - wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); - vB.x += mB * (P1x + P2x); - vB.y += mB * (P1y + P2y); - wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); - cp1.normalImpulse = xx; - cp2.normalImpulse = xy; - break - } - xx = 0; - xy = 0; - vn1 = bx; - vn2 = by; - if (vn1 >= 0 && vn2 >= 0) { - dx = xx - ax; - dy = xy - ay; - P1x = dx * normal.x; - P1y = dx * normal.y; - P2x = dy * normal.x; - P2y = dy * normal.y; - vA.x -= mA * (P1x + P2x); - vA.y -= mA * (P1y + P2y); - wA -= iA * ((cp1.rA.x * P1y - cp1.rA.y * P1x) + (cp2.rA.x * P2y - cp2.rA.y * P2x)); - vB.x += mB * (P1x + P2x); - vB.y += mB * (P1y + P2y); - wB += iB * ((cp1.rB.x * P1y - cp1.rB.y * P1x) + (cp2.rB.x * P2y - cp2.rB.y * P2x)); - cp1.normalImpulse = xx; - cp2.normalImpulse = xy; - break - } - break - } - } - this.m_velocities[indexA].w = wA; - this.m_velocities[indexB].w = wB - } - }, - StoreImpulses: function () { - for (var i = 0; i < this.m_count; ++i) { - var vc = this.m_velocityConstraints[i]; - var manifold = this.m_contacts[vc.contactIndex].GetManifold(); - for (var j = 0; j < vc.pointCount; ++j) { - manifold.points[j].normalImpulse = vc.points[j].normalImpulse; - manifold.points[j].tangentImpulse = vc.points[j].tangentImpulse - } - } - }, - SolvePositionConstraints: function () { - var minSeparation = 0; - for (var i = 0; i < this.m_count; ++i) { - var pc = this.m_positionConstraints[i]; - var indexA = pc.indexA; - var indexB = pc.indexB; - var localCenterA = pc.localCenterA; - var mA = pc.invMassA; - var iA = pc.invIA; - var localCenterB = pc.localCenterB; - var mB = pc.invMassB; - var iB = pc.invIB; - var pointCount = pc.pointCount; - var cA = this.m_positions[indexA].c; - var aA = this.m_positions[indexA].a; - var cB = this.m_positions[indexB].c; - var aB = this.m_positions[indexB].a; - for (var j = 0; j < pointCount; ++j) { - b2ContactSolver.cs_xfA.q.Set(aA); - b2ContactSolver.cs_xfB.q.Set(aB); - b2ContactSolver.cs_xfA.p.x = cA.x - (b2ContactSolver.cs_xfA.q.c * localCenterA.x - b2ContactSolver.cs_xfA.q.s * localCenterA.y); - b2ContactSolver.cs_xfA.p.y = cA.y - (b2ContactSolver.cs_xfA.q.s * localCenterA.x + b2ContactSolver.cs_xfA.q.c * localCenterA.y); - b2ContactSolver.cs_xfB.p.x = cB.x - (b2ContactSolver.cs_xfB.q.c * localCenterB.x - b2ContactSolver.cs_xfB.q.s * localCenterB.y); - b2ContactSolver.cs_xfB.p.y = cB.y - (b2ContactSolver.cs_xfB.q.s * localCenterB.x + b2ContactSolver.cs_xfB.q.c * localCenterB.y); - b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); - var normal = b2ContactSolver.temp_solver_manifold.normal; - var point = b2ContactSolver.temp_solver_manifold.point; - var separation = b2ContactSolver.temp_solver_manifold.separation; - var rAx = point.x - cA.x; - var rAy = point.y - cA.y; - var rBx = point.x - cB.x; - var rBy = point.y - cB.y; - minSeparation = b2Min(minSeparation, separation); - var C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); - var rnA = rAx * normal.y - rAy * normal.x; - var rnB = rBx * normal.y - rBy * normal.x; - var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; - var impulse = K > 0 ? -C / K : 0; - var Px = impulse * normal.x; - var Py = impulse * normal.y; - cA.x -= mA * Px; - cA.y -= mA * Py; - aA -= iA * (rAx * Py - rAy * Px); - cB.x += mB * Px; - cB.y += mB * Py; - aB += iB * (rBx * Py - rBy * Px) - } - this.m_positions[indexA].a = aA; - this.m_positions[indexB].a = aB - } - return minSeparation >= -3 * b2_linearSlop - }, - SolveTOIPositionConstraints: function (toiIndexA, toiIndexB) { - var minSeparation = 0; - for (var i = 0; i < this.m_count; ++i) { - var pc = this.m_positionConstraints[i]; - var indexA = pc.indexA; - var indexB = pc.indexB; - var localCenterA = pc.localCenterA; - var localCenterB = pc.localCenterB; - var pointCount = pc.pointCount; - var mA = 0; - var iA = 0; - if (indexA == toiIndexA || indexA == toiIndexB) { - mA = pc.invMassA; - iA = pc.invIA - } - var mB = 0; - var iB = 0; - if (indexB == toiIndexA || indexB == toiIndexB) { - mB = pc.invMassB; - iB = pc.invIB - } - var cA = this.m_positions[indexA].c; - var aA = this.m_positions[indexA].a; - var cB = this.m_positions[indexB].c; - var aB = this.m_positions[indexB].a; - for (var j = 0; j < pointCount; ++j) { - b2ContactSolver.cs_xfA.q.Set(aA); - b2ContactSolver.cs_xfB.q.Set(aB); - b2ContactSolver.cs_xfA.p.Assign(b2Vec2.Subtract(cA, b2Mul_r_v2(b2ContactSolver.cs_xfA.q, localCenterA))); - b2ContactSolver.cs_xfB.p.Assign(b2Vec2.Subtract(cB, b2Mul_r_v2(b2ContactSolver.cs_xfB.q, localCenterB))); - b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); - var normal = b2ContactSolver.temp_solver_manifold.normal; - var point = b2ContactSolver.temp_solver_manifold.point; - var separation = b2ContactSolver.temp_solver_manifold.separation; - var rA = b2Vec2.Subtract(point, cA); - var rB = b2Vec2.Subtract(point, cB); - minSeparation = b2Min(minSeparation, separation); - var C = b2Clamp(b2_toiBaugarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); - var rnA = b2Cross_v2_v2(rA, normal); - var rnB = b2Cross_v2_v2(rB, normal); - var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; - var impulse = K > 0 ? -C / K : 0; - var P = b2Vec2.Multiply(impulse, normal); - cA.Subtract(b2Vec2.Multiply(mA, P)); - aA -= iA * b2Cross_v2_v2(rA, P); - cB.Add(b2Vec2.Multiply(mB, P)); - aB += iB * b2Cross_v2_v2(rB, P) - } - this.m_positions[indexA].a = aA; - this.m_positions[indexB].a = aB - } - return minSeparation >= -1.5 * b2_linearSlop + this.m_positions[indexA].a = aA; + this.m_positions[indexB].a = aB } - }; - "use strict"; - - function b2Island() { - this.m_bodies = []; - this.m_contacts = []; - this.m_joints = []; - this.m_velocities = []; - this.m_positions = [] + return minSeparation >= -3 * b2_linearSlop + }, + SolveTOIPositionConstraints: function (toiIndexA, toiIndexB) { + var minSeparation = 0; + for (var i = 0; i < this.m_count; ++i) { + var pc = this.m_positionConstraints[i]; + var indexA = pc.indexA; + var indexB = pc.indexB; + var localCenterA = pc.localCenterA; + var localCenterB = pc.localCenterB; + var pointCount = pc.pointCount; + var mA = 0; + var iA = 0; + if (indexA == toiIndexA || indexA == toiIndexB) { + mA = pc.invMassA; + iA = pc.invIA + } + var mB = 0; + var iB = 0; + if (indexB == toiIndexA || indexB == toiIndexB) { + mB = pc.invMassB; + iB = pc.invIB + } + var cA = this.m_positions[indexA].c; + var aA = this.m_positions[indexA].a; + var cB = this.m_positions[indexB].c; + var aB = this.m_positions[indexB].a; + for (var j = 0; j < pointCount; ++j) { + b2ContactSolver.cs_xfA.q.Set(aA); + b2ContactSolver.cs_xfB.q.Set(aB); + b2ContactSolver.cs_xfA.p.Assign(b2Vec2.Subtract(cA, b2Mul_r_v2(b2ContactSolver.cs_xfA.q, localCenterA))); + b2ContactSolver.cs_xfB.p.Assign(b2Vec2.Subtract(cB, b2Mul_r_v2(b2ContactSolver.cs_xfB.q, localCenterB))); + b2ContactSolver.temp_solver_manifold.Initialize(pc, b2ContactSolver.cs_xfA, b2ContactSolver.cs_xfB, j); + var normal = b2ContactSolver.temp_solver_manifold.normal; + var point = b2ContactSolver.temp_solver_manifold.point; + var separation = b2ContactSolver.temp_solver_manifold.separation; + var rA = b2Vec2.Subtract(point, cA); + var rB = b2Vec2.Subtract(point, cB); + minSeparation = b2Min(minSeparation, separation); + var C = b2Clamp(b2_toiBaugarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0); + var rnA = b2Cross_v2_v2(rA, normal); + var rnB = b2Cross_v2_v2(rB, normal); + var K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + var impulse = K > 0 ? -C / K : 0; + var P = b2Vec2.Multiply(impulse, normal); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * b2Cross_v2_v2(rB, P) + } + this.m_positions[indexA].a = aA; + this.m_positions[indexB].a = aB + } + return minSeparation >= -1.5 * b2_linearSlop } - var profile_solve_init = b2Profiler.create("solve initialization", "solve"); - var profile_solve_init_warmStarting = b2Profiler.create("warm starting", "solve initialization"); - var profile_solve_velocity = b2Profiler.create("solve velocities", "solve"); - var profile_solve_position = b2Profiler.create("solve positions", "solve"); - b2Island._solverData = new b2SolverData(); - b2Island._solverDef = new b2ContactSolverDef(); - b2Island._solver = new b2ContactSolver(); - b2Island.prototype = { - Clear: function () { - this.m_bodyCount = 0; - this.m_contactCount = 0; - this.m_jointCount = 0 - }, - Initialize: function (bodyCapacity, contactCapacity, jointCapacity, listener) { - this.m_listener = listener; - this.m_bodyCapacity = bodyCapacity; - this.m_contactCapacity = contactCapacity; - this.m_jointCapacity = jointCapacity; - this.m_bodyCount = 0; - this.m_contactCount = 0; - this.m_jointCount = 0; - this.m_bodies.length = bodyCapacity; - this.m_contacts.length = contactCapacity; - this.m_joints.length = jointCapacity; - this.m_velocities.length = bodyCapacity; - this.m_positions.length = bodyCapacity - }, - Solve: function (step, gravity, allowSleep) { - profile_solve_init.start(); - var h = step.dt; +}; +"use strict"; + +function b2Island() { + this.m_bodies = []; + this.m_contacts = []; + this.m_joints = []; + this.m_velocities = []; + this.m_positions = [] +} +var profile_solve_init = b2Profiler.create("solve initialization", "solve"); +var profile_solve_init_warmStarting = b2Profiler.create("warm starting", "solve initialization"); +var profile_solve_velocity = b2Profiler.create("solve velocities", "solve"); +var profile_solve_position = b2Profiler.create("solve positions", "solve"); +b2Island._solverData = new b2SolverData(); +b2Island._solverDef = new b2ContactSolverDef(); +b2Island._solver = new b2ContactSolver(); +b2Island.prototype = { + Clear: function () { + this.m_bodyCount = 0; + this.m_contactCount = 0; + this.m_jointCount = 0 + }, + Initialize: function (bodyCapacity, contactCapacity, jointCapacity, listener) { + this.m_listener = listener; + this.m_bodyCapacity = bodyCapacity; + this.m_contactCapacity = contactCapacity; + this.m_jointCapacity = jointCapacity; + this.m_bodyCount = 0; + this.m_contactCount = 0; + this.m_jointCount = 0; + this.m_bodies.length = bodyCapacity; + this.m_contacts.length = contactCapacity; + this.m_joints.length = jointCapacity; + this.m_velocities.length = bodyCapacity; + this.m_positions.length = bodyCapacity + }, + Solve: function (step, gravity, allowSleep) { + profile_solve_init.start(); + var h = step.dt; + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + this.m_positions[i].c.Assign(b.m_sweep.c); + var a = b.m_sweep.a; + this.m_velocities[i].v.Assign(b.m_linearVelocity); + var w = b.m_angularVelocity; + b.m_sweep.c0.Assign(b.m_sweep.c); + b.m_sweep.a0 = b.m_sweep.a; + if (b.m_type == b2Body.b2_dynamicBody) { + this.m_velocities[i].v.x += h * ((b.m_gravityScale * gravity.x) + (b.m_invMass * b.m_force.x)); + this.m_velocities[i].v.y += h * ((b.m_gravityScale * gravity.y) + (b.m_invMass * b.m_force.y)); + w += h * b.m_invI * b.m_torque; + this.m_velocities[i].v.x *= 1 / (1 + h * b.m_linearDamping); + this.m_velocities[i].v.y *= 1 / (1 + h * b.m_linearDamping); + w *= 1 / (1 + h * b.m_angularDamping) + } + this.m_positions[i].a = a; + this.m_velocities[i].w = w + } + b2Island._solverData.step = step; + b2Island._solverData.positions = this.m_positions; + b2Island._solverData.velocities = this.m_velocities; + b2Island._solverDef.step = step; + b2Island._solverDef.contacts = this.m_contacts; + b2Island._solverDef.count = this.m_contactCount; + b2Island._solverDef.positions = this.m_positions; + b2Island._solverDef.velocities = this.m_velocities; + b2Island._solverDef.allocator = this.m_allocator; + b2Island._solver.Init(b2Island._solverDef); + b2Island._solver.InitializeVelocityConstraints(); + if (step.warmStarting) { + profile_solve_init_warmStarting.start(); + b2Island._solver.WarmStart(); + profile_solve_init_warmStarting.stop() + } + for (var i = 0; i < this.m_jointCount; ++i) { + this.m_joints[i].InitVelocityConstraints(b2Island._solverData) + } + profile_solve_init.stop(); + profile_solve_velocity.start(); + for (var i = 0; i < step.velocityIterations; ++i) { + for (var j = 0; j < this.m_jointCount; ++j) { + this.m_joints[j].SolveVelocityConstraints(b2Island._solverData) + } + b2Island._solver.SolveVelocityConstraints() + } + b2Island._solver.StoreImpulses(); + profile_solve_velocity.stop(); + profile_solve_position.start(); + for (var i = 0; i < this.m_bodyCount; ++i) { + var c = this.m_positions[i].c; + var a = this.m_positions[i].a; + var v = this.m_velocities[i].v; + var w = this.m_velocities[i].w; + var translationx = h * v.x; + var translationy = h * v.y; + var translationl = translationx * translationx + translationy * translationy; + if (translationl > b2_maxTranslationSquared) { + var ratio = b2_maxTranslation / b2Sqrt(translationl); + v.x *= ratio; + v.y *= ratio + } + var rotation = h * w; + if (rotation * rotation > b2_maxRotationSquared) { + var ratio = b2_maxRotation / b2Abs(rotation); + w *= ratio + } + c.x += h * v.x; + c.y += h * v.y; + a += h * w; + this.m_positions[i].a = a; + this.m_velocities[i].w = w + } + var positionSolved = false; + for (var i = 0; i < step.positionIterations; ++i) { + var contactsOkay = b2Island._solver.SolvePositionConstraints(); + var jointsOkay = true; + for (var j = 0; j < this.m_jointCount; ++j) { + var jointOkay = this.m_joints[j].SolvePositionConstraints(b2Island._solverData); + jointsOkay = jointsOkay && jointOkay + } + if (contactsOkay && jointsOkay) { + positionSolved = true; + break + } + } + for (var i = 0; i < this.m_bodyCount; ++i) { + var body = this.m_bodies[i]; + body.m_sweep.c.Assign(this.m_positions[i].c); + body.m_sweep.a = this.m_positions[i].a; + body.m_linearVelocity.Assign(this.m_velocities[i].v); + body.m_angularVelocity = this.m_velocities[i].w; + body.SynchronizeTransform() + } + profile_solve_position.stop(); + this.Report(b2Island._solver.m_velocityConstraints); + if (allowSleep) { + var minSleepTime = b2_maxFloat; + var linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance; + var angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance; for (var i = 0; i < this.m_bodyCount; ++i) { var b = this.m_bodies[i]; - this.m_positions[i].c.Assign(b.m_sweep.c); - var a = b.m_sweep.a; - this.m_velocities[i].v.Assign(b.m_linearVelocity); - var w = b.m_angularVelocity; - b.m_sweep.c0.Assign(b.m_sweep.c); - b.m_sweep.a0 = b.m_sweep.a; - if (b.m_type == b2Body.b2_dynamicBody) { - this.m_velocities[i].v.x += h * ((b.m_gravityScale * gravity.x) + (b.m_invMass * b.m_force.x)); - this.m_velocities[i].v.y += h * ((b.m_gravityScale * gravity.y) + (b.m_invMass * b.m_force.y)); - w += h * b.m_invI * b.m_torque; - this.m_velocities[i].v.x *= 1 / (1 + h * b.m_linearDamping); - this.m_velocities[i].v.y *= 1 / (1 + h * b.m_linearDamping); - w *= 1 / (1 + h * b.m_angularDamping) + if (b.GetType() == b2Body.b2_staticBody) { + continue } - this.m_positions[i].a = a; - this.m_velocities[i].w = w - } - b2Island._solverData.step = step; - b2Island._solverData.positions = this.m_positions; - b2Island._solverData.velocities = this.m_velocities; - b2Island._solverDef.step = step; - b2Island._solverDef.contacts = this.m_contacts; - b2Island._solverDef.count = this.m_contactCount; - b2Island._solverDef.positions = this.m_positions; - b2Island._solverDef.velocities = this.m_velocities; - b2Island._solverDef.allocator = this.m_allocator; - b2Island._solver.Init(b2Island._solverDef); - b2Island._solver.InitializeVelocityConstraints(); - if (step.warmStarting) { - profile_solve_init_warmStarting.start(); - b2Island._solver.WarmStart(); - profile_solve_init_warmStarting.stop() - } - for (var i = 0; i < this.m_jointCount; ++i) { - this.m_joints[i].InitVelocityConstraints(b2Island._solverData) - } - profile_solve_init.stop(); - profile_solve_velocity.start(); - for (var i = 0; i < step.velocityIterations; ++i) { - for (var j = 0; j < this.m_jointCount; ++j) { - this.m_joints[j].SolveVelocityConstraints(b2Island._solverData) - } - b2Island._solver.SolveVelocityConstraints() - } - b2Island._solver.StoreImpulses(); - profile_solve_velocity.stop(); - profile_solve_position.start(); - for (var i = 0; i < this.m_bodyCount; ++i) { - var c = this.m_positions[i].c; - var a = this.m_positions[i].a; - var v = this.m_velocities[i].v; - var w = this.m_velocities[i].w; - var translationx = h * v.x; - var translationy = h * v.y; - var translationl = translationx * translationx + translationy * translationy; - if (translationl > b2_maxTranslationSquared) { - var ratio = b2_maxTranslation / b2Sqrt(translationl); - v.x *= ratio; - v.y *= ratio - } - var rotation = h * w; - if (rotation * rotation > b2_maxRotationSquared) { - var ratio = b2_maxRotation / b2Abs(rotation); - w *= ratio - } - c.x += h * v.x; - c.y += h * v.y; - a += h * w; - this.m_positions[i].a = a; - this.m_velocities[i].w = w - } - var positionSolved = false; - for (var i = 0; i < step.positionIterations; ++i) { - var contactsOkay = b2Island._solver.SolvePositionConstraints(); - var jointsOkay = true; - for (var j = 0; j < this.m_jointCount; ++j) { - var jointOkay = this.m_joints[j].SolvePositionConstraints(b2Island._solverData); - jointsOkay = jointsOkay && jointOkay - } - if (contactsOkay && jointsOkay) { - positionSolved = true; - break + if ((b.m_flags & b2Body.e_autoSleepFlag) == 0 || b.m_angularVelocity * b.m_angularVelocity > angTolSqr || b2Dot_v2_v2(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) { + b.m_sleepTime = 0; + minSleepTime = 0 + } else { + b.m_sleepTime += h; + minSleepTime = b2Min(minSleepTime, b.m_sleepTime) } } - for (var i = 0; i < this.m_bodyCount; ++i) { - var body = this.m_bodies[i]; - body.m_sweep.c.Assign(this.m_positions[i].c); - body.m_sweep.a = this.m_positions[i].a; - body.m_linearVelocity.Assign(this.m_velocities[i].v); - body.m_angularVelocity = this.m_velocities[i].w; - body.SynchronizeTransform() - } - profile_solve_position.stop(); - this.Report(b2Island._solver.m_velocityConstraints); - if (allowSleep) { - var minSleepTime = b2_maxFloat; - var linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance; - var angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance; + if (minSleepTime >= b2_timeToSleep && positionSolved) { for (var i = 0; i < this.m_bodyCount; ++i) { var b = this.m_bodies[i]; - if (b.GetType() == b2Body.b2_staticBody) { - continue - } - if ((b.m_flags & b2Body.e_autoSleepFlag) == 0 || b.m_angularVelocity * b.m_angularVelocity > angTolSqr || b2Dot_v2_v2(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) { - b.m_sleepTime = 0; - minSleepTime = 0 - } else { - b.m_sleepTime += h; - minSleepTime = b2Min(minSleepTime, b.m_sleepTime) - } + b.SetAwake(false) } - if (minSleepTime >= b2_timeToSleep && positionSolved) { - for (var i = 0; i < this.m_bodyCount; ++i) { - var b = this.m_bodies[i]; - b.SetAwake(false) - } - } - } - }, - SolveTOI: function (subStep, toiIndexA, toiIndexB) { - for (var i = 0; i < this.m_bodyCount; ++i) { - var b = this.m_bodies[i]; - this.m_positions[i].c.Assign(b.m_sweep.c); - this.m_positions[i].a = b.m_sweep.a; - this.m_velocities[i].v.Assign(b.m_linearVelocity); - this.m_velocities[i].w = b.m_angularVelocity - } - b2Island._solverDef.contacts = this.m_contacts; - b2Island._solverDef.count = this.m_contactCount; - b2Island._solverDef.step = subStep; - b2Island._solverDef.positions = this.m_positions; - b2Island._solverDef.velocities = this.m_velocities; - b2Island._solver.Init(b2Island._solverDef); - for (var i = 0; i < subStep.positionIterations; ++i) { - var contactsOkay = b2Island._solver.SolveTOIPositionConstraints(toiIndexA, toiIndexB); - if (contactsOkay) { - break - } - } - this.m_bodies[toiIndexA].m_sweep.c0.Assign(this.m_positions[toiIndexA].c); - this.m_bodies[toiIndexA].m_sweep.a0 = this.m_positions[toiIndexA].a; - this.m_bodies[toiIndexB].m_sweep.c0.Assign(this.m_positions[toiIndexB].c); - this.m_bodies[toiIndexB].m_sweep.a0 = this.m_positions[toiIndexB].a; - b2Island._solver.InitializeVelocityConstraints(); - for (var i = 0; i < subStep.velocityIterations; ++i) { - b2Island._solver.SolveVelocityConstraints() - } - var h = subStep.dt; - for (var i = 0; i < this.m_bodyCount; ++i) { - var c = this.m_positions[i].c; - var a = this.m_positions[i].a; - var v = this.m_velocities[i].v; - var w = this.m_velocities[i].w; - var translation = b2Vec2.Multiply(h, v); - if (b2Dot_v2_v2(translation, translation) > b2_maxTranslationSquared) { - var ratio = b2_maxTranslation / translation.Length(); - v.Multiply(ratio) - } - var rotation = h * w; - if (rotation * rotation > b2_maxRotationSquared) { - var ratio = b2_maxRotation / b2Abs(rotation); - w *= ratio - } - c.Add(b2Vec2.Multiply(h, v)); - a += h * w; - this.m_positions[i].a = a; - this.m_velocities[i].w = w; - var body = this.m_bodies[i]; - body.m_sweep.c.Assign(c); - body.m_sweep.a = a; - body.m_linearVelocity.Assign(v); - body.m_angularVelocity = w; - body.SynchronizeTransform() - } - this.Report(b2Island._solver.m_velocityConstraints) - }, - AddBody: function (body) { - body.m_islandIndex = this.m_bodyCount; - this.m_bodies[this.m_bodyCount] = body; - if (!this.m_positions[this.m_bodyCount]) { - this.m_positions[this.m_bodyCount] = new b2Position(); - this.m_velocities[this.m_bodyCount] = new b2Velocity() - }++this.m_bodyCount - }, - AddContact: function (contact) { - this.m_contacts[this.m_contactCount++] = contact - }, - AddJoint: function (joint) { - this.m_joints[this.m_jointCount++] = joint - }, - Report: function (constraints) { - if (this.m_listener == null) { - return - } - for (var i = 0; i < this.m_contactCount; ++i) { - var c = this.m_contacts[i]; - var vc = constraints[i]; - var impulse = new b2ContactImpulse(); - impulse.count = vc.pointCount; - for (var j = 0; j < vc.pointCount; ++j) { - impulse.normalImpulses[j] = vc.points[j].normalImpulse; - impulse.tangentImpulses[j] = vc.points[j].tangentImpulse - } - this.m_listener.PostSolve(c, impulse) } } - }; - - function b2Jacobian() { - this.linear = new b2Vec2(); - this.angularA = 0; - this.angularB = 0 - } - - function b2JointEdge() { - this.other = null; - this.joint = null; - this.prev = null; - this.next = null - } - - function b2JointDef() { - this.type = b2Joint.e_unknownJoint; - this.userData = null; - this.bodyA = null; - this.bodyB = null; - this.collideConnected = false - } - b2JointDef.prototype = { - _deserialize: function (data, bodies, joints) { - this.bodyA = bodies[data.bodyA]; - this.bodyB = bodies[data.bodyB]; - this.collideConnected = data.collideConnected + }, + SolveTOI: function (subStep, toiIndexA, toiIndexB) { + for (var i = 0; i < this.m_bodyCount; ++i) { + var b = this.m_bodies[i]; + this.m_positions[i].c.Assign(b.m_sweep.c); + this.m_positions[i].a = b.m_sweep.a; + this.m_velocities[i].v.Assign(b.m_linearVelocity); + this.m_velocities[i].w = b.m_angularVelocity } - }; - - function b2Joint(def) { - this.m_type = def.type; - this.m_prev = null; - this.m_next = null; - this.m_bodyA = def.bodyA; - this.m_bodyB = def.bodyB; - this.m_index = 0; - this.m_collideConnected = def.collideConnected; - this.m_islandFlag = false; - this.m_userData = def.userData; - this.m_edgeA = new b2JointEdge(); - this.m_edgeA.joint = null; - this.m_edgeA.other = null; - this.m_edgeA.prev = null; - this.m_edgeA.next = null; - this.m_edgeB = new b2JointEdge(); - this.m_edgeB.joint = null; - this.m_edgeB.other = null; - this.m_edgeB.prev = null; - this.m_edgeB.next = null - } - b2Joint.prototype = { - GetType: function () { - return this.m_type - }, - GetBodyA: function () { - return this.m_bodyA - }, - GetBodyB: function () { - return this.m_bodyB - }, - GetAnchorA: function () {}, - GetAnchorB: function () {}, - GetReactionForce: function (inv_dt) {}, - GetReactionTorque: function (inv_dt) {}, - GetNext: function () { - return this.m_next - }, - GetUserData: function () { - return this.m_userData - }, - SetUserData: function (data) { - this.m_userData = data - }, - IsActive: function () { - return this.m_bodyA.IsActive() && this.m_bodyB.IsActive() - }, - GetCollideConnected: function () { - return this.m_collideConnected - }, - ShiftOrigin: function (newOrigin) {}, - InitVelocityConstraints: function (data) {}, - SolveVelocityConstraints: function (data) {}, - SolvePositionConstraints: function (data) {}, - _serialize: function (out) { - var obj = out || {}; - obj.bodyA = null; - obj.bodyB = null; - obj.type = this.m_type; - obj.collideConnected = this.m_collideConnected; - return obj - } - }; - b2Joint.e_inactiveLimit = 0; - b2Joint.e_atLowerLimit = 1; - b2Joint.e_atUpperLimit = 2; - b2Joint.e_equalLimits = 3; - b2Joint.e_unknownJoint = 0; - b2Joint.e_revoluteJoint = 1; - b2Joint.e_prismaticJoint = 2; - b2Joint.e_distanceJoint = 3; - b2Joint.e_pulleyJoint = 4; - b2Joint.e_mouseJoint = 5; - b2Joint.e_gearJoint = 6; - b2Joint.e_wheelJoint = 7; - b2Joint.e_weldJoint = 8; - b2Joint.e_frictionJoint = 9; - b2Joint.e_ropeJoint = 10; - b2Joint.e_motorJoint = 11; - b2Joint.Create = function (def) { - var joint = null; - switch (def.type) { - case b2Joint.e_distanceJoint: - joint = new b2DistanceJoint(def); - break; - case b2Joint.e_mouseJoint: - joint = new b2MouseJoint(def); - break; - case b2Joint.e_prismaticJoint: - joint = new b2PrismaticJoint(def); - break; - case b2Joint.e_revoluteJoint: - joint = new b2RevoluteJoint(def); - break; - case b2Joint.e_pulleyJoint: - joint = new b2PulleyJoint(def); - break; - case b2Joint.e_gearJoint: - joint = new b2GearJoint(def); - break; - case b2Joint.e_wheelJoint: - joint = new b2WheelJoint(def); - break; - case b2Joint.e_weldJoint: - joint = new b2WeldJoint(def); - break; - case b2Joint.e_frictionJoint: - joint = new b2FrictionJoint(def); - break; - case b2Joint.e_ropeJoint: - joint = new b2RopeJoint(def); - break; - case b2Joint.e_motorJoint: - joint = new b2MotorJoint(def); + b2Island._solverDef.contacts = this.m_contacts; + b2Island._solverDef.count = this.m_contactCount; + b2Island._solverDef.step = subStep; + b2Island._solverDef.positions = this.m_positions; + b2Island._solverDef.velocities = this.m_velocities; + b2Island._solver.Init(b2Island._solverDef); + for (var i = 0; i < subStep.positionIterations; ++i) { + var contactsOkay = b2Island._solver.SolveTOIPositionConstraints(toiIndexA, toiIndexB); + if (contactsOkay) { break + } } - return joint - }; - b2Joint.Destroy = function (joint) {}; - - function b2RevoluteJointDef() { - this.parent.call(this); - this.type = b2Joint.e_revoluteJoint; - this.localAnchorA = new b2Vec2(); - this.localAnchorB = new b2Vec2(); - this.referenceAngle = 0; - this.lowerAngle = 0; - this.upperAngle = 0; - this.maxMotorTorque = 0; - this.motorSpeed = 0; - this.enableLimit = false; - this.enableMotor = false; - Object.seal(this) - } - b2RevoluteJointDef.prototype = { - Initialize: function (bA, bB, anchor) { - this.bodyA = bA; - this.bodyB = bB; - this.localAnchorA = this.bodyA.GetLocalPoint(anchor); - this.localAnchorB = this.bodyB.GetLocalPoint(anchor); - this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.referenceAngle = data.referenceAngle; - this.lowerAngle = data.lowerAngle; - this.upperAngle = data.upperAngle; - this.maxMotorTorque = data.maxMotorTorque; - this.motorSpeed = data.motorSpeed; - this.enableLimit = data.enableLimit; - this.enableMotor = data.enableMotor + this.m_bodies[toiIndexA].m_sweep.c0.Assign(this.m_positions[toiIndexA].c); + this.m_bodies[toiIndexA].m_sweep.a0 = this.m_positions[toiIndexA].a; + this.m_bodies[toiIndexB].m_sweep.c0.Assign(this.m_positions[toiIndexB].c); + this.m_bodies[toiIndexB].m_sweep.a0 = this.m_positions[toiIndexB].a; + b2Island._solver.InitializeVelocityConstraints(); + for (var i = 0; i < subStep.velocityIterations; ++i) { + b2Island._solver.SolveVelocityConstraints() + } + var h = subStep.dt; + for (var i = 0; i < this.m_bodyCount; ++i) { + var c = this.m_positions[i].c; + var a = this.m_positions[i].a; + var v = this.m_velocities[i].v; + var w = this.m_velocities[i].w; + var translation = b2Vec2.Multiply(h, v); + if (b2Dot_v2_v2(translation, translation) > b2_maxTranslationSquared) { + var ratio = b2_maxTranslation / translation.Length(); + v.Multiply(ratio) + } + var rotation = h * w; + if (rotation * rotation > b2_maxRotationSquared) { + var ratio = b2_maxRotation / b2Abs(rotation); + w *= ratio + } + c.Add(b2Vec2.Multiply(h, v)); + a += h * w; + this.m_positions[i].a = a; + this.m_velocities[i].w = w; + var body = this.m_bodies[i]; + body.m_sweep.c.Assign(c); + body.m_sweep.a = a; + body.m_linearVelocity.Assign(v); + body.m_angularVelocity = w; + body.SynchronizeTransform() + } + this.Report(b2Island._solver.m_velocityConstraints) + }, + AddBody: function (body) { + body.m_islandIndex = this.m_bodyCount; + this.m_bodies[this.m_bodyCount] = body; + if (!this.m_positions[this.m_bodyCount]) { + this.m_positions[this.m_bodyCount] = new b2Position(); + this.m_velocities[this.m_bodyCount] = new b2Velocity() + }++this.m_bodyCount + }, + AddContact: function (contact) { + this.m_contacts[this.m_contactCount++] = contact + }, + AddJoint: function (joint) { + this.m_joints[this.m_jointCount++] = joint + }, + Report: function (constraints) { + if (this.m_listener == null) { + return + } + for (var i = 0; i < this.m_contactCount; ++i) { + var c = this.m_contacts[i]; + var vc = constraints[i]; + var impulse = new b2ContactImpulse(); + impulse.count = vc.pointCount; + for (var j = 0; j < vc.pointCount; ++j) { + impulse.normalImpulses[j] = vc.points[j].normalImpulse; + impulse.tangentImpulses[j] = vc.points[j].tangentImpulse + } + this.m_listener.PostSolve(c, impulse) } - }; - b2RevoluteJointDef._extend(b2JointDef); - - function b2RevoluteJoint(def) { - this.parent.call(this, def); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_referenceAngle = def.referenceAngle; - this.m_impulse = new b2Vec3(); - this.m_motorImpulse = 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; - this.m_limitState = b2Joint.e_inactiveLimit; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_mass = new b2Mat33(); - this.m_motorMass = 0 } - b2RevoluteJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - GetReferenceAngle: function () { - return this.m_referenceAngle - }, - GetJointAngle: function () { - var bA = this.m_bodyA; - var bB = this.m_bodyB; - return bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle - }, - GetJointSpeed: function () { - var bA = this.m_bodyA; - var bB = this.m_bodyB; - return bB.m_angularVelocity - bA.m_angularVelocity - }, - IsLimitEnabled: function () { - return this.m_enableLimit - }, - 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 - } - }, - GetLowerLimit: function () { - return this.m_lowerAngle - }, - GetUpperLimit: function () { - return this.m_upperAngle - }, - SetLimits: function (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; - this.m_lowerAngle = lower; - this.m_upperAngle = upper - } - }, - IsMotorEnabled: function () { - return this.m_enableMotor - }, - EnableMotor: function (flag) { +}; + +function b2Jacobian() { + this.linear = new b2Vec2(); + this.angularA = 0; + this.angularB = 0 +} + +function b2JointEdge() { + this.other = null; + this.joint = null; + this.prev = null; + this.next = null +} + +function b2JointDef() { + this.type = b2Joint.e_unknownJoint; + this.userData = null; + this.bodyA = null; + this.bodyB = null; + this.collideConnected = false +} +b2JointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.bodyA = bodies[data.bodyA]; + this.bodyB = bodies[data.bodyB]; + this.collideConnected = data.collideConnected + } +}; + +function b2Joint(def) { + this.m_type = def.type; + this.m_prev = null; + this.m_next = null; + this.m_bodyA = def.bodyA; + this.m_bodyB = def.bodyB; + this.m_index = 0; + this.m_collideConnected = def.collideConnected; + this.m_islandFlag = false; + this.m_userData = def.userData; + this.m_edgeA = new b2JointEdge(); + this.m_edgeA.joint = null; + this.m_edgeA.other = null; + this.m_edgeA.prev = null; + this.m_edgeA.next = null; + this.m_edgeB = new b2JointEdge(); + this.m_edgeB.joint = null; + this.m_edgeB.other = null; + this.m_edgeB.prev = null; + this.m_edgeB.next = null +} +b2Joint.prototype = { + GetType: function () { + return this.m_type + }, + GetBodyA: function () { + return this.m_bodyA + }, + GetBodyB: function () { + return this.m_bodyB + }, + GetAnchorA: function () {}, + GetAnchorB: function () {}, + GetReactionForce: function (inv_dt) {}, + GetReactionTorque: function (inv_dt) {}, + GetNext: function () { + return this.m_next + }, + GetUserData: function () { + return this.m_userData + }, + SetUserData: function (data) { + this.m_userData = data + }, + IsActive: function () { + return this.m_bodyA.IsActive() && this.m_bodyB.IsActive() + }, + GetCollideConnected: function () { + return this.m_collideConnected + }, + ShiftOrigin: function (newOrigin) {}, + InitVelocityConstraints: function (data) {}, + SolveVelocityConstraints: function (data) {}, + SolvePositionConstraints: function (data) {}, + _serialize: function (out) { + var obj = out || {}; + obj.bodyA = null; + obj.bodyB = null; + obj.type = this.m_type; + obj.collideConnected = this.m_collideConnected; + return obj + } +}; +b2Joint.e_inactiveLimit = 0; +b2Joint.e_atLowerLimit = 1; +b2Joint.e_atUpperLimit = 2; +b2Joint.e_equalLimits = 3; +b2Joint.e_unknownJoint = 0; +b2Joint.e_revoluteJoint = 1; +b2Joint.e_prismaticJoint = 2; +b2Joint.e_distanceJoint = 3; +b2Joint.e_pulleyJoint = 4; +b2Joint.e_mouseJoint = 5; +b2Joint.e_gearJoint = 6; +b2Joint.e_wheelJoint = 7; +b2Joint.e_weldJoint = 8; +b2Joint.e_frictionJoint = 9; +b2Joint.e_ropeJoint = 10; +b2Joint.e_motorJoint = 11; +b2Joint.Create = function (def) { + var joint = null; + switch (def.type) { + case b2Joint.e_distanceJoint: + joint = new b2DistanceJoint(def); + break; + case b2Joint.e_mouseJoint: + joint = new b2MouseJoint(def); + break; + case b2Joint.e_prismaticJoint: + joint = new b2PrismaticJoint(def); + break; + case b2Joint.e_revoluteJoint: + joint = new b2RevoluteJoint(def); + break; + case b2Joint.e_pulleyJoint: + joint = new b2PulleyJoint(def); + break; + case b2Joint.e_gearJoint: + joint = new b2GearJoint(def); + break; + case b2Joint.e_wheelJoint: + joint = new b2WheelJoint(def); + break; + case b2Joint.e_weldJoint: + joint = new b2WeldJoint(def); + break; + case b2Joint.e_frictionJoint: + joint = new b2FrictionJoint(def); + break; + case b2Joint.e_ropeJoint: + joint = new b2RopeJoint(def); + break; + case b2Joint.e_motorJoint: + joint = new b2MotorJoint(def); + break + } + return joint +}; +b2Joint.Destroy = function (joint) {}; + +function b2RevoluteJointDef() { + this.parent.call(this); + this.type = b2Joint.e_revoluteJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.referenceAngle = 0; + this.lowerAngle = 0; + this.upperAngle = 0; + this.maxMotorTorque = 0; + this.motorSpeed = 0; + this.enableLimit = false; + this.enableMotor = false; + Object.seal(this) +} +b2RevoluteJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.referenceAngle = data.referenceAngle; + this.lowerAngle = data.lowerAngle; + this.upperAngle = data.upperAngle; + this.maxMotorTorque = data.maxMotorTorque; + this.motorSpeed = data.motorSpeed; + this.enableLimit = data.enableLimit; + this.enableMotor = data.enableMotor + } +}; +b2RevoluteJointDef._extend(b2JointDef); + +function b2RevoluteJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_referenceAngle = def.referenceAngle; + this.m_impulse = new b2Vec3(); + this.m_motorImpulse = 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; + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat33(); + this.m_motorMass = 0 +} +b2RevoluteJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + GetJointAngle: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + return bB.m_sweep.a - bA.m_sweep.a - this.m_referenceAngle + }, + GetJointSpeed: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + return bB.m_angularVelocity - bA.m_angularVelocity + }, + IsLimitEnabled: function () { + return this.m_enableLimit + }, + EnableLimit: function (flag) { + if (flag != this.m_enableLimit) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); - this.m_enableMotor = flag - }, - SetMotorSpeed: function (speed) { + this.m_enableLimit = flag; + this.m_impulse.z = 0 + } + }, + GetLowerLimit: function () { + return this.m_lowerAngle + }, + GetUpperLimit: function () { + return this.m_upperAngle + }, + SetLimits: function (lower, upper) { + if (lower != this.m_lowerAngle || upper != this.m_upperAngle) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); - this.m_motorSpeed = speed - }, - GetMotorSpeed: function () { - return this.m_motorSpeed - }, - SetMaxMotorTorque: function (torque) { - this.m_bodyA.SetAwake(true); - this.m_bodyB.SetAwake(true); - this.m_maxMotorTorque = torque - }, - GetMaxMotorTorque: function () { - return this.m_maxMotorTorque - }, - GetReactionForce: function (inv_dt) { - var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); - return b2Vec2.Multiply(inv_dt, P) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * this.m_impulse.z - }, - GetMotorTorque: function (inv_dt) { - return inv_dt * this.m_motorImpulse - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - 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 = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var fixedRotation = (iA + iB == 0); - 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) { - this.m_motorMass = 1 / this.m_motorMass - } - if (this.m_enableMotor == false || fixedRotation) { - this.m_motorImpulse = 0 - } - if (this.m_enableLimit && fixedRotation == false) { - var jointAngle = aB - aA - this.m_referenceAngle; - if (b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2 * b2_angularSlop) { - this.m_limitState = b2Joint.e_equalLimits + this.m_impulse.z = 0; + this.m_lowerAngle = lower; + this.m_upperAngle = upper + } + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorTorque: function (torque) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorTorque = torque + }, + GetMaxMotorTorque: function () { + return this.m_maxMotorTorque + }, + GetReactionForce: function (inv_dt) { + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.z + }, + GetMotorTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + 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 = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var fixedRotation = (iA + iB == 0); + 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) { + this.m_motorMass = 1 / this.m_motorMass + } + if (this.m_enableMotor == false || fixedRotation) { + this.m_motorImpulse = 0 + } + if (this.m_enableLimit && fixedRotation == false) { + var jointAngle = aB - aA - this.m_referenceAngle; + if (b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2 * b2_angularSlop) { + this.m_limitState = b2Joint.e_equalLimits + } else { + if (jointAngle <= this.m_lowerAngle) { + if (this.m_limitState != b2Joint.e_atLowerLimit) { + this.m_impulse.z = 0 + } + this.m_limitState = b2Joint.e_atLowerLimit } else { - if (jointAngle <= this.m_lowerAngle) { - if (this.m_limitState != b2Joint.e_atLowerLimit) { + if (jointAngle >= this.m_upperAngle) { + if (this.m_limitState != b2Joint.e_atUpperLimit) { this.m_impulse.z = 0 } - this.m_limitState = b2Joint.e_atLowerLimit + this.m_limitState = b2Joint.e_atUpperLimit } else { - if (jointAngle >= this.m_upperAngle) { - if (this.m_limitState != b2Joint.e_atUpperLimit) { - this.m_impulse.z = 0 - } - this.m_limitState = b2Joint.e_atUpperLimit - } else { - this.m_limitState = b2Joint.e_inactiveLimit; - this.m_impulse.z = 0 - } + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 } } + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + this.m_motorImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_motorImpulse + this.m_impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_motorImpulse + this.m_impulse.z) + } else { + this.m_impulse.SetZero(); + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var fixedRotation = (iA + iB == 0); + if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits && fixedRotation == false) { + var Cdot = wB - wA - this.m_motorSpeed; + var impulse = -this.m_motorMass * Cdot; + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorTorque; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse + } + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var Cdot2 = wB - wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var impulse = this.m_mass.Solve33(Cdot).Negate(); + if (this.m_limitState == b2Joint.e_equalLimits) { + this.m_impulse.Add(impulse) } else { - this.m_limitState = b2Joint.e_inactiveLimit - } - if (data.step.warmStarting) { - this.m_impulse.Multiply(data.step.dtRatio); - this.m_motorImpulse *= data.step.dtRatio; - var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_motorImpulse + this.m_impulse.z); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_motorImpulse + this.m_impulse.z) - } else { - this.m_impulse.SetZero(); - this.m_motorImpulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var fixedRotation = (iA + iB == 0); - if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits && fixedRotation == false) { - var Cdot = wB - wA - this.m_motorSpeed; - var impulse = -this.m_motorMass * Cdot; - var oldImpulse = this.m_motorImpulse; - var maxImpulse = data.step.dt * this.m_maxMotorTorque; - this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); - impulse = this.m_motorImpulse - oldImpulse; - wA -= iA * impulse; - wB += iB * impulse - } - if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { - var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); - var Cdot2 = wB - wA; - var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); - var impulse = this.m_mass.Solve33(Cdot).Negate(); - if (this.m_limitState == b2Joint.e_equalLimits) { - this.m_impulse.Add(impulse) + if (this.m_limitState == b2Joint.e_atLowerLimit) { + var newImpulse = this.m_impulse.z + impulse.z; + if (newImpulse < 0) { + var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); + var reduced = this.m_mass.Solve22(rhs); + 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 + } else { + this.m_impulse.Add(impulse) + } } else { - if (this.m_limitState == b2Joint.e_atLowerLimit) { + if (this.m_limitState == b2Joint.e_atUpperLimit) { var newImpulse = this.m_impulse.z + impulse.z; - if (newImpulse < 0) { + if (newImpulse > 0) { var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); var reduced = this.m_mass.Solve22(rhs); impulse.x = reduced.x; @@ -7571,4012 +7585,3987 @@ } else { this.m_impulse.Add(impulse) } - } else { - if (this.m_limitState == b2Joint.e_atUpperLimit) { - var newImpulse = this.m_impulse.z + impulse.z; - if (newImpulse > 0) { - var rhs = b2Vec2.Add(Cdot1.Negate(), b2Vec2.Multiply(this.m_impulse.z, new b2Vec2(this.m_mass.ez.x, this.m_mass.ez.y))); - var reduced = this.m_mass.Solve22(rhs); - 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 - } else { - this.m_impulse.Add(impulse) - } - } } } - var P = new b2Vec2(impulse.x, impulse.y); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) - } else { - var Cdot = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); - var impulse = this.m_mass.Solve22(Cdot.Negate()); - this.m_impulse.x += impulse.x; - this.m_impulse.y += impulse.y; - vA.Subtract(b2Vec2.Multiply(mA, impulse)); - wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); - vB.Add(b2Vec2.Multiply(mB, impulse)); - wB += iB * b2Cross_v2_v2(this.m_rB, impulse) } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var angularError = 0; - var positionError = 0; - var fixedRotation = (this.m_invIA + this.m_invIB == 0); - if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { - var angle = aB - aA - this.m_referenceAngle; - var limitImpulse = 0; - if (this.m_limitState == b2Joint.e_equalLimits) { - var C = b2Clamp(angle - this.m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); - limitImpulse = -this.m_motorMass * C; - angularError = b2Abs(C) - } else { - if (this.m_limitState == b2Joint.e_atLowerLimit) { - var C = angle - this.m_lowerAngle; - angularError = -C; - C = b2Clamp(C + b2_angularSlop, -b2_maxAngularCorrection, 0); - limitImpulse = -this.m_motorMass * C - } else { - if (this.m_limitState == b2Joint.e_atUpperLimit) { - var C = angle - this.m_upperAngle; - angularError = C; - C = b2Clamp(C - b2_angularSlop, 0, b2_maxAngularCorrection); - limitImpulse = -this.m_motorMass * C - } - } - } - aA -= this.m_invIA * limitImpulse; - aB += this.m_invIB * limitImpulse - } - qA.Set(aA); - qB.Set(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var C = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - positionError = C.Length(); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var K = new b2Mat22(); - 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 = K.Solve(C).Negate(); - cA.Subtract(b2Vec2.Multiply(mA, impulse)); - aA -= iA * b2Cross_v2_v2(rA, impulse); - cB.Add(b2Vec2.Multiply(mB, impulse)); - aB += iB * b2Cross_v2_v2(rB, impulse); - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return positionError <= b2_linearSlop && angularError <= b2_angularSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.referenceAngle = this.m_referenceAngle; - obj.lowerAngle = this.m_lowerAngle; - obj.upperAngle = this.m_upperAngle; - obj.maxMotorTorque = this.m_maxMotorTorque; - obj.motorSpeed = this.m_motorSpeed; - obj.enableLimit = this.m_enableLimit; - obj.enableMotor = this.m_enableMotor; - return obj + var P = new b2Vec2(impulse.x, impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) + } else { + var Cdot = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var impulse = this.m_mass.Solve22(Cdot.Negate()); + this.m_impulse.x += impulse.x; + this.m_impulse.y += impulse.y; + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse) } - }; - b2RevoluteJoint._extend(b2Joint); - - function b2MouseJointDef() { - this.parent.call(this); - this.type = b2Joint.e_mouseJoint; - this.target = new b2Vec2(0, 0); - this.maxForce = 0; - this.frequencyHz = 5; - this.dampingRatio = 0.7; - Object.seal(this) - } - b2MouseJointDef._extend(b2JointDef); - - function b2MouseJoint(def) { - this.parent.call(this, def); - this.m_targetA = def.target.Clone(); - this.m_localAnchorB = b2MulT_t_v2(this.m_bodyB.GetTransform(), this.m_targetA); - this.m_maxForce = def.maxForce; - this.m_impulse = new b2Vec2(); - this.m_frequencyHz = def.frequencyHz; - this.m_dampingRatio = def.dampingRatio; - this.m_beta = 0; - this.m_gamma = 0; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_rB = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassB = 0; - this.m_invIB = 0; - this.m_mass = new b2Mat22(); - this.m_C = new b2Vec2() - } - b2MouseJoint.prototype = { - GetAnchorA: function () { - return this.m_targetA - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - return b2Vec2.Multiply(inv_dt, this.m_impulse) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * 0 - }, - SetTarget: function (target) { - if (this.m_bodyB.IsAwake() == false) { - this.m_bodyB.SetAwake(true) + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var angularError = 0; + var positionError = 0; + var fixedRotation = (this.m_invIA + this.m_invIB == 0); + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit && fixedRotation == false) { + var angle = aB - aA - this.m_referenceAngle; + var limitImpulse = 0; + if (this.m_limitState == b2Joint.e_equalLimits) { + var C = b2Clamp(angle - this.m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); + limitImpulse = -this.m_motorMass * C; + angularError = b2Abs(C) + } else { + if (this.m_limitState == b2Joint.e_atLowerLimit) { + var C = angle - this.m_lowerAngle; + angularError = -C; + C = b2Clamp(C + b2_angularSlop, -b2_maxAngularCorrection, 0); + limitImpulse = -this.m_motorMass * C + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + var C = angle - this.m_upperAngle; + angularError = C; + C = b2Clamp(C - b2_angularSlop, 0, b2_maxAngularCorrection); + limitImpulse = -this.m_motorMass * C + } + } } - this.m_targetA.Assign(target) - }, - GetTarget: function () { - return this.m_targetA - }, - SetMaxForce: function (force) { - this.m_maxForce = force - }, - GetMaxForce: function () { - return this.m_maxForce - }, - SetFrequency: function (hz) { - this.m_frequencyHz = hz - }, - GetFrequency: function () { - return this.m_frequencyHz - }, - SetDampingRatio: function (ratio) { - this.m_dampingRatio = ratio - }, - GetDampingRatio: function () { - return this.m_dampingRatio - }, - ShiftOrigin: function (newOrigin) { - this.m_targetA.Subtract(newOrigin) - }, - InitVelocityConstraints: function (data) { - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); - this.m_invMassB = this.m_bodyB.m_invMass; - this.m_invIB = this.m_bodyB.m_invI; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qB = new b2Rot(aB); - var mass = this.m_bodyB.GetMass(); + aA -= this.m_invIA * limitImpulse; + aB += this.m_invIB * limitImpulse + } + qA.Set(aA); + qB.Set(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var C = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + positionError = C.Length(); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + 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 = K.Solve(C).Negate(); + cA.Subtract(b2Vec2.Multiply(mA, impulse)); + aA -= iA * b2Cross_v2_v2(rA, impulse); + cB.Add(b2Vec2.Multiply(mB, impulse)); + aB += iB * b2Cross_v2_v2(rB, impulse); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return positionError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.lowerAngle = this.m_lowerAngle; + obj.upperAngle = this.m_upperAngle; + obj.maxMotorTorque = this.m_maxMotorTorque; + obj.motorSpeed = this.m_motorSpeed; + obj.enableLimit = this.m_enableLimit; + obj.enableMotor = this.m_enableMotor; + return obj + } +}; +b2RevoluteJoint._extend(b2Joint); + +function b2MouseJointDef() { + this.parent.call(this); + this.type = b2Joint.e_mouseJoint; + this.target = new b2Vec2(0, 0); + this.maxForce = 0; + this.frequencyHz = 5; + this.dampingRatio = 0.7; + Object.seal(this) +} +b2MouseJointDef._extend(b2JointDef); + +function b2MouseJoint(def) { + this.parent.call(this, def); + this.m_targetA = def.target.Clone(); + this.m_localAnchorB = b2MulT_t_v2(this.m_bodyB.GetTransform(), this.m_targetA); + this.m_maxForce = def.maxForce; + this.m_impulse = new b2Vec2(); + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_beta = 0; + this.m_gamma = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rB = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassB = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat22(); + this.m_C = new b2Vec2() +} +b2MouseJoint.prototype = { + GetAnchorA: function () { + return this.m_targetA + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_impulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * 0 + }, + SetTarget: function (target) { + if (this.m_bodyB.IsAwake() == false) { + this.m_bodyB.SetAwake(true) + } + this.m_targetA.Assign(target) + }, + GetTarget: function () { + return this.m_targetA + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + ShiftOrigin: function (newOrigin) { + this.m_targetA.Subtract(newOrigin) + }, + InitVelocityConstraints: function (data) { + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_invMassB = this.m_bodyB.m_invMass; + this.m_invIB = this.m_bodyB.m_invI; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qB = new b2Rot(aB); + var mass = this.m_bodyB.GetMass(); + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * mass * this.m_dampingRatio * omega; + var k = mass * (omega * omega); + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + if (this.m_gamma != 0) { + this.m_gamma = 1 / this.m_gamma + } + this.m_beta = h * k * this.m_gamma; + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + var K = new b2Mat22(); + 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.Assign(K.GetInverse()); + this.m_C.Assign(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), this.m_targetA)); + this.m_C.Multiply(this.m_beta); + wB *= 0.98; + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + vB.Add(b2Vec2.Multiply(this.m_invMassB, this.m_impulse)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, this.m_impulse) + } else { + this.m_impulse.SetZero() + } + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var Cdot = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var impulse = b2Mul_m22_v2(this.m_mass, (b2Vec2.Add(b2Vec2.Add(Cdot, this.m_C), b2Vec2.Multiply(this.m_gamma, this.m_impulse))).Negate()); + var oldImpulse = this.m_impulse.Clone(); + this.m_impulse.Add(impulse); + var maxImpulse = data.step.dt * this.m_maxForce; + if (this.m_impulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_impulse.Multiply(maxImpulse / this.m_impulse.Length()) + } + impulse.Assign(b2Vec2.Subtract(this.m_impulse, oldImpulse)); + vB.Add(b2Vec2.Multiply(this.m_invMassB, impulse)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + } +}; +b2MouseJoint._extend(b2Joint); + +function b2DistanceJointDef() { + this.parent.call(this); + this.type = b2Joint.e_distanceJoint; + this.localAnchorA = new b2Vec2(0, 0); + this.localAnchorB = new b2Vec2(0, 0); + this.length = 1; + this.frequencyHz = 0; + this.dampingRatio = 0; + Object.seal(this) +} +b2DistanceJointDef.prototype = { + Initialize: function (b1, b2, anchor1, anchor2) { + this.bodyA = b1; + this.bodyB = b2; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor1); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor2); + var d = b2Vec2.Subtract(anchor2, anchor1); + this.length = d.Length() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.length = data.length; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } +}; +b2DistanceJointDef._extend(b2JointDef); + +function b2DistanceJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_length = def.length; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_impulse = 0; + this.m_gamma = 0; + this.m_bias = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_u = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = 0 +} +b2DistanceJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); + return F + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetLength: function (length) { + this.m_length = length + }, + GetLength: function () { + return this.m_length + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + this.m_u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA); + var length = this.m_u.Length(); + if (length > b2_linearSlop) { + this.m_u.Multiply(1 / length) + } else { + this.m_u.Set(0, 0) + } + var crAu = b2Cross_v2_v2(this.m_rA, this.m_u); + var crBu = b2Cross_v2_v2(this.m_rB, this.m_u); + var invMass = this.m_invMassA + this.m_invIA * crAu * crAu + this.m_invMassB + this.m_invIB * crBu * crBu; + this.m_mass = invMass != 0 ? 1 / invMass : 0; + if (this.m_frequencyHz > 0) { + var C = length - this.m_length; var omega = 2 * b2_pi * this.m_frequencyHz; - var d = 2 * mass * this.m_dampingRatio * omega; - var k = mass * (omega * omega); + var d = 2 * this.m_mass * this.m_dampingRatio * omega; + var k = this.m_mass * omega * omega; var h = data.step.dt; this.m_gamma = h * (d + h * k); - if (this.m_gamma != 0) { - this.m_gamma = 1 / this.m_gamma - } - this.m_beta = h * k * this.m_gamma; - this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); - var K = new b2Mat22(); - 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.Assign(K.GetInverse()); - this.m_C.Assign(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), this.m_targetA)); - this.m_C.Multiply(this.m_beta); - wB *= 0.98; - if (data.step.warmStarting) { - this.m_impulse.Multiply(data.step.dtRatio); - vB.Add(b2Vec2.Multiply(this.m_invMassB, this.m_impulse)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, this.m_impulse) - } else { - this.m_impulse.SetZero() - } - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var Cdot = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); - var impulse = b2Mul_m22_v2(this.m_mass, (b2Vec2.Add(b2Vec2.Add(Cdot, this.m_C), b2Vec2.Multiply(this.m_gamma, this.m_impulse))).Negate()); - var oldImpulse = this.m_impulse.Clone(); - this.m_impulse.Add(impulse); - var maxImpulse = data.step.dt * this.m_maxForce; - if (this.m_impulse.LengthSquared() > maxImpulse * maxImpulse) { - this.m_impulse.Multiply(maxImpulse / this.m_impulse.Length()) - } - impulse.Assign(b2Vec2.Subtract(this.m_impulse, oldImpulse)); - vB.Add(b2Vec2.Multiply(this.m_invMassB, impulse)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, impulse); - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - return true + this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + this.m_bias = C * h * k * this.m_gamma; + invMass += this.m_gamma; + this.m_mass = invMass != 0 ? 1 / invMass : 0 + } else { + this.m_gamma = 0; + this.m_bias = 0 } - }; - b2MouseJoint._extend(b2Joint); - - function b2DistanceJointDef() { - this.parent.call(this); - this.type = b2Joint.e_distanceJoint; - this.localAnchorA = new b2Vec2(0, 0); - this.localAnchorB = new b2Vec2(0, 0); - this.length = 1; - this.frequencyHz = 0; - this.dampingRatio = 0; - Object.seal(this) - } - b2DistanceJointDef.prototype = { - Initialize: function (b1, b2, anchor1, anchor2) { - this.bodyA = b1; - this.bodyB = b2; - this.localAnchorA = this.bodyA.GetLocalPoint(anchor1); - this.localAnchorB = this.bodyB.GetLocalPoint(anchor2); - var d = b2Vec2.Subtract(anchor2, anchor1); - this.length = d.Length() - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.length = data.length; - this.frequencyHz = data.frequencyHz; - this.dampingRatio = data.dampingRatio - } - }; - b2DistanceJointDef._extend(b2JointDef); - - function b2DistanceJoint(def) { - this.parent.call(this, def); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_length = def.length; - this.m_frequencyHz = def.frequencyHz; - this.m_dampingRatio = def.dampingRatio; - this.m_impulse = 0; - this.m_gamma = 0; - this.m_bias = 0; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_u = new b2Vec2(); - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_mass = 0 - } - b2DistanceJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); - return F - }, - GetReactionTorque: function (inv_dt) { - return 0 - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - SetLength: function (length) { - this.m_length = length - }, - GetLength: function () { - return this.m_length - }, - SetFrequency: function (hz) { - this.m_frequencyHz = hz - }, - GetFrequency: function () { - return this.m_frequencyHz - }, - SetDampingRatio: function (ratio) { - this.m_dampingRatio = ratio - }, - GetDampingRatio: function () { - return this.m_dampingRatio - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - this.m_u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA); - var length = this.m_u.Length(); - if (length > b2_linearSlop) { - this.m_u.Multiply(1 / length) - } else { - this.m_u.Set(0, 0) - } - var crAu = b2Cross_v2_v2(this.m_rA, this.m_u); - var crBu = b2Cross_v2_v2(this.m_rB, this.m_u); - var invMass = this.m_invMassA + this.m_invIA * crAu * crAu + this.m_invMassB + this.m_invIB * crBu * crBu; - this.m_mass = invMass != 0 ? 1 / invMass : 0; - if (this.m_frequencyHz > 0) { - var C = length - this.m_length; - var omega = 2 * b2_pi * this.m_frequencyHz; - var d = 2 * this.m_mass * this.m_dampingRatio * omega; - var k = this.m_mass * omega * omega; - var h = data.step.dt; - this.m_gamma = h * (d + h * k); - this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; - this.m_bias = C * h * k * this.m_gamma; - invMass += this.m_gamma; - this.m_mass = invMass != 0 ? 1 / invMass : 0 - } else { - this.m_gamma = 0; - this.m_bias = 0 - } - if (data.step.warmStarting) { - this.m_impulse *= data.step.dtRatio; - var P = b2Vec2.Multiply(this.m_impulse, this.m_u); - vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); - wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); - vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) - } else { - this.m_impulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); - var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); - var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); - var impulse = -this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse); - this.m_impulse += impulse; - var P = b2Vec2.Multiply(impulse, this.m_u); + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var P = b2Vec2.Multiply(this.m_impulse, this.m_u); vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - if (this.m_frequencyHz > 0) { - return true - } - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - var length = u.Normalize(); - var C = length - this.m_length; - C = b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection); - var impulse = -this.m_mass * C; - var P = b2Vec2.Multiply(impulse, u); - cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); - aA -= this.m_invIA * b2Cross_v2_v2(rA, P); - cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - aB += this.m_invIB * b2Cross_v2_v2(rB, P); - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return b2Abs(C) < b2_linearSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.length = this.m_length; - obj.frequencyHz = this.m_frequencyHz; - obj.dampingRatio = this.m_dampingRatio; - return obj + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) + } else { + this.m_impulse = 0 } - }; - b2DistanceJoint._extend(b2Joint); - - function b2PrismaticJointDef() { - this.parent.call(this); - this.type = b2Joint.e_prismaticJoint; - this.localAnchorA = new b2Vec2(); - this.localAnchorB = new b2Vec2(); - this.localAxisA = new b2Vec2(1, 0); - this.referenceAngle = 0; - this.enableLimit = false; - this.lowerTranslation = 0; - this.upperTranslation = 0; - this.enableMotor = false; - this.maxMotorForce = 0; - this.motorSpeed = 0; - Object.seal(this) - } - b2PrismaticJointDef.prototype = { - Initialize: function (bA, bB, anchor, axis) { - this.bodyA = bA; - this.bodyB = bB; - this.localAnchorA = this.bodyA.GetLocalPoint(anchor); - this.localAnchorB = this.bodyB.GetLocalPoint(anchor); - this.localAxisA = this.bodyA.GetLocalVector(axis); - this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.localAxisA._deserialize(data.localAxisA); - this.referenceAngle = data.referenceAngle; - this.enableLimit = data.enableLimit; - this.lowerTranslation = data.lowerTranslation; - this.upperTranslation = data.upperTranslation; - this.enableMotor = data.enableMotor; - this.maxMotorForce = data.maxMotorForce; - this.motorSpeed = data.motorSpeed + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); + var impulse = -this.m_mass * (Cdot + this.m_bias + this.m_gamma * this.m_impulse); + this.m_impulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + if (this.m_frequencyHz > 0) { + return true } - }; - b2PrismaticJointDef._extend(b2JointDef); - - function b2PrismaticJoint(def) { - this.parent.call(this, def); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_localXAxisA = def.localAxisA.Clone(); - this.m_localXAxisA.Normalize(); - this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); - this.m_referenceAngle = def.referenceAngle; - this.m_impulse = new b2Vec3(); - this.m_motorMass = 0; - this.m_motorImpulse = 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 = b2Joint.e_inactiveLimit; - this.m_axis = new b2Vec2(); - this.m_perp = new b2Vec2(); - this.m_indexA = 0; - this.m_indexB = 0; - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_s1 = 0, this.m_s2 = 0; - this.m_a1 = 0, this.m_a2 = 0; - this.m_K = new b2Mat33(); - this.m_motorMass = 0 + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var length = u.Normalize(); + var C = length - this.m_length; + C = b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection); + var impulse = -this.m_mass * C; + var P = b2Vec2.Multiply(impulse, u); + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * b2Cross_v2_v2(rB, P); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return b2Abs(C) < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.length = this.m_length; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj } - b2PrismaticJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((this.m_motorImpulse + this.m_impulse.z), this.m_axis))) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * this.m_impulse.y - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - GetLocalAxisA: function () { - return this.m_localXAxisA - }, - GetReferenceAngle: function () { - return this.m_referenceAngle - }, - GetJointTranslation: function () { - var pA = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); - var pB = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); - var d = b2Vec2.Subtract(pB, pA); - var axis = this.m_bodyA.GetWorldVector(this.m_localXAxisA); - var translation = b2Dot_v2_v2(d, axis); - return translation - }, - GetJointSpeed: function () { - var bA = this.m_bodyA; - var bB = this.m_bodyB; - var rA = b2Mul_r_v2(bA.m_xf.q, b2Vec2.Subtract(this.m_localAnchorA, bA.m_sweep.localCenter)); - var rB = b2Mul_r_v2(bB.m_xf.q, b2Vec2.Subtract(this.m_localAnchorB, bB.m_sweep.localCenter)); - var p1 = b2Vec2.Add(bA.m_sweep.c, rA); - var p2 = b2Vec2.Add(bB.m_sweep.c, rB); - var d = b2Vec2.Subtract(p2, p1); - var axis = b2Mul_r_v2(bA.m_xf.q, this.m_localXAxisA); - var vA = bA.m_linearVelocity; - var vB = bB.m_linearVelocity; - var wA = bA.m_angularVelocity; - var wB = bB.m_angularVelocity; - var speed = b2Dot_v2_v2(d, b2Cross_f_v2(wA, axis)) + b2Dot_v2_v2(axis, b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, rB)), vA), b2Cross_f_v2(wA, rA))); - return speed - }, - IsLimitEnabled: function () { - return this.m_enableLimit - }, - 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 - } - }, - GetLowerLimit: function () { - return this.m_lowerTranslation - }, - GetUpperLimit: function () { - return this.m_upperTranslation - }, - SetLimits: function (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 - } - }, - IsMotorEnabled: function () { - return this.m_enableMotor - }, - EnableMotor: function (flag) { +}; +b2DistanceJoint._extend(b2Joint); + +function b2PrismaticJointDef() { + this.parent.call(this); + this.type = b2Joint.e_prismaticJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.localAxisA = new b2Vec2(1, 0); + this.referenceAngle = 0; + this.enableLimit = false; + this.lowerTranslation = 0; + this.upperTranslation = 0; + this.enableMotor = false; + this.maxMotorForce = 0; + this.motorSpeed = 0; + Object.seal(this) +} +b2PrismaticJointDef.prototype = { + Initialize: function (bA, bB, anchor, axis) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA = this.bodyA.GetLocalPoint(anchor); + this.localAnchorB = this.bodyB.GetLocalPoint(anchor); + this.localAxisA = this.bodyA.GetLocalVector(axis); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.localAxisA._deserialize(data.localAxisA); + this.referenceAngle = data.referenceAngle; + this.enableLimit = data.enableLimit; + this.lowerTranslation = data.lowerTranslation; + this.upperTranslation = data.upperTranslation; + this.enableMotor = data.enableMotor; + this.maxMotorForce = data.maxMotorForce; + this.motorSpeed = data.motorSpeed + } +}; +b2PrismaticJointDef._extend(b2JointDef); + +function b2PrismaticJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_localXAxisA = def.localAxisA.Clone(); + this.m_localXAxisA.Normalize(); + this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); + this.m_referenceAngle = def.referenceAngle; + this.m_impulse = new b2Vec3(); + this.m_motorMass = 0; + this.m_motorImpulse = 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 = b2Joint.e_inactiveLimit; + this.m_axis = new b2Vec2(); + this.m_perp = new b2Vec2(); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_s1 = 0, this.m_s2 = 0; + this.m_a1 = 0, this.m_a2 = 0; + this.m_K = new b2Mat33(); + this.m_motorMass = 0 +} +b2PrismaticJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((this.m_motorImpulse + this.m_impulse.z), this.m_axis))) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.y + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetLocalAxisA: function () { + return this.m_localXAxisA + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + GetJointTranslation: function () { + var pA = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); + var pB = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); + var d = b2Vec2.Subtract(pB, pA); + var axis = this.m_bodyA.GetWorldVector(this.m_localXAxisA); + var translation = b2Dot_v2_v2(d, axis); + return translation + }, + GetJointSpeed: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + var rA = b2Mul_r_v2(bA.m_xf.q, b2Vec2.Subtract(this.m_localAnchorA, bA.m_sweep.localCenter)); + var rB = b2Mul_r_v2(bB.m_xf.q, b2Vec2.Subtract(this.m_localAnchorB, bB.m_sweep.localCenter)); + var p1 = b2Vec2.Add(bA.m_sweep.c, rA); + var p2 = b2Vec2.Add(bB.m_sweep.c, rB); + var d = b2Vec2.Subtract(p2, p1); + var axis = b2Mul_r_v2(bA.m_xf.q, this.m_localXAxisA); + var vA = bA.m_linearVelocity; + var vB = bB.m_linearVelocity; + var wA = bA.m_angularVelocity; + var wB = bB.m_angularVelocity; + var speed = b2Dot_v2_v2(d, b2Cross_f_v2(wA, axis)) + b2Dot_v2_v2(axis, b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, rB)), vA), b2Cross_f_v2(wA, rA))); + return speed + }, + IsLimitEnabled: function () { + return this.m_enableLimit + }, + EnableLimit: function (flag) { + if (flag != this.m_enableLimit) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); - this.m_enableMotor = flag - }, - SetMotorSpeed: function (speed) { + this.m_enableLimit = flag; + this.m_impulse.z = 0 + } + }, + GetLowerLimit: function () { + return this.m_lowerTranslation + }, + GetUpperLimit: function () { + return this.m_upperTranslation + }, + SetLimits: function (lower, upper) { + if (lower != this.m_lowerTranslation || upper != this.m_upperTranslation) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); - this.m_motorSpeed = speed - }, - GetMotorSpeed: function () { - return this.m_motorSpeed - }, - SetMaxMotorForce: function (force) { - this.m_bodyA.SetAwake(true); - this.m_bodyB.SetAwake(true); - this.m_maxMotorForce = force - }, - GetMaxMotorForce: function () { - return this.m_maxMotorForce - }, - GetMotorForce: function (inv_dt) { - return inv_dt * this.m_motorImpulse - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - 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 = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - this.m_axis = b2Mul_r_v2(qA, this.m_localXAxisA); - this.m_a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_axis); - this.m_a2 = b2Cross_v2_v2(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) { - this.m_motorMass = 1 / this.m_motorMass + this.m_lowerTranslation = lower; + this.m_upperTranslation = upper; + this.m_impulse.z = 0 + } + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorForce: function (force) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorForce = force + }, + GetMaxMotorForce: function () { + return this.m_maxMotorForce + }, + GetMotorForce: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + 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 = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + this.m_axis = b2Mul_r_v2(qA, this.m_localXAxisA); + this.m_a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_axis); + this.m_a2 = b2Cross_v2_v2(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) { + this.m_motorMass = 1 / this.m_motorMass + } + this.m_perp = b2Mul_r_v2(qA, this.m_localYAxisA); + this.m_s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_perp); + this.m_s2 = b2Cross_v2_v2(rB, 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) { + k22 = 1 + } + 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); + if (this.m_enableLimit) { + var jointTranslation = b2Dot_v2_v2(this.m_axis, d); + if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { + this.m_limitState = b2Joint.e_equalLimits + } else { + if (jointTranslation <= this.m_lowerTranslation) { + if (this.m_limitState != b2Joint.e_atLowerLimit) { + this.m_limitState = b2Joint.e_atLowerLimit; + this.m_impulse.z = 0 + } + } else { + if (jointTranslation >= this.m_upperTranslation) { + if (this.m_limitState != b2Joint.e_atUpperLimit) { + this.m_limitState = b2Joint.e_atUpperLimit; + this.m_impulse.z = 0 + } + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + } } - this.m_perp = b2Mul_r_v2(qA, this.m_localYAxisA); - this.m_s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_perp); - this.m_s2 = b2Cross_v2_v2(rB, 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; + } else { + this.m_limitState = b2Joint.e_inactiveLimit; + this.m_impulse.z = 0 + } + if (this.m_enableMotor == false) { + this.m_motorImpulse = 0 + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + this.m_motorImpulse *= data.step.dtRatio; + var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((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.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } else { + this.m_impulse.SetZero(); + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) { + var Cdot = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(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 = data.step.dt * this.m_maxMotorForce; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + var P = b2Vec2.Multiply(impulse, this.m_axis); + var LA = impulse * this.m_a1; + var LB = impulse * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } + var Cdot1 = new b2Vec2(); + Cdot1.x = b2Dot_v2_v2(this.m_perp, b2Vec2.Subtract(vB, vA)) + this.m_s2 * wB - this.m_s1 * wA; + Cdot1.y = wB - wA; + if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) { + var Cdot2; + Cdot2 = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var f1 = this.m_impulse.Clone(); + var df = this.m_K.Solve33(Cdot.Negate()); + this.m_impulse.Add(df); + if (this.m_limitState == b2Joint.e_atLowerLimit) { + this.m_impulse.z = b2Max(this.m_impulse.z, 0) + } else { + if (this.m_limitState == b2Joint.e_atUpperLimit) { + this.m_impulse.z = b2Min(this.m_impulse.z, 0) + } + } + var b = b2Vec2.Subtract(Cdot1.Negate(), b2Vec2.Multiply((this.m_impulse.z - f1.z), new b2Vec2(this.m_K.ez.x, this.m_K.ez.y))); + var f2r = b2Vec2.Add(this.m_K.Solve22(b), new b2Vec2(f1.x, f1.y)); + this.m_impulse.x = f2r.x; + this.m_impulse.y = f2r.y; + df = b2Vec3.Subtract(this.m_impulse, f1); + var P = b2Vec2.Add(b2Vec2.Multiply(df.x, this.m_perp), b2Vec2.Multiply(df.z, this.m_axis)); + var LA = df.x * this.m_s1 + df.y + df.z * this.m_a1; + var LB = df.x * this.m_s2 + df.y + df.z * this.m_a2; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } else { + var df = this.m_K.Solve22(Cdot1.Negate()); + this.m_impulse.x += df.x; + this.m_impulse.y += df.y; + var P = b2Vec2.Multiply(df.x, this.m_perp); + var LA = df.x * this.m_s1 + df.y; + var LB = df.x * this.m_s2 + df.y; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var axis = b2Mul_r_v2(qA, this.m_localXAxisA); + var a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), axis); + var a2 = b2Cross_v2_v2(rB, axis); + var perp = b2Mul_r_v2(qA, this.m_localYAxisA); + var s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), perp); + var s2 = b2Cross_v2_v2(rB, perp); + var impulse = new b2Vec3(); + var C1 = new b2Vec2(); + C1.x = b2Dot_v2_v2(perp, d); + C1.y = aB - aA - this.m_referenceAngle; + var linearError = b2Abs(C1.x); + var angularError = b2Abs(C1.y); + var active = false; + var C2 = 0; + if (this.m_enableLimit) { + var translation = b2Dot_v2_v2(axis, d); + if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { + C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection); + linearError = b2Max(linearError, b2Abs(translation)); + active = true + } else { + if (translation <= this.m_lowerTranslation) { + C2 = b2Clamp(translation - this.m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0); + linearError = b2Max(linearError, this.m_lowerTranslation - translation); + active = true + } else { + if (translation >= this.m_upperTranslation) { + C2 = b2Clamp(translation - this.m_upperTranslation - b2_linearSlop, 0, b2_maxLinearCorrection); + linearError = b2Max(linearError, translation - this.m_upperTranslation); + active = true + } + } + } + } + if (active) { + var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + var k12 = iA * s1 + iB * s2; + var k13 = iA * s1 * a1 + iB * s2 * a2; var k22 = iA + iB; if (k22 == 0) { k22 = 1 } - 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); - if (this.m_enableLimit) { - var jointTranslation = b2Dot_v2_v2(this.m_axis, d); - if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { - this.m_limitState = b2Joint.e_equalLimits - } else { - if (jointTranslation <= this.m_lowerTranslation) { - if (this.m_limitState != b2Joint.e_atLowerLimit) { - this.m_limitState = b2Joint.e_atLowerLimit; - this.m_impulse.z = 0 - } - } else { - if (jointTranslation >= this.m_upperTranslation) { - if (this.m_limitState != b2Joint.e_atUpperLimit) { - this.m_limitState = b2Joint.e_atUpperLimit; - this.m_impulse.z = 0 - } - } else { - this.m_limitState = b2Joint.e_inactiveLimit; - this.m_impulse.z = 0 - } - } - } - } else { - this.m_limitState = b2Joint.e_inactiveLimit; - this.m_impulse.z = 0 + var k23 = iA * a1 + iB * a2; + var k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; + var K = new b2Mat33(); + K.ex.Set(k11, k12, k13); + K.ey.Set(k12, k22, k23); + K.ez.Set(k13, k23, k33); + var C = new b2Vec3(); + C.x = C1.x; + C.y = C1.y; + C.z = C2; + impulse = K.Solve33(C.Negate()) + } else { + var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + var k12 = iA * s1 + iB * s2; + var k22 = iA + iB; + if (k22 == 0) { + k22 = 1 } - if (this.m_enableMotor == false) { - this.m_motorImpulse = 0 - } - if (data.step.warmStarting) { - this.m_impulse.Multiply(data.step.dtRatio); - this.m_motorImpulse *= data.step.dtRatio; - var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse.x, this.m_perp), b2Vec2.Multiply((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.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * LA; - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * LB - } else { - this.m_impulse.SetZero(); - this.m_motorImpulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - if (this.m_enableMotor && this.m_limitState != b2Joint.e_equalLimits) { - var Cdot = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(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 = data.step.dt * this.m_maxMotorForce; - this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); - impulse = this.m_motorImpulse - oldImpulse; - var P = b2Vec2.Multiply(impulse, this.m_axis); - var LA = impulse * this.m_a1; - var LB = impulse * this.m_a2; - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * LA; - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * LB - } - var Cdot1 = new b2Vec2(); - Cdot1.x = b2Dot_v2_v2(this.m_perp, b2Vec2.Subtract(vB, vA)) + this.m_s2 * wB - this.m_s1 * wA; - Cdot1.y = wB - wA; - if (this.m_enableLimit && this.m_limitState != b2Joint.e_inactiveLimit) { - var Cdot2; - Cdot2 = b2Dot_v2_v2(this.m_axis, b2Vec2.Subtract(vB, vA)) + this.m_a2 * wB - this.m_a1 * wA; - var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); - var f1 = this.m_impulse.Clone(); - var df = this.m_K.Solve33(Cdot.Negate()); - this.m_impulse.Add(df); - if (this.m_limitState == b2Joint.e_atLowerLimit) { - this.m_impulse.z = b2Max(this.m_impulse.z, 0) - } else { - if (this.m_limitState == b2Joint.e_atUpperLimit) { - this.m_impulse.z = b2Min(this.m_impulse.z, 0) - } - } - var b = b2Vec2.Subtract(Cdot1.Negate(), b2Vec2.Multiply((this.m_impulse.z - f1.z), new b2Vec2(this.m_K.ez.x, this.m_K.ez.y))); - var f2r = b2Vec2.Add(this.m_K.Solve22(b), new b2Vec2(f1.x, f1.y)); - this.m_impulse.x = f2r.x; - this.m_impulse.y = f2r.y; - df = b2Vec3.Subtract(this.m_impulse, f1); - var P = b2Vec2.Add(b2Vec2.Multiply(df.x, this.m_perp), b2Vec2.Multiply(df.z, this.m_axis)); - var LA = df.x * this.m_s1 + df.y + df.z * this.m_a1; - var LB = df.x * this.m_s2 + df.y + df.z * this.m_a2; - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * LA; - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * LB - } else { - var df = this.m_K.Solve22(Cdot1.Negate()); - this.m_impulse.x += df.x; - this.m_impulse.y += df.y; - var P = b2Vec2.Multiply(df.x, this.m_perp); - var LA = df.x * this.m_s1 + df.y; - var LB = df.x * this.m_s2 + df.y; - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * LA; - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * LB - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - var axis = b2Mul_r_v2(qA, this.m_localXAxisA); - var a1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), axis); - var a2 = b2Cross_v2_v2(rB, axis); - var perp = b2Mul_r_v2(qA, this.m_localYAxisA); - var s1 = b2Cross_v2_v2(b2Vec2.Add(d, rA), perp); - var s2 = b2Cross_v2_v2(rB, perp); - var impulse = new b2Vec3(); - var C1 = new b2Vec2(); - C1.x = b2Dot_v2_v2(perp, d); - C1.y = aB - aA - this.m_referenceAngle; - var linearError = b2Abs(C1.x); - var angularError = b2Abs(C1.y); - var active = false; - var C2 = 0; - if (this.m_enableLimit) { - var translation = b2Dot_v2_v2(axis, d); - if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { - C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection); - linearError = b2Max(linearError, b2Abs(translation)); - active = true - } else { - if (translation <= this.m_lowerTranslation) { - C2 = b2Clamp(translation - this.m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0); - linearError = b2Max(linearError, this.m_lowerTranslation - translation); - active = true - } else { - if (translation >= this.m_upperTranslation) { - C2 = b2Clamp(translation - this.m_upperTranslation - b2_linearSlop, 0, b2_maxLinearCorrection); - linearError = b2Max(linearError, translation - this.m_upperTranslation); - active = true - } - } - } - } - if (active) { - var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; - var k12 = iA * s1 + iB * s2; - var k13 = iA * s1 * a1 + iB * s2 * a2; - var k22 = iA + iB; - if (k22 == 0) { - k22 = 1 - } - var k23 = iA * a1 + iB * a2; - var k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; - var K = new b2Mat33(); - K.ex.Set(k11, k12, k13); - K.ey.Set(k12, k22, k23); - K.ez.Set(k13, k23, k33); - var C = new b2Vec3(); - C.x = C1.x; - C.y = C1.y; - C.z = C2; - impulse = K.Solve33(C.Negate()) - } else { - var k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; - var k12 = iA * s1 + iB * s2; - var k22 = iA + iB; - if (k22 == 0) { - k22 = 1 - } - var K = new b2Mat22(); - K.ex.Set(k11, k12); - K.ey.Set(k12, k22); - var impulse1 = K.Solve(C1.Negate()); - impulse.x = impulse1.x; - impulse.y = impulse1.y; - impulse.z = 0 - } - var P = b2Vec2.Add(b2Vec2.Multiply(impulse.x, perp), b2Vec2.Multiply(impulse.z, axis)); - var LA = impulse.x * s1 + impulse.y + impulse.z * a1; - var LB = impulse.x * s2 + impulse.y + impulse.z * a2; - cA.Subtract(b2Vec2.Multiply(mA, P)); - aA -= iA * LA; - cB.Add(b2Vec2.Multiply(mB, P)); - aB += iB * LB; - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return linearError <= b2_linearSlop && angularError <= b2_angularSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.localAxisA = this.m_localXAxisA._serialize(); - obj.referenceAngle = this.m_referenceAngle; - obj.enableLimit = this.m_enableLimit; - obj.lowerTranslation = this.m_lowerTranslation; - obj.upperTranslation = this.m_upperTranslation; - obj.enableMotor = this.m_enableMotor; - obj.maxMotorForce = this.m_maxMotorForce; - obj.motorSpeed = this.m_motorSpeed; - return obj - } - }; - b2PrismaticJoint._extend(b2Joint); - - function b2FrictionJointDef() { - this.parent.call(this); - this.type = b2Joint.e_frictionJoint; - this.localAnchorA = new b2Vec2(); - this.localAnchorB = new b2Vec2(); - this.maxForce = 0; - this.maxTorque = 0; - Object.seal(this) - } - b2FrictionJointDef.prototype = { - Initialize: function (bA, bB, anchor) { - this.bodyA = bA; - this.bodyB = bB; - this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); - this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)) - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.maxForce = data.maxForce; - this.maxTorque = data.maxTorque - } - }; - b2FrictionJointDef._extend(b2JointDef); - - function b2FrictionJoint(def) { - this.parent.call(this, def); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_linearImpulse = new b2Vec2(); - this.m_angularImpulse = 0; - this.m_maxForce = def.maxForce; - this.m_maxTorque = def.maxTorque; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_linearMass = new b2Mat22(); - this.m_angularMass = 0 - } - b2FrictionJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * this.m_angularImpulse - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - SetMaxForce: function (force) { - this.m_maxForce = force - }, - GetMaxForce: function () { - return this.m_maxForce - }, - SetMaxTorque: function (torque) { - this.m_maxTorque = torque - }, - GetMaxTorque: function () { - return this.m_maxTorque - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; var K = new b2Mat22(); - 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) { - this.m_angularMass = 1 / this.m_angularMass - } - if (data.step.warmStarting) { - this.m_linearImpulse.Multiply(data.step.dtRatio); - this.m_angularImpulse *= data.step.dtRatio; - var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) - } else { - this.m_linearImpulse.SetZero(); - this.m_angularImpulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var h = data.step.dt; - var Cdot = wB - wA; - var impulse = -this.m_angularMass * Cdot; - var oldImpulse = this.m_angularImpulse; - var maxImpulse = h * this.m_maxTorque; - this.m_angularImpulse = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); - impulse = this.m_angularImpulse - oldImpulse; - wA -= iA * impulse; - wB += iB * impulse; - var Cdot = b2Vec2.Add(vB, b2Vec2.Subtract(b2Cross_f_v2(wB, this.m_rB), b2Vec2.Subtract(vA, b2Cross_f_v2(wA, this.m_rA)))); - var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); - var oldImpulse = this.m_linearImpulse.Clone(); - this.m_linearImpulse.Add(impulse); - var maxImpulse = h * this.m_maxForce; - if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { - this.m_linearImpulse.Normalize(); - this.m_linearImpulse.Multiply(maxImpulse) - } - impulse = b2Vec2.Subtract(this.m_linearImpulse, oldImpulse); - vA.Subtract(b2Vec2.Multiply(mA, impulse)); - wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); - vB.Add(b2Vec2.Multiply(mB, impulse)); - wB += iB * b2Cross_v2_v2(this.m_rB, impulse); - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - return true - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.maxForce = this.m_maxForce; - obj.maxTorque = this.m_maxTorque; - return obj + K.ex.Set(k11, k12); + K.ey.Set(k12, k22); + var impulse1 = K.Solve(C1.Negate()); + impulse.x = impulse1.x; + impulse.y = impulse1.y; + impulse.z = 0 } - }; - b2FrictionJoint._extend(b2Joint); - - function b2WeldJointDef() { - this.parent.call(this); - this.type = b2Joint.e_weldJoint; - this.localAnchorA = new b2Vec2(0, 0); - this.localAnchorB = new b2Vec2(0, 0); - this.referenceAngle = 0; - this.frequencyHz = 0; - this.dampingRatio = 0; - Object.seal(this) + var P = b2Vec2.Add(b2Vec2.Multiply(impulse.x, perp), b2Vec2.Multiply(impulse.z, axis)); + var LA = impulse.x * s1 + impulse.y + impulse.z * a1; + var LB = impulse.x * s2 + impulse.y + impulse.z * a2; + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * LA; + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * LB; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return linearError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.localAxisA = this.m_localXAxisA._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.enableLimit = this.m_enableLimit; + obj.lowerTranslation = this.m_lowerTranslation; + obj.upperTranslation = this.m_upperTranslation; + obj.enableMotor = this.m_enableMotor; + obj.maxMotorForce = this.m_maxMotorForce; + obj.motorSpeed = this.m_motorSpeed; + return obj } - b2WeldJointDef.prototype = { - Initialize: function (bA, bB, anchor) { - this.bodyA = bA; - this.bodyB = bB; - this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); - this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); - this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.referenceAngle = data.referenceAngle; - this.frequencyHz = data.frequencyHz; - this.dampingRatio = data.dampingRatio - } - }; - b2WeldJointDef._extend(b2JointDef); +}; +b2PrismaticJoint._extend(b2Joint); - function b2WeldJoint(def) { - this.parent.call(this, def); +function b2FrictionJointDef() { + this.parent.call(this); + this.type = b2Joint.e_frictionJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.maxForce = 0; + this.maxTorque = 0; + Object.seal(this) +} +b2FrictionJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)) + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.maxForce = data.maxForce; + this.maxTorque = data.maxTorque + } +}; +b2FrictionJointDef._extend(b2JointDef); + +function b2FrictionJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_linearImpulse = new b2Vec2(); + this.m_angularImpulse = 0; + this.m_maxForce = def.maxForce; + this.m_maxTorque = def.maxTorque; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_linearMass = new b2Mat22(); + this.m_angularMass = 0 +} +b2FrictionJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_angularImpulse + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetMaxTorque: function (torque) { + this.m_maxTorque = torque + }, + GetMaxTorque: function () { + return this.m_maxTorque + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + this.m_rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + 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) { + this.m_angularMass = 1 / this.m_angularMass + } + if (data.step.warmStarting) { + this.m_linearImpulse.Multiply(data.step.dtRatio); + this.m_angularImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) + } else { + this.m_linearImpulse.SetZero(); + this.m_angularImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var h = data.step.dt; + var Cdot = wB - wA; + var impulse = -this.m_angularMass * Cdot; + var oldImpulse = this.m_angularImpulse; + var maxImpulse = h * this.m_maxTorque; + this.m_angularImpulse = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_angularImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Vec2.Add(vB, b2Vec2.Subtract(b2Cross_f_v2(wB, this.m_rB), b2Vec2.Subtract(vA, b2Cross_f_v2(wA, this.m_rA)))); + var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); + var oldImpulse = this.m_linearImpulse.Clone(); + this.m_linearImpulse.Add(impulse); + var maxImpulse = h * this.m_maxForce; + if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_linearImpulse.Normalize(); + this.m_linearImpulse.Multiply(maxImpulse) + } + impulse = b2Vec2.Subtract(this.m_linearImpulse, oldImpulse); + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.maxForce = this.m_maxForce; + obj.maxTorque = this.m_maxTorque; + return obj + } +}; +b2FrictionJoint._extend(b2Joint); + +function b2WeldJointDef() { + this.parent.call(this); + this.type = b2Joint.e_weldJoint; + this.localAnchorA = new b2Vec2(0, 0); + this.localAnchorB = new b2Vec2(0, 0); + this.referenceAngle = 0; + this.frequencyHz = 0; + this.dampingRatio = 0; + Object.seal(this) +} +b2WeldJointDef.prototype = { + Initialize: function (bA, bB, anchor) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); + this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle() + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.referenceAngle = data.referenceAngle; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } +}; +b2WeldJointDef._extend(b2JointDef); + +function b2WeldJoint(def) { + this.parent.call(this, def); + this.m_bias = 0; + this.m_gamma = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = new b2Mat33(); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_referenceAngle = def.referenceAngle; + this.m_frequencyHz = def.frequencyHz; + this.m_dampingRatio = def.dampingRatio; + this.m_impulse = new b2Vec3() +} +b2WeldJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_impulse.z + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetReferenceAngle: function () { + return this.m_referenceAngle + }, + SetFrequency: function (hz) { + this.m_frequencyHz = hz + }, + GetFrequency: function () { + return this.m_frequencyHz + }, + SetDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat33(); + 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) { + K.GetInverse22(this.m_mass); + var invM = iA + iB; + var m = invM > 0 ? 1 / invM : 0; + var C = aB - aA - this.m_referenceAngle; + var omega = 2 * b2_pi * this.m_frequencyHz; + var d = 2 * m * this.m_dampingRatio * omega; + var k = m * omega * omega; + var h = data.step.dt; + this.m_gamma = h * (d + h * k); + this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + this.m_bias = C * h * k * this.m_gamma; + invM += this.m_gamma; + this.m_mass.ez.z = invM != 0 ? 1 / invM : 0 + } else { + K.GetSymInverse33(this.m_mass); + this.m_gamma = 0; + this.m_bias = 0 + } + if (data.step.warmStarting) { + this.m_impulse.Multiply(data.step.dtRatio); + var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_impulse.z) + } else { + this.m_impulse.SetZero() + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + if (this.m_frequencyHz > 0) { + var Cdot2 = wB - wA; + var impulse2 = -this.m_mass.ez.z * (Cdot2 + this.m_bias + this.m_gamma * this.m_impulse.z); + this.m_impulse.z += impulse2; + wA -= iA * impulse2; + wB += iB * impulse2; + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var impulse1 = b2Mul22_m33_v2(this.m_mass, Cdot1).Negate(); + this.m_impulse.x += impulse1.x; + this.m_impulse.y += impulse1.y; + var P = impulse1.Clone(); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * b2Cross_v2_v2(this.m_rB, P) + } else { + var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); + var Cdot2 = wB - wA; + var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); + var impulse = b2Mul_m33_v3(this.m_mass, Cdot).Negate(); + this.m_impulse.Add(impulse); + var P = new b2Vec2(impulse.x, impulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var positionError, angularError; + var K = new b2Mat33(); + 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) { + var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + positionError = C1.Length(); + angularError = 0; + var P = K.Solve22(C1).Negate(); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * b2Cross_v2_v2(rB, P) + } else { + var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var C2 = aB - aA - this.m_referenceAngle; + positionError = C1.Length(); + angularError = b2Abs(C2); + var C = new b2Vec3(C1.x, C1.y, C2); + var impulse = K.Solve33(C).Negate(); + var P = new b2Vec2(impulse.x, impulse.y); + cA.Subtract(b2Vec2.Multiply(mA, P)); + aA -= iA * (b2Cross_v2_v2(rA, P) + impulse.z); + cB.Add(b2Vec2.Multiply(mB, P)); + aB += iB * (b2Cross_v2_v2(rB, P) + impulse.z) + } + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return positionError <= b2_linearSlop && angularError <= b2_angularSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.referenceAngle = this.m_referenceAngle; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj + } +}; +b2WeldJoint._extend(b2Joint); + +function b2WheelJointDef() { + this.parent.call(this); + this.type = b2Joint.e_wheelJoint; + this.localAnchorA = new b2Vec2(); + this.localAnchorB = new b2Vec2(); + this.localAxisA = new b2Vec2(1, 0); + this.enableMotor = false; + this.maxMotorTorque = 0; + this.motorSpeed = 0; + this.frequencyHz = 2; + this.dampingRatio = 0.7; + Object.seal(this) +} +b2WheelJointDef.prototype = { + Initialize: function (bA, bB, anchor, axis) { + this.bodyA = bA; + this.bodyB = bB; + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); + this.localAxisA.Assign(this.bodyA.GetLocalVector(axis)) + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.localAxisA._deserialize(data.localAxisA); + this.enableMotor = data.enableMotor; + this.maxMotorTorque = data.maxMotorTorque; + this.motorSpeed = data.motorSpeed; + this.frequencyHz = data.frequencyHz; + this.dampingRatio = data.dampingRatio + } +}; +b2WheelJointDef._extend(b2JointDef); + +function b2WheelJoint(def) { + this.parent.call(this, def); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_localXAxisA = def.localAxisA.Clone(); + this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); + this.m_mass = 0; + this.m_impulse = 0; + this.m_motorMass = 0; + this.m_motorImpulse = 0; + this.m_springMass = 0; + this.m_springImpulse = 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; + this.m_gamma = 0; + this.m_ax = new b2Vec2(); + this.m_ay = new b2Vec2(); + this.m_sAx = this.m_sBx = 0; + this.m_sAy = this.m_sBy = 0 +} +b2WheelJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(this.m_springImpulse, this.m_ax))) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + GetLocalAxisA: function () { + return this.m_localXAxisA + }, + GetJointTranslation: function () { + var bA = this.m_bodyA; + var bB = this.m_bodyB; + var pA = bA.GetWorldPoint(this.m_localAnchorA); + var pB = bB.GetWorldPoint(this.m_localAnchorB); + var d = b2Vec2.Subtract(pB, pA); + var axis = bA.GetWorldVector(this.m_localXAxisA); + var translation = b2Dot_v2_v2(d, axis); + return translation + }, + GetJointSpeed: function () { + var wA = this.m_bodyA.m_angularVelocity; + var wB = this.m_bodyB.m_angularVelocity; + return wB - wA + }, + IsMotorEnabled: function () { + return this.m_enableMotor + }, + EnableMotor: function (flag) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_enableMotor = flag + }, + SetMotorSpeed: function (speed) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_motorSpeed = speed + }, + GetMotorSpeed: function () { + return this.m_motorSpeed + }, + SetMaxMotorTorque: function (torque) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_maxMotorTorque = torque + }, + GetMaxMotorTorque: function () { + return this.m_maxMotorTorque + }, + GetMotorTorque: function (inv_dt) { + return inv_dt * this.m_motorImpulse + }, + SetSpringFrequencyHz: function (hz) { + this.m_frequencyHz = hz + }, + GetSpringFrequencyHz: function () { + return this.m_frequencyHz + }, + SetSpringDampingRatio: function (ratio) { + this.m_dampingRatio = ratio + }, + GetSpringDampingRatio: function () { + return this.m_dampingRatio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + this.m_ay.Assign(b2Mul_r_v2(qA, this.m_localYAxisA)); + this.m_sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ay); + this.m_sBy = b2Cross_v2_v2(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) { + this.m_mass = 1 / this.m_mass + } + this.m_springMass = 0; this.m_bias = 0; this.m_gamma = 0; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_mass = new b2Mat33(); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_referenceAngle = def.referenceAngle; - this.m_frequencyHz = def.frequencyHz; - this.m_dampingRatio = def.dampingRatio; - this.m_impulse = new b2Vec3() - } - b2WeldJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); - return b2Vec2.Multiply(inv_dt, P) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * this.m_impulse.z - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - GetReferenceAngle: function () { - return this.m_referenceAngle - }, - SetFrequency: function (hz) { - this.m_frequencyHz = hz - }, - GetFrequency: function () { - return this.m_frequencyHz - }, - SetDampingRatio: function (ratio) { - this.m_dampingRatio = ratio - }, - GetDampingRatio: function () { - return this.m_dampingRatio - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); - this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var K = new b2Mat33(); - 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) { - K.GetInverse22(this.m_mass); - var invM = iA + iB; - var m = invM > 0 ? 1 / invM : 0; - var C = aB - aA - this.m_referenceAngle; + if (this.m_frequencyHz > 0) { + this.m_ax.Assign(b2Mul_r_v2(qA, this.m_localXAxisA)); + this.m_sAx = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ax); + this.m_sBx = b2Cross_v2_v2(rB, this.m_ax); + var invMass = mA + mB + iA * this.m_sAx * this.m_sAx + iB * this.m_sBx * this.m_sBx; + if (invMass > 0) { + this.m_springMass = 1 / invMass; + var C = b2Dot_v2_v2(d, this.m_ax); var omega = 2 * b2_pi * this.m_frequencyHz; - var d = 2 * m * this.m_dampingRatio * omega; - var k = m * omega * omega; + var d = 2 * this.m_springMass * this.m_dampingRatio * omega; + var k = this.m_springMass * omega * omega; var h = data.step.dt; this.m_gamma = h * (d + h * k); - this.m_gamma = this.m_gamma != 0 ? 1 / this.m_gamma : 0; + if (this.m_gamma > 0) { + this.m_gamma = 1 / this.m_gamma + } this.m_bias = C * h * k * this.m_gamma; - invM += this.m_gamma; - this.m_mass.ez.z = invM != 0 ? 1 / invM : 0 - } else { - K.GetSymInverse33(this.m_mass); - this.m_gamma = 0; - this.m_bias = 0 + this.m_springMass = invMass + this.m_gamma; + if (this.m_springMass > 0) { + this.m_springMass = 1 / this.m_springMass + } } - if (data.step.warmStarting) { - this.m_impulse.Multiply(data.step.dtRatio); - var P = new b2Vec2(this.m_impulse.x, this.m_impulse.y); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_impulse.z); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_impulse.z) - } else { - this.m_impulse.SetZero() - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - if (this.m_frequencyHz > 0) { - var Cdot2 = wB - wA; - var impulse2 = -this.m_mass.ez.z * (Cdot2 + this.m_bias + this.m_gamma * this.m_impulse.z); - this.m_impulse.z += impulse2; - wA -= iA * impulse2; - wB += iB * impulse2; - var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); - var impulse1 = b2Mul22_m33_v2(this.m_mass, Cdot1).Negate(); - this.m_impulse.x += impulse1.x; - this.m_impulse.y += impulse1.y; - var P = impulse1.Clone(); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * b2Cross_v2_v2(this.m_rA, P); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * b2Cross_v2_v2(this.m_rB, P) - } else { - var Cdot1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)); - var Cdot2 = wB - wA; - var Cdot = new b2Vec3(Cdot1.x, Cdot1.y, Cdot2); - var impulse = b2Mul_m33_v3(this.m_mass, Cdot).Negate(); - this.m_impulse.Add(impulse); - var P = new b2Vec2(impulse.x, impulse.y); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + impulse.z); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * (b2Cross_v2_v2(this.m_rB, P) + impulse.z) - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var positionError, angularError; - var K = new b2Mat33(); - 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) { - var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - positionError = C1.Length(); - angularError = 0; - var P = K.Solve22(C1).Negate(); - cA.Subtract(b2Vec2.Multiply(mA, P)); - aA -= iA * b2Cross_v2_v2(rA, P); - cB.Add(b2Vec2.Multiply(mB, P)); - aB += iB * b2Cross_v2_v2(rB, P) - } else { - var C1 = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - var C2 = aB - aA - this.m_referenceAngle; - positionError = C1.Length(); - angularError = b2Abs(C2); - var C = new b2Vec3(C1.x, C1.y, C2); - var impulse = K.Solve33(C).Negate(); - var P = new b2Vec2(impulse.x, impulse.y); - cA.Subtract(b2Vec2.Multiply(mA, P)); - aA -= iA * (b2Cross_v2_v2(rA, P) + impulse.z); - cB.Add(b2Vec2.Multiply(mB, P)); - aB += iB * (b2Cross_v2_v2(rB, P) + impulse.z) - } - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return positionError <= b2_linearSlop && angularError <= b2_angularSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.referenceAngle = this.m_referenceAngle; - obj.frequencyHz = this.m_frequencyHz; - obj.dampingRatio = this.m_dampingRatio; - return obj + } else { + this.m_springImpulse = 0 } - }; - b2WeldJoint._extend(b2Joint); - - function b2WheelJointDef() { - this.parent.call(this); - this.type = b2Joint.e_wheelJoint; - this.localAnchorA = new b2Vec2(); - this.localAnchorB = new b2Vec2(); - this.localAxisA = new b2Vec2(1, 0); - this.enableMotor = false; - this.maxMotorTorque = 0; - this.motorSpeed = 0; - this.frequencyHz = 2; - this.dampingRatio = 0.7; - Object.seal(this) + if (this.m_enableMotor) { + this.m_motorMass = iA + iB; + if (this.m_motorMass > 0) { + this.m_motorMass = 1 / this.m_motorMass + } + } else { + this.m_motorMass = 0; + this.m_motorImpulse = 0 + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + this.m_springImpulse *= data.step.dtRatio; + this.m_motorImpulse *= data.step.dtRatio; + var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(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.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * LA; + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * LB + } else { + this.m_impulse = 0; + this.m_springImpulse = 0; + this.m_motorImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var Cdot = b2Dot_v2_v2(this.m_ax, b2Vec2.Subtract(vB, vA)) + this.m_sBx * wB - this.m_sAx * wA; + var impulse = -this.m_springMass * (Cdot + this.m_bias + this.m_gamma * this.m_springImpulse); + this.m_springImpulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_ax); + var LA = impulse * this.m_sAx; + var LB = impulse * this.m_sBx; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB; + var Cdot = wB - wA - this.m_motorSpeed; + var impulse = -this.m_motorMass * Cdot; + var oldImpulse = this.m_motorImpulse; + var maxImpulse = data.step.dt * this.m_maxMotorTorque; + this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_motorImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Dot_v2_v2(this.m_ay, b2Vec2.Subtract(vB, vA)) + this.m_sBy * wB - this.m_sAy * wA; + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + var P = b2Vec2.Multiply(impulse, this.m_ay); + var LA = impulse * this.m_sAy; + var LB = impulse * this.m_sBy; + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * LA; + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * LB; + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); + var ay = b2Mul_r_v2(qA, this.m_localYAxisA); + var sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), ay); + var sBy = b2Cross_v2_v2(rB, ay); + var C = b2Dot_v2_v2(d, ay); + 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; + var impulse; + if (k != 0) { + impulse = -C / k + } else { + impulse = 0 + } + var P = b2Vec2.Multiply(impulse, ay); + var LA = impulse * sAy; + var LB = impulse * sBy; + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * LA; + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * LB; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return b2Abs(C) <= b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.localAxisA = this.m_localAxisA._serialize(); + obj.enableMotor = this.m_enableMotor; + obj.maxMotorTorque = this.m_maxMotorTorque; + obj.motorSpeed = this.m_motorSpeed; + obj.frequencyHz = this.m_frequencyHz; + obj.dampingRatio = this.m_dampingRatio; + return obj } - b2WheelJointDef.prototype = { - Initialize: function (bA, bB, anchor, axis) { - this.bodyA = bA; - this.bodyB = bB; - this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchor)); - this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchor)); - this.localAxisA.Assign(this.bodyA.GetLocalVector(axis)) - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.localAxisA._deserialize(data.localAxisA); - this.enableMotor = data.enableMotor; - this.maxMotorTorque = data.maxMotorTorque; - this.motorSpeed = data.motorSpeed; - this.frequencyHz = data.frequencyHz; - this.dampingRatio = data.dampingRatio - } - }; - b2WheelJointDef._extend(b2JointDef); +}; +b2WheelJoint._extend(b2Joint); - function b2WheelJoint(def) { - this.parent.call(this, def); - this.m_indexA = 0; - this.m_indexB = 0; - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_localXAxisA = def.localAxisA.Clone(); - this.m_localYAxisA = b2Cross_f_v2(1, this.m_localXAxisA); +function b2GearJointDef() { + this.parent.call(this); + this.type = b2Joint.e_gearJoint; + this.joint1 = null; + this.joint2 = null; + this.ratio = 1; + Object.seal(this) +} +b2GearJointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.joint1 = data.joint1; + this.joint2 = data.joint2; + this.ratio = data.ratio + } +}; +b2GearJointDef._extend(b2JointDef); + +function b2GearJoint(def) { + this.parent.call(this, def); + this.m_joint1 = def.joint1; + this.m_joint2 = def.joint2; + this.m_typeA = this.m_joint1.GetType(); + this.m_typeB = this.m_joint2.GetType(); + var coordinateA, coordinateB; + this.m_bodyC = this.m_joint1.GetBodyA(); + this.m_bodyA = this.m_joint1.GetBodyB(); + 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; + this.m_localAnchorA = new b2Vec2(); + this.m_localAnchorB = new b2Vec2(); + this.m_localAnchorC = new b2Vec2(); + this.m_localAnchorD = new b2Vec2(); + this.m_localAxisC = new b2Vec2(); + this.m_localAxisD = new b2Vec2(); + if (this.m_typeA == b2Joint.e_revoluteJoint) { + var revolute = def.joint1; + this.m_localAnchorC.Assign(revolute.m_localAnchorA); + this.m_localAnchorA.Assign(revolute.m_localAnchorB); + this.m_referenceAngleA = revolute.m_referenceAngle; + this.m_localAxisC.SetZero(); + coordinateA = aA - aC - this.m_referenceAngleA + } else { + var prismatic = def.joint1; + this.m_localAnchorC.Assign(prismatic.m_localAnchorA); + this.m_localAnchorA.Assign(prismatic.m_localAnchorB); + this.m_referenceAngleA = prismatic.m_referenceAngle; + this.m_localAxisC.Assign(prismatic.m_localXAxisA); + var pC = this.m_localAnchorC; + var pA = b2MulT_r_v2(xfC.q, b2Vec2.Add(b2Mul_r_v2(xfA.q, this.m_localAnchorA), b2Vec2.Subtract(xfA.p, xfC.p))); + coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) + } + this.m_bodyD = this.m_joint2.GetBodyA(); + this.m_bodyB = this.m_joint2.GetBodyB(); + 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_typeB == b2Joint.e_revoluteJoint) { + var revolute = def.joint2; + this.m_localAnchorD.Assign(revolute.m_localAnchorA); + this.m_localAnchorB.Assign(revolute.m_localAnchorB); + this.m_referenceAngleB = revolute.m_referenceAngle; + this.m_localAxisD.SetZero(); + coordinateB = aB - aD - this.m_referenceAngleB + } else { + var prismatic = def.joint2; + this.m_localAnchorD.Assign(prismatic.m_localAnchorA); + this.m_localAnchorB.Assign(prismatic.m_localAnchorB); + this.m_referenceAngleB = prismatic.m_referenceAngle; + this.m_localAxisD.Assign(prismatic.m_localXAxisA); + var pD = this.m_localAnchorD; + var pB = b2MulT_r_v2(xfD.q, b2Vec2.Add(b2Mul_r_v2(xfB.q, this.m_localAnchorB), b2Vec2.Subtract(xfB.p, xfD.p))); + coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) + } + this.m_ratio = def.ratio; + this.m_constant = coordinateA + this.m_ratio * coordinateB; + this.m_impulse = 0; + this.m_indexA = this.m_indexB = this.m_indexC = this.m_indexD = 0; + this.m_lcA = new b2Vec2(); + this.m_lcB = new b2Vec2(); + this.m_lcC = new b2Vec2(); + this.m_lcD = new b2Vec2(); + this.m_mA = this.m_mB = this.m_mC = this.m_mD = 0; + this.m_iA = this.m_iB = this.m_iC = this.m_iD = 0; + this.m_JvAC = new b2Vec2(), this.m_JvBD = new b2Vec2(); + this.m_JwA = this.m_JwB = this.m_JwC = this.m_JwD = 0; + this.m_mass = 0 +} +b2GearJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = b2Vec2.Multiply(this.m_impulse, this.m_JvAC); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + var L = this.m_impulse * this.m_JwA; + return inv_dt * L + }, + GetJoint1: function () { + return this.m_joint1 + }, + GetJoint2: function () { + return this.m_joint2 + }, + SetRatio: function (ratio) { + this.m_ratio = ratio + }, + GetRatio: function () { + return this.m_ratio + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_indexC = this.m_bodyC.m_islandIndex; + this.m_indexD = this.m_bodyD.m_islandIndex; + this.m_lcA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_lcB.Assign(this.m_bodyB.m_sweep.localCenter); + this.m_lcC.Assign(this.m_bodyC.m_sweep.localCenter); + this.m_lcD.Assign(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 = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var aC = data.positions[this.m_indexC].a; + var vC = data.velocities[this.m_indexC].v.Clone(); + var wC = data.velocities[this.m_indexC].w; + var aD = data.positions[this.m_indexD].a; + var vD = data.velocities[this.m_indexD].v.Clone(); + var wD = data.velocities[this.m_indexD].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB), + qC = new b2Rot(aC), + qD = new b2Rot(aD); this.m_mass = 0; - this.m_impulse = 0; - this.m_motorMass = 0; - this.m_motorImpulse = 0; - this.m_springMass = 0; - this.m_springImpulse = 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; - this.m_gamma = 0; - this.m_ax = new b2Vec2(); - this.m_ay = new b2Vec2(); - this.m_sAx = this.m_sBx = 0; - this.m_sAy = this.m_sBy = 0 - } - b2WheelJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - return b2Vec2.Multiply(inv_dt, b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(this.m_springImpulse, this.m_ax))) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * this.m_motorImpulse - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - GetLocalAxisA: function () { - return this.m_localXAxisA - }, - GetJointTranslation: function () { - var bA = this.m_bodyA; - var bB = this.m_bodyB; - var pA = bA.GetWorldPoint(this.m_localAnchorA); - var pB = bB.GetWorldPoint(this.m_localAnchorB); - var d = b2Vec2.Subtract(pB, pA); - var axis = bA.GetWorldVector(this.m_localXAxisA); - var translation = b2Dot_v2_v2(d, axis); - return translation - }, - GetJointSpeed: function () { - var wA = this.m_bodyA.m_angularVelocity; - var wB = this.m_bodyB.m_angularVelocity; - return wB - wA - }, - IsMotorEnabled: function () { - return this.m_enableMotor - }, - EnableMotor: function (flag) { - this.m_bodyA.SetAwake(true); - this.m_bodyB.SetAwake(true); - this.m_enableMotor = flag - }, - SetMotorSpeed: function (speed) { - this.m_bodyA.SetAwake(true); - this.m_bodyB.SetAwake(true); - this.m_motorSpeed = speed - }, - GetMotorSpeed: function () { - return this.m_motorSpeed - }, - SetMaxMotorTorque: function (torque) { - this.m_bodyA.SetAwake(true); - this.m_bodyB.SetAwake(true); - this.m_maxMotorTorque = torque - }, - GetMaxMotorTorque: function () { - return this.m_maxMotorTorque - }, - GetMotorTorque: function (inv_dt) { - return inv_dt * this.m_motorImpulse - }, - SetSpringFrequencyHz: function (hz) { - this.m_frequencyHz = hz - }, - GetSpringFrequencyHz: function () { - return this.m_frequencyHz - }, - SetSpringDampingRatio: function (ratio) { - this.m_dampingRatio = ratio - }, - GetSpringDampingRatio: function () { - return this.m_dampingRatio - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var d = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - this.m_ay.Assign(b2Mul_r_v2(qA, this.m_localYAxisA)); - this.m_sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ay); - this.m_sBy = b2Cross_v2_v2(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) { - this.m_mass = 1 / this.m_mass - } - this.m_springMass = 0; - this.m_bias = 0; - this.m_gamma = 0; - if (this.m_frequencyHz > 0) { - this.m_ax.Assign(b2Mul_r_v2(qA, this.m_localXAxisA)); - this.m_sAx = b2Cross_v2_v2(b2Vec2.Add(d, rA), this.m_ax); - this.m_sBx = b2Cross_v2_v2(rB, this.m_ax); - var invMass = mA + mB + iA * this.m_sAx * this.m_sAx + iB * this.m_sBx * this.m_sBx; - if (invMass > 0) { - this.m_springMass = 1 / invMass; - var C = b2Dot_v2_v2(d, this.m_ax); - var omega = 2 * b2_pi * this.m_frequencyHz; - var d = 2 * this.m_springMass * this.m_dampingRatio * omega; - var k = this.m_springMass * omega * omega; - var h = data.step.dt; - this.m_gamma = h * (d + h * k); - if (this.m_gamma > 0) { - this.m_gamma = 1 / this.m_gamma - } - this.m_bias = C * h * k * this.m_gamma; - this.m_springMass = invMass + this.m_gamma; - if (this.m_springMass > 0) { - this.m_springMass = 1 / this.m_springMass - } - } - } else { - this.m_springImpulse = 0 - } - if (this.m_enableMotor) { - this.m_motorMass = iA + iB; - if (this.m_motorMass > 0) { - this.m_motorMass = 1 / this.m_motorMass - } - } else { - this.m_motorMass = 0; - this.m_motorImpulse = 0 - } - if (data.step.warmStarting) { - this.m_impulse *= data.step.dtRatio; - this.m_springImpulse *= data.step.dtRatio; - this.m_motorImpulse *= data.step.dtRatio; - var P = b2Vec2.Add(b2Vec2.Multiply(this.m_impulse, this.m_ay), b2Vec2.Multiply(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.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); - wA -= this.m_invIA * LA; - vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - wB += this.m_invIB * LB - } else { - this.m_impulse = 0; - this.m_springImpulse = 0; - this.m_motorImpulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var Cdot = b2Dot_v2_v2(this.m_ax, b2Vec2.Subtract(vB, vA)) + this.m_sBx * wB - this.m_sAx * wA; - var impulse = -this.m_springMass * (Cdot + this.m_bias + this.m_gamma * this.m_springImpulse); - this.m_springImpulse += impulse; - var P = b2Vec2.Multiply(impulse, this.m_ax); - var LA = impulse * this.m_sAx; - var LB = impulse * this.m_sBx; - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * LA; - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * LB; - var Cdot = wB - wA - this.m_motorSpeed; - var impulse = -this.m_motorMass * Cdot; - var oldImpulse = this.m_motorImpulse; - var maxImpulse = data.step.dt * this.m_maxMotorTorque; - this.m_motorImpulse = b2Clamp(this.m_motorImpulse + impulse, -maxImpulse, maxImpulse); - impulse = this.m_motorImpulse - oldImpulse; - wA -= iA * impulse; - wB += iB * impulse; - var Cdot = b2Dot_v2_v2(this.m_ay, b2Vec2.Subtract(vB, vA)) + this.m_sBy * wB - this.m_sAy * wA; - var impulse = -this.m_mass * Cdot; - this.m_impulse += impulse; - var P = b2Vec2.Multiply(impulse, this.m_ay); - var LA = impulse * this.m_sAy; - var LB = impulse * this.m_sBy; - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * LA; - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * LB; - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var d = b2Vec2.Add(b2Vec2.Subtract(cB, cA), b2Vec2.Subtract(rB, rA)); - var ay = b2Mul_r_v2(qA, this.m_localYAxisA); - var sAy = b2Cross_v2_v2(b2Vec2.Add(d, rA), ay); - var sBy = b2Cross_v2_v2(rB, ay); - var C = b2Dot_v2_v2(d, ay); - 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; - var impulse; - if (k != 0) { - impulse = -C / k - } else { - impulse = 0 - } - var P = b2Vec2.Multiply(impulse, ay); - var LA = impulse * sAy; - var LB = impulse * sBy; - cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); - aA -= this.m_invIA * LA; - cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - aB += this.m_invIB * LB; - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return b2Abs(C) <= b2_linearSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.localAxisA = this.m_localAxisA._serialize(); - obj.enableMotor = this.m_enableMotor; - obj.maxMotorTorque = this.m_maxMotorTorque; - obj.motorSpeed = this.m_motorSpeed; - obj.frequencyHz = this.m_frequencyHz; - obj.dampingRatio = this.m_dampingRatio; - return obj - } - }; - b2WheelJoint._extend(b2Joint); - - function b2GearJointDef() { - this.parent.call(this); - this.type = b2Joint.e_gearJoint; - this.joint1 = null; - this.joint2 = null; - this.ratio = 1; - Object.seal(this) - } - b2GearJointDef.prototype = { - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.joint1 = data.joint1; - this.joint2 = data.joint2; - this.ratio = data.ratio - } - }; - b2GearJointDef._extend(b2JointDef); - - function b2GearJoint(def) { - this.parent.call(this, def); - this.m_joint1 = def.joint1; - this.m_joint2 = def.joint2; - this.m_typeA = this.m_joint1.GetType(); - this.m_typeB = this.m_joint2.GetType(); - var coordinateA, coordinateB; - this.m_bodyC = this.m_joint1.GetBodyA(); - this.m_bodyA = this.m_joint1.GetBodyB(); - 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; - this.m_localAnchorA = new b2Vec2(); - this.m_localAnchorB = new b2Vec2(); - this.m_localAnchorC = new b2Vec2(); - this.m_localAnchorD = new b2Vec2(); - this.m_localAxisC = new b2Vec2(); - this.m_localAxisD = new b2Vec2(); if (this.m_typeA == b2Joint.e_revoluteJoint) { - var revolute = def.joint1; - this.m_localAnchorC.Assign(revolute.m_localAnchorA); - this.m_localAnchorA.Assign(revolute.m_localAnchorB); - this.m_referenceAngleA = revolute.m_referenceAngle; - this.m_localAxisC.SetZero(); + this.m_JvAC.SetZero(); + this.m_JwA = 1; + this.m_JwC = 1; + this.m_mass += this.m_iA + this.m_iC + } else { + var u = b2Mul_r_v2(qC, this.m_localAxisC); + var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); + this.m_JvAC.Assign(u); + this.m_JwC = b2Cross_v2_v2(rC, u); + this.m_JwA = b2Cross_v2_v2(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_typeB == b2Joint.e_revoluteJoint) { + this.m_JvBD.SetZero(); + 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 = b2Mul_r_v2(qD, this.m_localAxisD); + var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); + this.m_JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); + this.m_JwD = this.m_ratio * b2Cross_v2_v2(rD, u); + this.m_JwB = this.m_ratio * b2Cross_v2_v2(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 + } + this.m_mass = this.m_mass > 0 ? 1 / this.m_mass : 0; + if (data.step.warmStarting) { + vA.Add(b2Vec2.Multiply((this.m_mA * this.m_impulse), this.m_JvAC)); + wA += this.m_iA * this.m_impulse * this.m_JwA; + vB.Add(b2Vec2.Multiply((this.m_mB * this.m_impulse), this.m_JvBD)); + wB += this.m_iB * this.m_impulse * this.m_JwB; + vC.Subtract(b2Vec2.Multiply((this.m_mC * this.m_impulse), this.m_JvAC)); + wC -= this.m_iC * this.m_impulse * this.m_JwC; + vD.Subtract(b2Vec2.Multiply((this.m_mD * this.m_impulse), this.m_JvBD)); + wD -= this.m_iD * this.m_impulse * this.m_JwD + } else { + this.m_impulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB; + data.velocities[this.m_indexC].v.Assign(vC); + data.velocities[this.m_indexC].w = wC; + data.velocities[this.m_indexD].v.Assign(vD); + data.velocities[this.m_indexD].w = wD + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vC = data.velocities[this.m_indexC].v.Clone(); + var wC = data.velocities[this.m_indexC].w; + var vD = data.velocities[this.m_indexD].v.Clone(); + var wD = data.velocities[this.m_indexD].w; + var Cdot = b2Dot_v2_v2(this.m_JvAC, b2Vec2.Subtract(vA, vC)) + b2Dot_v2_v2(this.m_JvBD, b2Vec2.Subtract(vB, vD)); + Cdot += (this.m_JwA * wA - this.m_JwC * wC) + (this.m_JwB * wB - this.m_JwD * wD); + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + vA.Add(b2Vec2.Multiply((this.m_mA * impulse), this.m_JvAC)); + wA += this.m_iA * impulse * this.m_JwA; + vB.Add(b2Vec2.Multiply((this.m_mB * impulse), this.m_JvBD)); + wB += this.m_iB * impulse * this.m_JwB; + vC.Subtract(b2Vec2.Multiply((this.m_mC * impulse), this.m_JvAC)); + wC -= this.m_iC * impulse * this.m_JwC; + vD.Subtract(b2Vec2.Multiply((this.m_mD * impulse), this.m_JvBD)); + wD -= this.m_iD * impulse * this.m_JwD; + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB; + data.velocities[this.m_indexC].v.Assign(vC); + data.velocities[this.m_indexC].w = wC; + data.velocities[this.m_indexD].v.Assign(vD); + data.velocities[this.m_indexD].w = wD + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var cC = data.positions[this.m_indexC].c.Clone(); + var aC = data.positions[this.m_indexC].a; + var cD = data.positions[this.m_indexD].c.Clone(); + var aD = data.positions[this.m_indexD].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB), + qC = new b2Rot(aC), + qD = new b2Rot(aD); + var linearError = 0; + var coordinateA, coordinateB; + var JvAC = new b2Vec2(), + JvBD = new b2Vec2(); + var JwA, JwB, JwC, JwD; + var mass = 0; + if (this.m_typeA == b2Joint.e_revoluteJoint) { + JvAC.SetZero(); + JwA = 1; + JwC = 1; + mass += this.m_iA + this.m_iC; coordinateA = aA - aC - this.m_referenceAngleA } else { - var prismatic = def.joint1; - this.m_localAnchorC.Assign(prismatic.m_localAnchorA); - this.m_localAnchorA.Assign(prismatic.m_localAnchorB); - this.m_referenceAngleA = prismatic.m_referenceAngle; - this.m_localAxisC.Assign(prismatic.m_localXAxisA); - var pC = this.m_localAnchorC; - var pA = b2MulT_r_v2(xfC.q, b2Vec2.Add(b2Mul_r_v2(xfA.q, this.m_localAnchorA), b2Vec2.Subtract(xfA.p, xfC.p))); + var u = b2Mul_r_v2(qC, this.m_localAxisC); + var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); + JvAC.Assign(u); + JwC = b2Cross_v2_v2(rC, u); + JwA = b2Cross_v2_v2(rA, u); + mass += this.m_mC + this.m_mA + this.m_iC * JwC * JwC + this.m_iA * JwA * JwA; + var pC = b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC); + var pA = b2MulT_r_v2(qC, b2Vec2.Add(rA, b2Vec2.Subtract(cA, cC))); coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) } - this.m_bodyD = this.m_joint2.GetBodyA(); - this.m_bodyB = this.m_joint2.GetBodyB(); - 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_typeB == b2Joint.e_revoluteJoint) { - var revolute = def.joint2; - this.m_localAnchorD.Assign(revolute.m_localAnchorA); - this.m_localAnchorB.Assign(revolute.m_localAnchorB); - this.m_referenceAngleB = revolute.m_referenceAngle; - this.m_localAxisD.SetZero(); + JvBD.SetZero(); + 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 prismatic = def.joint2; - this.m_localAnchorD.Assign(prismatic.m_localAnchorA); - this.m_localAnchorB.Assign(prismatic.m_localAnchorB); - this.m_referenceAngleB = prismatic.m_referenceAngle; - this.m_localAxisD.Assign(prismatic.m_localXAxisA); - var pD = this.m_localAnchorD; - var pB = b2MulT_r_v2(xfD.q, b2Vec2.Add(b2Mul_r_v2(xfB.q, this.m_localAnchorB), b2Vec2.Subtract(xfB.p, xfD.p))); + var u = b2Mul_r_v2(qD, this.m_localAxisD); + var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); + JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); + JwD = this.m_ratio * b2Cross_v2_v2(rD, u); + JwB = this.m_ratio * b2Cross_v2_v2(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 = b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD); + var pB = b2MulT_r_v2(qD, b2Vec2.Add(rB, b2Vec2.Subtract(cB, cD))); coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) } - this.m_ratio = def.ratio; - this.m_constant = coordinateA + this.m_ratio * coordinateB; - this.m_impulse = 0; - this.m_indexA = this.m_indexB = this.m_indexC = this.m_indexD = 0; - this.m_lcA = new b2Vec2(); - this.m_lcB = new b2Vec2(); - this.m_lcC = new b2Vec2(); - this.m_lcD = new b2Vec2(); - this.m_mA = this.m_mB = this.m_mC = this.m_mD = 0; - this.m_iA = this.m_iB = this.m_iC = this.m_iD = 0; - this.m_JvAC = new b2Vec2(), this.m_JvBD = new b2Vec2(); - this.m_JwA = this.m_JwB = this.m_JwC = this.m_JwD = 0; - this.m_mass = 0 - } - b2GearJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - var P = b2Vec2.Multiply(this.m_impulse, this.m_JvAC); - return b2Vec2.Multiply(inv_dt, P) - }, - GetReactionTorque: function (inv_dt) { - var L = this.m_impulse * this.m_JwA; - return inv_dt * L - }, - GetJoint1: function () { - return this.m_joint1 - }, - GetJoint2: function () { - return this.m_joint2 - }, - SetRatio: function (ratio) { - this.m_ratio = ratio - }, - GetRatio: function () { - return this.m_ratio - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_indexC = this.m_bodyC.m_islandIndex; - this.m_indexD = this.m_bodyD.m_islandIndex; - this.m_lcA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_lcB.Assign(this.m_bodyB.m_sweep.localCenter); - this.m_lcC.Assign(this.m_bodyC.m_sweep.localCenter); - this.m_lcD.Assign(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 = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var aC = data.positions[this.m_indexC].a; - var vC = data.velocities[this.m_indexC].v.Clone(); - var wC = data.velocities[this.m_indexC].w; - var aD = data.positions[this.m_indexD].a; - var vD = data.velocities[this.m_indexD].v.Clone(); - var wD = data.velocities[this.m_indexD].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB), - qC = new b2Rot(aC), - qD = new b2Rot(aD); - this.m_mass = 0; - if (this.m_typeA == b2Joint.e_revoluteJoint) { - this.m_JvAC.SetZero(); - this.m_JwA = 1; - this.m_JwC = 1; - this.m_mass += this.m_iA + this.m_iC - } else { - var u = b2Mul_r_v2(qC, this.m_localAxisC); - var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); - this.m_JvAC.Assign(u); - this.m_JwC = b2Cross_v2_v2(rC, u); - this.m_JwA = b2Cross_v2_v2(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_typeB == b2Joint.e_revoluteJoint) { - this.m_JvBD.SetZero(); - 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 = b2Mul_r_v2(qD, this.m_localAxisD); - var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); - this.m_JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); - this.m_JwD = this.m_ratio * b2Cross_v2_v2(rD, u); - this.m_JwB = this.m_ratio * b2Cross_v2_v2(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 - } - this.m_mass = this.m_mass > 0 ? 1 / this.m_mass : 0; - if (data.step.warmStarting) { - vA.Add(b2Vec2.Multiply((this.m_mA * this.m_impulse), this.m_JvAC)); - wA += this.m_iA * this.m_impulse * this.m_JwA; - vB.Add(b2Vec2.Multiply((this.m_mB * this.m_impulse), this.m_JvBD)); - wB += this.m_iB * this.m_impulse * this.m_JwB; - vC.Subtract(b2Vec2.Multiply((this.m_mC * this.m_impulse), this.m_JvAC)); - wC -= this.m_iC * this.m_impulse * this.m_JwC; - vD.Subtract(b2Vec2.Multiply((this.m_mD * this.m_impulse), this.m_JvBD)); - wD -= this.m_iD * this.m_impulse * this.m_JwD - } else { - this.m_impulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB; - data.velocities[this.m_indexC].v.Assign(vC); - data.velocities[this.m_indexC].w = wC; - data.velocities[this.m_indexD].v.Assign(vD); - data.velocities[this.m_indexD].w = wD - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var vC = data.velocities[this.m_indexC].v.Clone(); - var wC = data.velocities[this.m_indexC].w; - var vD = data.velocities[this.m_indexD].v.Clone(); - var wD = data.velocities[this.m_indexD].w; - var Cdot = b2Dot_v2_v2(this.m_JvAC, b2Vec2.Subtract(vA, vC)) + b2Dot_v2_v2(this.m_JvBD, b2Vec2.Subtract(vB, vD)); - Cdot += (this.m_JwA * wA - this.m_JwC * wC) + (this.m_JwB * wB - this.m_JwD * wD); - var impulse = -this.m_mass * Cdot; - this.m_impulse += impulse; - vA.Add(b2Vec2.Multiply((this.m_mA * impulse), this.m_JvAC)); - wA += this.m_iA * impulse * this.m_JwA; - vB.Add(b2Vec2.Multiply((this.m_mB * impulse), this.m_JvBD)); - wB += this.m_iB * impulse * this.m_JwB; - vC.Subtract(b2Vec2.Multiply((this.m_mC * impulse), this.m_JvAC)); - wC -= this.m_iC * impulse * this.m_JwC; - vD.Subtract(b2Vec2.Multiply((this.m_mD * impulse), this.m_JvBD)); - wD -= this.m_iD * impulse * this.m_JwD; - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB; - data.velocities[this.m_indexC].v.Assign(vC); - data.velocities[this.m_indexC].w = wC; - data.velocities[this.m_indexD].v.Assign(vD); - data.velocities[this.m_indexD].w = wD - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var cC = data.positions[this.m_indexC].c.Clone(); - var aC = data.positions[this.m_indexC].a; - var cD = data.positions[this.m_indexD].c.Clone(); - var aD = data.positions[this.m_indexD].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB), - qC = new b2Rot(aC), - qD = new b2Rot(aD); - var linearError = 0; - var coordinateA, coordinateB; - var JvAC = new b2Vec2(), - JvBD = new b2Vec2(); - var JwA, JwB, JwC, JwD; - var mass = 0; - if (this.m_typeA == b2Joint.e_revoluteJoint) { - JvAC.SetZero(); - JwA = 1; - JwC = 1; - mass += this.m_iA + this.m_iC; - coordinateA = aA - aC - this.m_referenceAngleA - } else { - var u = b2Mul_r_v2(qC, this.m_localAxisC); - var rC = b2Mul_r_v2(qC, b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC)); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_lcA)); - JvAC.Assign(u); - JwC = b2Cross_v2_v2(rC, u); - JwA = b2Cross_v2_v2(rA, u); - mass += this.m_mC + this.m_mA + this.m_iC * JwC * JwC + this.m_iA * JwA * JwA; - var pC = b2Vec2.Subtract(this.m_localAnchorC, this.m_lcC); - var pA = b2MulT_r_v2(qC, b2Vec2.Add(rA, b2Vec2.Subtract(cA, cC))); - coordinateA = b2Dot_v2_v2(b2Vec2.Subtract(pA, pC), this.m_localAxisC) - } - if (this.m_typeB == b2Joint.e_revoluteJoint) { - JvBD.SetZero(); - 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 = b2Mul_r_v2(qD, this.m_localAxisD); - var rD = b2Mul_r_v2(qD, b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_lcB)); - JvBD.Assign(b2Vec2.Multiply(this.m_ratio, u)); - JwD = this.m_ratio * b2Cross_v2_v2(rD, u); - JwB = this.m_ratio * b2Cross_v2_v2(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 = b2Vec2.Subtract(this.m_localAnchorD, this.m_lcD); - var pB = b2MulT_r_v2(qD, b2Vec2.Add(rB, b2Vec2.Subtract(cB, cD))); - coordinateB = b2Dot_v2_v2(b2Vec2.Subtract(pB, pD), this.m_localAxisD) - } - var C = (coordinateA + this.m_ratio * coordinateB) - this.m_constant; - var impulse = 0; - if (mass > 0) { - impulse = -C / mass - } - cA.Add(b2Vec2.Multiply(this.m_mA, b2Vec2.Multiply(impulse, JvAC))); - aA += this.m_iA * impulse * JwA; - cB.Add(b2Vec2.Multiply(this.m_mB, b2Vec2.Multiply(impulse, JvBD))); - aB += this.m_iB * impulse * JwB; - cC.Subtract(b2Vec2.Multiply(this.m_mC, b2Vec2.Multiply(impulse, JvAC))); - aC -= this.m_iC * impulse * JwC; - cD.Subtract(b2Vec2.Multiply(this.m_mD, b2Vec2.Multiply(impulse, JvBD))); - aD -= this.m_iD * impulse * JwD; - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - data.positions[this.m_indexC].c.Assign(cC); - data.positions[this.m_indexC].a = aC; - data.positions[this.m_indexD].c.Assign(cD); - data.positions[this.m_indexD].a = aD; - return linearError < b2_linearSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.joint1 = this.m_joint1.__temp_joint_id; - obj.joint2 = this.m_joint2.__temp_joint_id; - obj.ratio = this.m_ratio; - return obj + var C = (coordinateA + this.m_ratio * coordinateB) - this.m_constant; + var impulse = 0; + if (mass > 0) { + impulse = -C / mass } - }; - b2GearJoint._extend(b2Joint); - - function b2MotorJointDef() { - this.parent.call(this); - this.type = b2Joint.e_motorJoint; - this.linearOffset = new b2Vec2(); - this.angularOffset = 0; - this.maxForce = 1; - this.maxTorque = 1; - this.correctionFactor = 0.3; - Object.seal(this) + cA.Add(b2Vec2.Multiply(this.m_mA, b2Vec2.Multiply(impulse, JvAC))); + aA += this.m_iA * impulse * JwA; + cB.Add(b2Vec2.Multiply(this.m_mB, b2Vec2.Multiply(impulse, JvBD))); + aB += this.m_iB * impulse * JwB; + cC.Subtract(b2Vec2.Multiply(this.m_mC, b2Vec2.Multiply(impulse, JvAC))); + aC -= this.m_iC * impulse * JwC; + cD.Subtract(b2Vec2.Multiply(this.m_mD, b2Vec2.Multiply(impulse, JvBD))); + aD -= this.m_iD * impulse * JwD; + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + data.positions[this.m_indexC].c.Assign(cC); + data.positions[this.m_indexC].a = aC; + data.positions[this.m_indexD].c.Assign(cD); + data.positions[this.m_indexD].a = aD; + return linearError < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.joint1 = this.m_joint1.__temp_joint_id; + obj.joint2 = this.m_joint2.__temp_joint_id; + obj.ratio = this.m_ratio; + return obj } - b2MotorJointDef.prototype = { - Initialize: function (bA, bB) { - this.bodyA = bA; - this.bodyB = bB; - var xB = this.bodyB.GetPosition(); - this.linearOffset.Assign(this.bodyA.GetLocalPoint(xB)); - var angleA = this.bodyA.GetAngle(); - var angleB = this.bodyB.GetAngle(); - this.angularOffset = angleB - angleA - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.linearOffset._deserialize(data.linearOffset); - this.angularOffset = data.angularOffset; - this.maxForce = data.maxForce; - this.maxTorque = data.maxTorque; - this.correctionFactor = data.correctionFactor +}; +b2GearJoint._extend(b2Joint); + +function b2MotorJointDef() { + this.parent.call(this); + this.type = b2Joint.e_motorJoint; + this.linearOffset = new b2Vec2(); + this.angularOffset = 0; + this.maxForce = 1; + this.maxTorque = 1; + this.correctionFactor = 0.3; + Object.seal(this) +} +b2MotorJointDef.prototype = { + Initialize: function (bA, bB) { + this.bodyA = bA; + this.bodyB = bB; + var xB = this.bodyB.GetPosition(); + this.linearOffset.Assign(this.bodyA.GetLocalPoint(xB)); + var angleA = this.bodyA.GetAngle(); + var angleB = this.bodyB.GetAngle(); + this.angularOffset = angleB - angleA + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.linearOffset._deserialize(data.linearOffset); + this.angularOffset = data.angularOffset; + this.maxForce = data.maxForce; + this.maxTorque = data.maxTorque; + this.correctionFactor = data.correctionFactor + } +}; +b2MotorJointDef._extend(b2JointDef); + +function b2MotorJoint(def) { + this.parent.call(this, def); + this.m_linearOffset = def.linearOffset.Clone(); + this.m_angularOffset = def.angularOffset; + this.m_linearImpulse = new b2Vec2(); + this.m_angularImpulse = 0; + this.m_maxForce = def.maxForce; + this.m_maxTorque = def.maxTorque; + this.m_correctionFactor = def.correctionFactor; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_linearError = new b2Vec2(); + this.m_angularError = 0; + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_linearMass = new b2Mat22(); + this.m_angularMass = 0 +} +b2MotorJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetPosition() + }, + GetAnchorB: function () { + return this.m_bodyB.GetPosition() + }, + GetReactionForce: function (inv_dt) { + return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) + }, + GetReactionTorque: function (inv_dt) { + return inv_dt * this.m_angularImpulse + }, + 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.Assign(linearOffset) } - }; - b2MotorJointDef._extend(b2JointDef); - - function b2MotorJoint(def) { - this.parent.call(this, def); - this.m_linearOffset = def.linearOffset.Clone(); - this.m_angularOffset = def.angularOffset; - this.m_linearImpulse = new b2Vec2(); - this.m_angularImpulse = 0; - this.m_maxForce = def.maxForce; - this.m_maxTorque = def.maxTorque; - this.m_correctionFactor = def.correctionFactor; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_linearError = new b2Vec2(); - this.m_angularError = 0; - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_linearMass = new b2Mat22(); - this.m_angularMass = 0 - } - b2MotorJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetPosition() - }, - GetAnchorB: function () { - return this.m_bodyB.GetPosition() - }, - GetReactionForce: function (inv_dt) { - return b2Vec2.Multiply(inv_dt, this.m_linearImpulse) - }, - GetReactionTorque: function (inv_dt) { - return inv_dt * this.m_angularImpulse - }, - 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.Assign(linearOffset) - } - }, - GetLinearOffset: function () { - return this.m_linearOffset - }, - SetAngularOffset: function (angularOffset) { - if (angularOffset != this.m_angularOffset) { - this.m_bodyA.SetAwake(true); - this.m_bodyB.SetAwake(true); - this.m_angularOffset = angularOffset - } - }, - GetAngularOffset: function () { - return this.m_angularOffset - }, - SetMaxForce: function (force) { - this.m_maxForce = force - }, - GetMaxForce: function () { - return this.m_maxForce - }, - SetMaxTorque: function (torque) { - this.m_maxTorque = torque - }, - GetMaxTorque: function () { - return this.m_maxTorque - }, - SetCorrectionFactor: function (factor) { - this.m_correctionFactor = factor - }, - GetCorrectionFactor: function () { - return this.m_correctionFactor - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA.Assign(b2Mul_r_v2(qA, this.m_localCenterA.Negate())); - this.m_rB.Assign(b2Mul_r_v2(qB, this.m_localCenterB.Negate())); - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var K = new b2Mat22(); - 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.Assign(K.GetInverse()); - this.m_angularMass = iA + iB; - if (this.m_angularMass > 0) { - this.m_angularMass = 1 / this.m_angularMass - } - this.m_linearError.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA), b2Mul_r_v2(qA, this.m_linearOffset))); - this.m_angularError = aB - aA - this.m_angularOffset; - if (data.step.warmStarting) { - this.m_linearImpulse.Multiply(data.step.dtRatio); - this.m_angularImpulse *= data.step.dtRatio; - var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); - vA.Subtract(b2Vec2.Multiply(mA, P)); - wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); - vB.Add(b2Vec2.Multiply(mB, P)); - wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) - } else { - this.m_linearImpulse.SetZero(); - this.m_angularImpulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var mA = this.m_invMassA, - mB = this.m_invMassB; - var iA = this.m_invIA, - iB = this.m_invIB; - var h = data.step.dt; - var inv_h = data.step.inv_dt; - 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 = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); - impulse = this.m_angularImpulse - oldImpulse; - wA -= iA * impulse; - wB += iB * impulse; - var Cdot = b2Vec2.Add(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)), b2Vec2.Multiply(inv_h, b2Vec2.Multiply(this.m_correctionFactor, this.m_linearError))); - var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); - var oldImpulse = this.m_linearImpulse; - this.m_linearImpulse.Add(impulse); - var maxImpulse = h * this.m_maxForce; - if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { - this.m_linearImpulse.Normalize(); - this.m_linearImpulse.Multiply(maxImpulse) - } - impulse.Assign(b2Vec2.Subtract(this.m_linearImpulse, oldImpulse)); - vA.Subtract(b2Vec2.Multiply(mA, impulse)); - wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); - vB.Add(b2Vec2.Multiply(mB, impulse)); - wB += iB * b2Cross_v2_v2(this.m_rB, impulse); - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - return true - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.linearOffset = this.m_linearOffset._serialize(); - obj.angularOffset = this.m_angularOffset; - obj.maxForce = this.m_maxForce; - obj.maxTorque = this.m_maxTorque; - obj.correctionFactor = this.m_correctionFactor; - return obj + }, + GetLinearOffset: function () { + return this.m_linearOffset + }, + SetAngularOffset: function (angularOffset) { + if (angularOffset != this.m_angularOffset) { + this.m_bodyA.SetAwake(true); + this.m_bodyB.SetAwake(true); + this.m_angularOffset = angularOffset } - }; - b2MotorJoint._extend(b2Joint); - var b2_minPulleyLength = 2; - - function b2PulleyJointDef() { - this.parent.call(this); - this.type = b2Joint.e_pulleyJoint; - this.groundAnchorA = new b2Vec2(-1, 1); - this.groundAnchorB = new b2Vec2(1, 1); - this.localAnchorA = new b2Vec2(-1, 0); - this.localAnchorB = new b2Vec2(1, 0); - this.lengthA = 0; - this.lengthB = 0; - this.ratio = 1; - this.collideConnected = true; - Object.seal(this) - } - b2PulleyJointDef.prototype = { - Initialize: function (bA, bB, groundA, groundB, anchorA, anchorB, r) { - this.bodyA = bA; - this.bodyB = bB; - this.groundAnchorA.Assign(groundA); - this.groundAnchorB.Assign(groundB); - this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchorA)); - this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchorB)); - var dA = b2Vec2.Subtract(anchorA, groundA); - this.lengthA = dA.Length(); - var dB = b2Vec2.Subtract(anchorB, groundB); - this.lengthB = dB.Length(); - this.ratio = r - }, - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.groundAnchorA._deserialize(data.groundAnchorA); - this.groundAnchorB._deserialize(data.groundAnchorB); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.lengthA = data.lengthA; - this.lengthB = data.lengthB; - this.ratio = data.ratio + }, + GetAngularOffset: function () { + return this.m_angularOffset + }, + SetMaxForce: function (force) { + this.m_maxForce = force + }, + GetMaxForce: function () { + return this.m_maxForce + }, + SetMaxTorque: function (torque) { + this.m_maxTorque = torque + }, + GetMaxTorque: function () { + return this.m_maxTorque + }, + SetCorrectionFactor: function (factor) { + this.m_correctionFactor = factor + }, + GetCorrectionFactor: function () { + return this.m_correctionFactor + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, this.m_localCenterA.Negate())); + this.m_rB.Assign(b2Mul_r_v2(qB, this.m_localCenterB.Negate())); + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var K = new b2Mat22(); + 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.Assign(K.GetInverse()); + this.m_angularMass = iA + iB; + if (this.m_angularMass > 0) { + this.m_angularMass = 1 / this.m_angularMass } - }; - b2PulleyJointDef._extend(b2JointDef); - - function b2PulleyJoint(def) { - this.parent.call(this, def); - this.m_indexA = 0; - this.m_indexB = 0; - this.m_uA = new b2Vec2(); - this.m_uB = new b2Vec2(); - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0; - this.m_mass = 0; - this.m_groundAnchorA = def.groundAnchorA.Clone(); - this.m_groundAnchorB = def.groundAnchorB.Clone(); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_lengthA = def.lengthA; - this.m_lengthB = def.lengthB; - this.m_ratio = def.ratio; - this.m_constant = def.lengthA + this.m_ratio * def.lengthB; - this.m_impulse = 0 + this.m_linearError.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA), b2Mul_r_v2(qA, this.m_linearOffset))); + this.m_angularError = aB - aA - this.m_angularOffset; + if (data.step.warmStarting) { + this.m_linearImpulse.Multiply(data.step.dtRatio); + this.m_angularImpulse *= data.step.dtRatio; + var P = new b2Vec2(this.m_linearImpulse.x, this.m_linearImpulse.y); + vA.Subtract(b2Vec2.Multiply(mA, P)); + wA -= iA * (b2Cross_v2_v2(this.m_rA, P) + this.m_angularImpulse); + vB.Add(b2Vec2.Multiply(mB, P)); + wB += iB * (b2Cross_v2_v2(this.m_rB, P) + this.m_angularImpulse) + } else { + this.m_linearImpulse.SetZero(); + this.m_angularImpulse = 0 + } + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var mA = this.m_invMassA, + mB = this.m_invMassB; + var iA = this.m_invIA, + iB = this.m_invIB; + var h = data.step.dt; + var inv_h = data.step.inv_dt; + 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 = b2Clamp(this.m_angularImpulse + impulse, -maxImpulse, maxImpulse); + impulse = this.m_angularImpulse - oldImpulse; + wA -= iA * impulse; + wB += iB * impulse; + var Cdot = b2Vec2.Add(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)), vA), b2Cross_f_v2(wA, this.m_rA)), b2Vec2.Multiply(inv_h, b2Vec2.Multiply(this.m_correctionFactor, this.m_linearError))); + var impulse = b2Mul_m22_v2(this.m_linearMass, Cdot).Negate(); + var oldImpulse = this.m_linearImpulse; + this.m_linearImpulse.Add(impulse); + var maxImpulse = h * this.m_maxForce; + if (this.m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) { + this.m_linearImpulse.Normalize(); + this.m_linearImpulse.Multiply(maxImpulse) + } + impulse.Assign(b2Vec2.Subtract(this.m_linearImpulse, oldImpulse)); + vA.Subtract(b2Vec2.Multiply(mA, impulse)); + wA -= iA * b2Cross_v2_v2(this.m_rA, impulse); + vB.Add(b2Vec2.Multiply(mB, impulse)); + wB += iB * b2Cross_v2_v2(this.m_rB, impulse); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + return true + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.linearOffset = this.m_linearOffset._serialize(); + obj.angularOffset = this.m_angularOffset; + obj.maxForce = this.m_maxForce; + obj.maxTorque = this.m_maxTorque; + obj.correctionFactor = this.m_correctionFactor; + return obj } - b2PulleyJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - var P = b2Vec2.Multiply(this.m_impulse, this.m_uB); - return b2Vec2.Multiply(inv_dt, P) - }, - GetReactionTorque: function (inv_dt) { - return 0 - }, - GetGroundAnchorA: function () { - return this.m_groundAnchorA - }, - GetGroundAnchorB: function () { - return this.m_groundAnchorB - }, - GetLengthA: function () { - return this.m_lengthA - }, - GetLengthB: function () { - return this.m_lengthB - }, - GetRatio: function () { - return this.m_ratio - }, - GetCurrentLengthA: function () { - var p = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); - var s = this.m_groundAnchorA; - var d = b2Vec2.Subtract(p, s); - return d.Length() - }, - GetCurrentLengthB: function () { - var p = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); - var s = this.m_groundAnchorB; - var d = b2Vec2.Subtract(p, s); - return d.Length() - }, - ShiftOrigin: function (newOrigin) { - this.m_groundAnchorA.Subtract(newOrigin); - this.m_groundAnchorB.Subtract(newOrigin) - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); - this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); - this.m_uA.Assign(b2Vec2.Add(cA, b2Vec2.Subtract(this.m_rA, this.m_groundAnchorA))); - this.m_uB.Assign(b2Vec2.Add(cB, b2Vec2.Subtract(this.m_rB, this.m_groundAnchorB))); - var lengthA = this.m_uA.Length(); - var lengthB = this.m_uB.Length(); - if (lengthA > 10 * b2_linearSlop) { - this.m_uA.Multiply(1 / lengthA) - } else { - this.m_uA.SetZero() - } - if (lengthB > 10 * b2_linearSlop) { - this.m_uB.Multiply(1 / lengthB) - } else { - this.m_uB.SetZero() - } - var ruA = b2Cross_v2_v2(this.m_rA, this.m_uA); - var ruB = b2Cross_v2_v2(this.m_rB, this.m_uB); - var mA = this.m_invMassA + this.m_invIA * ruA * ruA; - var mB = this.m_invMassB + this.m_invIB * ruB * ruB; - this.m_mass = mA + this.m_ratio * this.m_ratio * mB; - if (this.m_mass > 0) { - this.m_mass = 1 / this.m_mass - } - if (data.step.warmStarting) { - this.m_impulse *= data.step.dtRatio; - var PA = b2Vec2.Multiply(-(this.m_impulse), this.m_uA); - var PB = b2Vec2.Multiply((-this.m_ratio * this.m_impulse), this.m_uB); - vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); - wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); - vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB) - } else { - this.m_impulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); - var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); - var Cdot = -b2Dot_v2_v2(this.m_uA, vpA) - this.m_ratio * b2Dot_v2_v2(this.m_uB, vpB); - var impulse = -this.m_mass * Cdot; - this.m_impulse += impulse; - var PA = b2Vec2.Multiply(-impulse, this.m_uA); - var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, this.m_uB)); +}; +b2MotorJoint._extend(b2Joint); +var b2_minPulleyLength = 2; + +function b2PulleyJointDef() { + this.parent.call(this); + this.type = b2Joint.e_pulleyJoint; + this.groundAnchorA = new b2Vec2(-1, 1); + this.groundAnchorB = new b2Vec2(1, 1); + this.localAnchorA = new b2Vec2(-1, 0); + this.localAnchorB = new b2Vec2(1, 0); + this.lengthA = 0; + this.lengthB = 0; + this.ratio = 1; + this.collideConnected = true; + Object.seal(this) +} +b2PulleyJointDef.prototype = { + Initialize: function (bA, bB, groundA, groundB, anchorA, anchorB, r) { + this.bodyA = bA; + this.bodyB = bB; + this.groundAnchorA.Assign(groundA); + this.groundAnchorB.Assign(groundB); + this.localAnchorA.Assign(this.bodyA.GetLocalPoint(anchorA)); + this.localAnchorB.Assign(this.bodyB.GetLocalPoint(anchorB)); + var dA = b2Vec2.Subtract(anchorA, groundA); + this.lengthA = dA.Length(); + var dB = b2Vec2.Subtract(anchorB, groundB); + this.lengthB = dB.Length(); + this.ratio = r + }, + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.groundAnchorA._deserialize(data.groundAnchorA); + this.groundAnchorB._deserialize(data.groundAnchorB); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.lengthA = data.lengthA; + this.lengthB = data.lengthB; + this.ratio = data.ratio + } +}; +b2PulleyJointDef._extend(b2JointDef); + +function b2PulleyJoint(def) { + this.parent.call(this, def); + this.m_indexA = 0; + this.m_indexB = 0; + this.m_uA = new b2Vec2(); + this.m_uB = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0; + this.m_mass = 0; + this.m_groundAnchorA = def.groundAnchorA.Clone(); + this.m_groundAnchorB = def.groundAnchorB.Clone(); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_lengthA = def.lengthA; + this.m_lengthB = def.lengthB; + this.m_ratio = def.ratio; + this.m_constant = def.lengthA + this.m_ratio * def.lengthB; + this.m_impulse = 0 +} +b2PulleyJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var P = b2Vec2.Multiply(this.m_impulse, this.m_uB); + return b2Vec2.Multiply(inv_dt, P) + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetGroundAnchorA: function () { + return this.m_groundAnchorA + }, + GetGroundAnchorB: function () { + return this.m_groundAnchorB + }, + GetLengthA: function () { + return this.m_lengthA + }, + GetLengthB: function () { + return this.m_lengthB + }, + GetRatio: function () { + return this.m_ratio + }, + GetCurrentLengthA: function () { + var p = this.m_bodyA.GetWorldPoint(this.m_localAnchorA); + var s = this.m_groundAnchorA; + var d = b2Vec2.Subtract(p, s); + return d.Length() + }, + GetCurrentLengthB: function () { + var p = this.m_bodyB.GetWorldPoint(this.m_localAnchorB); + var s = this.m_groundAnchorB; + var d = b2Vec2.Subtract(p, s); + return d.Length() + }, + ShiftOrigin: function (newOrigin) { + this.m_groundAnchorA.Subtract(newOrigin); + this.m_groundAnchorB.Subtract(newOrigin) + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + this.m_uA.Assign(b2Vec2.Add(cA, b2Vec2.Subtract(this.m_rA, this.m_groundAnchorA))); + this.m_uB.Assign(b2Vec2.Add(cB, b2Vec2.Subtract(this.m_rB, this.m_groundAnchorB))); + var lengthA = this.m_uA.Length(); + var lengthB = this.m_uB.Length(); + if (lengthA > 10 * b2_linearSlop) { + this.m_uA.Multiply(1 / lengthA) + } else { + this.m_uA.SetZero() + } + if (lengthB > 10 * b2_linearSlop) { + this.m_uB.Multiply(1 / lengthB) + } else { + this.m_uB.SetZero() + } + var ruA = b2Cross_v2_v2(this.m_rA, this.m_uA); + var ruB = b2Cross_v2_v2(this.m_rB, this.m_uB); + var mA = this.m_invMassA + this.m_invIA * ruA * ruA; + var mB = this.m_invMassB + this.m_invIB * ruB * ruB; + this.m_mass = mA + this.m_ratio * this.m_ratio * mB; + if (this.m_mass > 0) { + this.m_mass = 1 / this.m_mass + } + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var PA = b2Vec2.Multiply(-(this.m_impulse), this.m_uA); + var PB = b2Vec2.Multiply((-this.m_ratio * this.m_impulse), this.m_uB); vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB); - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var uA = b2Vec2.Add(cA, b2Vec2.Subtract(rA, this.m_groundAnchorA)); - var uB = b2Vec2.Add(cB, b2Vec2.Subtract(rB, this.m_groundAnchorB)); - var lengthA = uA.Length(); - var lengthB = uB.Length(); - if (lengthA > 10 * b2_linearSlop) { - uA.Multiply(1 / lengthA) - } else { - uA.SetZero() - } - if (lengthB > 10 * b2_linearSlop) { - uB.Multiply(1 / lengthB) - } else { - uB.SetZero() - } - var ruA = b2Cross_v2_v2(rA, uA); - var ruB = b2Cross_v2_v2(rB, uB); - var mA = this.m_invMassA + this.m_invIA * ruA * ruA; - var mB = this.m_invMassB + this.m_invIB * ruB * ruB; - var mass = mA + this.m_ratio * this.m_ratio * mB; - if (mass > 0) { - mass = 1 / mass - } - var C = this.m_constant - lengthA - this.m_ratio * lengthB; - var linearError = b2Abs(C); - var impulse = -mass * C; - var PA = b2Vec2.Multiply(-impulse, uA); - var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, uB)); - cA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); - aA += this.m_invIA * b2Cross_v2_v2(rA, PA); - cB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); - aB += this.m_invIB * b2Cross_v2_v2(rB, PB); - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return linearError < b2_linearSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.groundAnchorA = this.m_groundAnchorA._serialize(); - obj.groundAnchorB = this.m_groundAnchorB._serialize(); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.lengthA = this.m_lengthA; - obj.lengthB = this.m_lengthB; - obj.ratio = this.m_ratio; - return obj + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB) + } else { + this.m_impulse = 0 } - }; - b2PulleyJoint._extend(b2Joint); - - function b2RopeJointDef() { - this.parent.call(this); - this.type = b2Joint.e_ropeJoint; - this.localAnchorA = new b2Vec2(-1, 0); - this.localAnchorB = new b2Vec2(1, 0); - this.maxLength = 0; - Object.seal(this) - } - b2RopeJointDef.prototype = { - _deserialize: function (data, bodies, joints) { - this.parent.prototype._deserialize.call(this, data, bodies, joints); - this.localAnchorA._deserialize(data.localAnchorA); - this.localAnchorB._deserialize(data.localAnchorB); - this.maxLength = data.maxLength + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var Cdot = -b2Dot_v2_v2(this.m_uA, vpA) - this.m_ratio * b2Dot_v2_v2(this.m_uB, vpB); + var impulse = -this.m_mass * Cdot; + this.m_impulse += impulse; + var PA = b2Vec2.Multiply(-impulse, this.m_uA); + var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, this.m_uB)); + vA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + wA += this.m_invIA * b2Cross_v2_v2(this.m_rA, PA); + vB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, PB); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var uA = b2Vec2.Add(cA, b2Vec2.Subtract(rA, this.m_groundAnchorA)); + var uB = b2Vec2.Add(cB, b2Vec2.Subtract(rB, this.m_groundAnchorB)); + var lengthA = uA.Length(); + var lengthB = uB.Length(); + if (lengthA > 10 * b2_linearSlop) { + uA.Multiply(1 / lengthA) + } else { + uA.SetZero() } - }; - b2RopeJointDef._extend(b2JointDef); - - function b2RopeJoint(def) { - this.parent.call(this, def); - this.m_localAnchorA = def.localAnchorA.Clone(); - this.m_localAnchorB = def.localAnchorB.Clone(); - this.m_maxLength = def.maxLength; - this.m_mass = 0; - this.m_impulse = 0; - this.m_state = b2Joint.e_inactiveLimit; - this.m_length = 0; - this.m_indexA = 0; - this.m_indexB = 0; - this.m_u = new b2Vec2(); - this.m_rA = new b2Vec2(); - this.m_rB = new b2Vec2(); - this.m_localCenterA = new b2Vec2(); - this.m_localCenterB = new b2Vec2(); - this.m_invMassA = 0; - this.m_invMassB = 0; - this.m_invIA = 0; - this.m_invIB = 0 + if (lengthB > 10 * b2_linearSlop) { + uB.Multiply(1 / lengthB) + } else { + uB.SetZero() + } + var ruA = b2Cross_v2_v2(rA, uA); + var ruB = b2Cross_v2_v2(rB, uB); + var mA = this.m_invMassA + this.m_invIA * ruA * ruA; + var mB = this.m_invMassB + this.m_invIB * ruB * ruB; + var mass = mA + this.m_ratio * this.m_ratio * mB; + if (mass > 0) { + mass = 1 / mass + } + var C = this.m_constant - lengthA - this.m_ratio * lengthB; + var linearError = b2Abs(C); + var impulse = -mass * C; + var PA = b2Vec2.Multiply(-impulse, uA); + var PB = b2Vec2.Multiply(-this.m_ratio, b2Vec2.Multiply(impulse, uB)); + cA.Add(b2Vec2.Multiply(this.m_invMassA, PA)); + aA += this.m_invIA * b2Cross_v2_v2(rA, PA); + cB.Add(b2Vec2.Multiply(this.m_invMassB, PB)); + aB += this.m_invIB * b2Cross_v2_v2(rB, PB); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return linearError < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.groundAnchorA = this.m_groundAnchorA._serialize(); + obj.groundAnchorB = this.m_groundAnchorB._serialize(); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.lengthA = this.m_lengthA; + obj.lengthB = this.m_lengthB; + obj.ratio = this.m_ratio; + return obj } - b2RopeJoint.prototype = { - GetAnchorA: function () { - return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) - }, - GetAnchorB: function () { - return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) - }, - GetReactionForce: function (inv_dt) { - var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); - return F - }, - GetReactionTorque: function (inv_dt) { - return 0 - }, - GetLocalAnchorA: function () { - return this.m_localAnchorA - }, - GetLocalAnchorB: function () { - return this.m_localAnchorB - }, - SetMaxLength: function (length) { - this.m_maxLength = length - }, - GetMaxLength: function () { - return this.m_maxLength - }, - GetLimitState: function () { - return this.m_state - }, - InitVelocityConstraints: function (data) { - this.m_indexA = this.m_bodyA.m_islandIndex; - this.m_indexB = this.m_bodyB.m_islandIndex; - this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); - this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); - this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); - this.m_u.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA)); - this.m_length = this.m_u.Length(); - var C = this.m_length - this.m_maxLength; - if (C > 0) { - this.m_state = b2Joint.e_atUpperLimit - } else { - this.m_state = b2Joint.e_inactiveLimit - } - if (this.m_length > b2_linearSlop) { - this.m_u.Multiply(1 / this.m_length) - } else { - this.m_u.SetZero(); - this.m_mass = 0; - this.m_impulse = 0; - return - } - var crA = b2Cross_v2_v2(this.m_rA, this.m_u); - var crB = b2Cross_v2_v2(this.m_rB, this.m_u); - var invMass = this.m_invMassA + this.m_invIA * crA * crA + this.m_invMassB + this.m_invIB * crB * crB; - this.m_mass = invMass != 0 ? 1 / invMass : 0; - if (data.step.warmStarting) { - this.m_impulse *= data.step.dtRatio; - var P = b2Vec2.Multiply(this.m_impulse, this.m_u); - vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); - wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); - vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) - } else { - this.m_impulse = 0 - } - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolveVelocityConstraints: function (data) { - var vA = data.velocities[this.m_indexA].v.Clone(); - var wA = data.velocities[this.m_indexA].w; - var vB = data.velocities[this.m_indexB].v.Clone(); - var wB = data.velocities[this.m_indexB].w; - var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); - var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); - var C = this.m_length - this.m_maxLength; - var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); - if (C < 0) { - Cdot += data.step.inv_dt * C - } - var impulse = -this.m_mass * Cdot; - var oldImpulse = this.m_impulse; - this.m_impulse = b2Min(0, this.m_impulse + impulse); - impulse = this.m_impulse - oldImpulse; - var P = b2Vec2.Multiply(impulse, this.m_u); +}; +b2PulleyJoint._extend(b2Joint); + +function b2RopeJointDef() { + this.parent.call(this); + this.type = b2Joint.e_ropeJoint; + this.localAnchorA = new b2Vec2(-1, 0); + this.localAnchorB = new b2Vec2(1, 0); + this.maxLength = 0; + Object.seal(this) +} +b2RopeJointDef.prototype = { + _deserialize: function (data, bodies, joints) { + this.parent.prototype._deserialize.call(this, data, bodies, joints); + this.localAnchorA._deserialize(data.localAnchorA); + this.localAnchorB._deserialize(data.localAnchorB); + this.maxLength = data.maxLength + } +}; +b2RopeJointDef._extend(b2JointDef); + +function b2RopeJoint(def) { + this.parent.call(this, def); + this.m_localAnchorA = def.localAnchorA.Clone(); + this.m_localAnchorB = def.localAnchorB.Clone(); + this.m_maxLength = def.maxLength; + this.m_mass = 0; + this.m_impulse = 0; + this.m_state = b2Joint.e_inactiveLimit; + this.m_length = 0; + this.m_indexA = 0; + this.m_indexB = 0; + this.m_u = new b2Vec2(); + this.m_rA = new b2Vec2(); + this.m_rB = new b2Vec2(); + this.m_localCenterA = new b2Vec2(); + this.m_localCenterB = new b2Vec2(); + this.m_invMassA = 0; + this.m_invMassB = 0; + this.m_invIA = 0; + this.m_invIB = 0 +} +b2RopeJoint.prototype = { + GetAnchorA: function () { + return this.m_bodyA.GetWorldPoint(this.m_localAnchorA) + }, + GetAnchorB: function () { + return this.m_bodyB.GetWorldPoint(this.m_localAnchorB) + }, + GetReactionForce: function (inv_dt) { + var F = b2Vec2.Multiply((inv_dt * this.m_impulse), this.m_u); + return F + }, + GetReactionTorque: function (inv_dt) { + return 0 + }, + GetLocalAnchorA: function () { + return this.m_localAnchorA + }, + GetLocalAnchorB: function () { + return this.m_localAnchorB + }, + SetMaxLength: function (length) { + this.m_maxLength = length + }, + GetMaxLength: function () { + return this.m_maxLength + }, + GetLimitState: function () { + return this.m_state + }, + InitVelocityConstraints: function (data) { + this.m_indexA = this.m_bodyA.m_islandIndex; + this.m_indexB = this.m_bodyB.m_islandIndex; + this.m_localCenterA.Assign(this.m_bodyA.m_sweep.localCenter); + this.m_localCenterB.Assign(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 = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + this.m_rA.Assign(b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA))); + this.m_rB.Assign(b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB))); + this.m_u.Assign(b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, this.m_rB), cA), this.m_rA)); + this.m_length = this.m_u.Length(); + var C = this.m_length - this.m_maxLength; + if (C > 0) { + this.m_state = b2Joint.e_atUpperLimit + } else { + this.m_state = b2Joint.e_inactiveLimit + } + if (this.m_length > b2_linearSlop) { + this.m_u.Multiply(1 / this.m_length) + } else { + this.m_u.SetZero(); + this.m_mass = 0; + this.m_impulse = 0; + return + } + var crA = b2Cross_v2_v2(this.m_rA, this.m_u); + var crB = b2Cross_v2_v2(this.m_rB, this.m_u); + var invMass = this.m_invMassA + this.m_invIA * crA * crA + this.m_invMassB + this.m_invIB * crB * crB; + this.m_mass = invMass != 0 ? 1 / invMass : 0; + if (data.step.warmStarting) { + this.m_impulse *= data.step.dtRatio; + var P = b2Vec2.Multiply(this.m_impulse, this.m_u); vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); - data.velocities[this.m_indexA].v.Assign(vA); - data.velocities[this.m_indexA].w = wA; - data.velocities[this.m_indexB].v.Assign(vB); - data.velocities[this.m_indexB].w = wB - }, - SolvePositionConstraints: function (data) { - var cA = data.positions[this.m_indexA].c.Clone(); - var aA = data.positions[this.m_indexA].a; - var cB = data.positions[this.m_indexB].c.Clone(); - var aB = data.positions[this.m_indexB].a; - var qA = new b2Rot(aA), - qB = new b2Rot(aB); - var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); - var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); - var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); - var length = u.Normalize(); - var C = length - this.m_maxLength; - C = b2Clamp(C, 0, b2_maxLinearCorrection); - var impulse = -this.m_mass * C; - var P = b2Vec2.Multiply(impulse, u); - cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); - aA -= this.m_invIA * b2Cross_v2_v2(rA, P); - cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); - aB += this.m_invIB * b2Cross_v2_v2(rB, P); - data.positions[this.m_indexA].c.Assign(cA); - data.positions[this.m_indexA].a = aA; - data.positions[this.m_indexB].c.Assign(cB); - data.positions[this.m_indexB].a = aB; - return length - this.m_maxLength < b2_linearSlop - }, - _serialize: function (out) { - var obj = out || {}; - this.parent.prototype._serialize.call(this, obj); - obj.localAnchorA = this.m_localAnchorA._serialize(); - obj.localAnchorB = this.m_localAnchorB._serialize(); - obj.maxLength = this.m_maxLength; - return obj + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P) + } else { + this.m_impulse = 0 } - }; - b2RopeJoint._extend(b2Joint); - var expf = Math.exp; - - function b2RopeDef() { - this.vertices = null; - this.count = 0; - this.masses = null; - this.gravity = new b2Vec2(); - this.damping = 0.1; - this.k2 = 0.9; - this.k3 = 0.1 + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolveVelocityConstraints: function (data) { + var vA = data.velocities[this.m_indexA].v.Clone(); + var wA = data.velocities[this.m_indexA].w; + var vB = data.velocities[this.m_indexB].v.Clone(); + var wB = data.velocities[this.m_indexB].w; + var vpA = b2Vec2.Add(vA, b2Cross_f_v2(wA, this.m_rA)); + var vpB = b2Vec2.Add(vB, b2Cross_f_v2(wB, this.m_rB)); + var C = this.m_length - this.m_maxLength; + var Cdot = b2Dot_v2_v2(this.m_u, b2Vec2.Subtract(vpB, vpA)); + if (C < 0) { + Cdot += data.step.inv_dt * C + } + var impulse = -this.m_mass * Cdot; + var oldImpulse = this.m_impulse; + this.m_impulse = b2Min(0, this.m_impulse + impulse); + impulse = this.m_impulse - oldImpulse; + var P = b2Vec2.Multiply(impulse, this.m_u); + vA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + wA -= this.m_invIA * b2Cross_v2_v2(this.m_rA, P); + vB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + wB += this.m_invIB * b2Cross_v2_v2(this.m_rB, P); + data.velocities[this.m_indexA].v.Assign(vA); + data.velocities[this.m_indexA].w = wA; + data.velocities[this.m_indexB].v.Assign(vB); + data.velocities[this.m_indexB].w = wB + }, + SolvePositionConstraints: function (data) { + var cA = data.positions[this.m_indexA].c.Clone(); + var aA = data.positions[this.m_indexA].a; + var cB = data.positions[this.m_indexB].c.Clone(); + var aB = data.positions[this.m_indexB].a; + var qA = new b2Rot(aA), + qB = new b2Rot(aB); + var rA = b2Mul_r_v2(qA, b2Vec2.Subtract(this.m_localAnchorA, this.m_localCenterA)); + var rB = b2Mul_r_v2(qB, b2Vec2.Subtract(this.m_localAnchorB, this.m_localCenterB)); + var u = b2Vec2.Subtract(b2Vec2.Subtract(b2Vec2.Add(cB, rB), cA), rA); + var length = u.Normalize(); + var C = length - this.m_maxLength; + C = b2Clamp(C, 0, b2_maxLinearCorrection); + var impulse = -this.m_mass * C; + var P = b2Vec2.Multiply(impulse, u); + cA.Subtract(b2Vec2.Multiply(this.m_invMassA, P)); + aA -= this.m_invIA * b2Cross_v2_v2(rA, P); + cB.Add(b2Vec2.Multiply(this.m_invMassB, P)); + aB += this.m_invIB * b2Cross_v2_v2(rB, P); + data.positions[this.m_indexA].c.Assign(cA); + data.positions[this.m_indexA].a = aA; + data.positions[this.m_indexB].c.Assign(cB); + data.positions[this.m_indexB].a = aB; + return length - this.m_maxLength < b2_linearSlop + }, + _serialize: function (out) { + var obj = out || {}; + this.parent.prototype._serialize.call(this, obj); + obj.localAnchorA = this.m_localAnchorA._serialize(); + obj.localAnchorB = this.m_localAnchorB._serialize(); + obj.maxLength = this.m_maxLength; + return obj } +}; +b2RopeJoint._extend(b2Joint); +var expf = Math.exp; - function b2Rope() { - this.m_count = 0; - this.m_ps = null; - this.m_p0s = null; - this.m_vs = null; - this.m_ims = null; - this.m_Ls = null; - this.m_as = null; - this.m_damping = 0; - this.m_gravity = new b2Vec2(); - this.m_k2 = 1; - this.m_k3 = 0.1 +function b2RopeDef() { + this.vertices = null; + this.count = 0; + this.masses = null; + this.gravity = new b2Vec2(); + this.damping = 0.1; + this.k2 = 0.9; + this.k3 = 0.1 +} + +function b2Rope() { + this.m_count = 0; + this.m_ps = null; + this.m_p0s = null; + this.m_vs = null; + this.m_ims = null; + this.m_Ls = null; + this.m_as = null; + this.m_damping = 0; + this.m_gravity = new b2Vec2(); + this.m_k2 = 1; + this.m_k3 = 0.1 +} +b2Rope.prototype = { + Initialize: function (def) { + this.m_count = def.count; + this.m_ps = new Array(this.m_count); + this.m_p0s = new Array(this.m_count); + this.m_vs = new Array(this.m_count); + this.m_ims = new Array(this.m_count); + for (var i = 0; i < this.m_count; ++i) { + this.m_ps[i] = def.vertices[i].Clone(); + this.m_p0s[i] = def.vertices[i].Clone(); + this.m_vs[i] = new b2Vec2(); + var m = def.masses[i]; + if (m > 0) { + this.m_ims[i] = 1 / m + } else { + this.m_ims[i] = 0 + } + } + var count2 = this.m_count - 1; + var count3 = this.m_count - 2; + this.m_Ls = new Array(count2); + this.m_as = new Array(count3); + for (var i = 0; i < count2; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + this.m_Ls[i] = b2Distance(p1, p2) + } + for (var i = 0; i < count3; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var p3 = this.m_ps[i + 2]; + var d1 = b2Vec2.Subtract(p2, p1); + var d2 = b2Vec2.Subtract(p3, p2); + var a = b2Cross_v2_v2(d1, d2); + var b = b2Dot_v2_v2(d1, d2); + this.m_as[i] = b2Atan2(a, b) + } + this.m_gravity = def.gravity.Clone(); + this.m_damping = def.damping; + this.m_k2 = def.k2; + this.m_k3 = def.k3 + }, + Step: function (h, iterations) { + if (h == 0) { + return + } + var d = expf(-h * this.m_damping); + for (var i = 0; i < this.m_count; ++i) { + this.m_p0s[i].Assign(this.m_ps[i]); + if (this.m_ims[i] > 0) { + this.m_vs[i].Add(b2Vec2.Multiply(h, this.m_gravity)) + } + this.m_vs[i].Multiply(d); + this.m_ps[i].Add(b2Vec2.Multiply(h, this.m_vs[i])) + } + for (var i = 0; i < iterations; ++i) { + this.SolveC2(); + this.SolveC3(); + this.SolveC2() + } + var inv_h = 1 / h; + for (var i = 0; i < this.m_count; ++i) { + this.m_vs[i] = b2Vec2.Multiply(inv_h, b2Vec2.Subtract(this.m_ps[i], this.m_p0s[i])) + } + }, + GetVertexCount: function () { + return this.m_count + }, + GetVertices: function () { + return this.m_ps + }, + Draw: function (draw) { + var c = new b2Color(0.4, 0.5, 0.7); + for (var i = 0; i < this.m_count - 1; ++i) { + draw.DrawSegment(this.m_ps[i], this.m_ps[i + 1], c) + } + }, + SetAngle: function (angle) { + var count3 = this.m_count - 2; + for (var i = 0; i < count3; ++i) { + this.m_as[i] = angle + } + }, + SolveC2: function () { + var count2 = this.m_count - 1; + for (var i = 0; i < count2; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var d = b2Vec2.Subtract(p2, p1); + var L = d.Normalize(); + var im1 = this.m_ims[i]; + var im2 = this.m_ims[i + 1]; + if (im1 + im2 == 0) { + continue + } + var s1 = im1 / (im1 + im2); + var s2 = im2 / (im1 + im2); + p1.Subtract(b2Vec2.Multiply(this.m_k2 * s1 * (this.m_Ls[i] - L), d)); + p2.Add(b2Vec2.Multiply(this.m_k2 * s2 * (this.m_Ls[i] - L), d)) + } + }, + SolveC3: function () { + var count3 = this.m_count - 2; + for (var i = 0; i < count3; ++i) { + var p1 = this.m_ps[i]; + var p2 = this.m_ps[i + 1]; + var p3 = this.m_ps[i + 2]; + var m1 = this.m_ims[i]; + var m2 = this.m_ims[i + 1]; + var m3 = this.m_ims[i + 2]; + var d1 = b2Vec2.Subtract(p2, p1); + var d2 = b2Vec2.Subtract(p3, p2); + var L1sqr = d1.LengthSquared(); + var L2sqr = d2.LengthSquared(); + if (L1sqr * L2sqr == 0) { + continue + } + var a = b2Cross_v2_v2(d1, d2); + var b = b2Dot_v2_v2(d1, d2); + var angle = b2Atan2(a, b); + var Jd1 = b2Vec2.Multiply((-1 / L1sqr), d1.Skew()); + var Jd2 = b2Vec2.Multiply((1 / L2sqr), d2.Skew()); + var J1 = b2Vec2.Negate(Jd1); + var J2 = b2Vec2.Subtract(Jd1, Jd2); + var J3 = Jd2; + var mass = m1 * b2Dot_v2_v2(J1, J1) + m2 * b2Dot_v2_v2(J2, J2) + m3 * b2Dot_v2_v2(J3, J3); + if (mass == 0) { + continue + } + mass = 1 / mass; + var C = angle - this.m_as[i]; + while (C > b2_pi) { + angle -= 2 * b2_pi; + C = angle - this.m_as[i] + } + while (C < -b2_pi) { + angle += 2 * b2_pi; + C = angle - this.m_as[i] + } + var impulse = -this.m_k3 * mass * C; + p1.Add(b2Vec2.Multiply((m1 * impulse), J1)); + p2.Add(b2Vec2.Multiply((m2 * impulse), J2)); + p3.Add(b2Vec2.Multiply((m3 * impulse), J3)) + } } - b2Rope.prototype = { - Initialize: function (def) { - this.m_count = def.count; - this.m_ps = new Array(this.m_count); - this.m_p0s = new Array(this.m_count); - this.m_vs = new Array(this.m_count); - this.m_ims = new Array(this.m_count); - for (var i = 0; i < this.m_count; ++i) { - this.m_ps[i] = def.vertices[i].Clone(); - this.m_p0s[i] = def.vertices[i].Clone(); - this.m_vs[i] = new b2Vec2(); - var m = def.masses[i]; - if (m > 0) { - this.m_ims[i] = 1 / m - } else { - this.m_ims[i] = 0 - } - } - var count2 = this.m_count - 1; - var count3 = this.m_count - 2; - this.m_Ls = new Array(count2); - this.m_as = new Array(count3); - for (var i = 0; i < count2; ++i) { - var p1 = this.m_ps[i]; - var p2 = this.m_ps[i + 1]; - this.m_Ls[i] = b2Distance(p1, p2) - } - for (var i = 0; i < count3; ++i) { - var p1 = this.m_ps[i]; - var p2 = this.m_ps[i + 1]; - var p3 = this.m_ps[i + 2]; - var d1 = b2Vec2.Subtract(p2, p1); - var d2 = b2Vec2.Subtract(p3, p2); - var a = b2Cross_v2_v2(d1, d2); - var b = b2Dot_v2_v2(d1, d2); - this.m_as[i] = b2Atan2(a, b) - } - this.m_gravity = def.gravity.Clone(); - this.m_damping = def.damping; - this.m_k2 = def.k2; - this.m_k3 = def.k3 - }, - Step: function (h, iterations) { - if (h == 0) { - return - } - var d = expf(-h * this.m_damping); - for (var i = 0; i < this.m_count; ++i) { - this.m_p0s[i].Assign(this.m_ps[i]); - if (this.m_ims[i] > 0) { - this.m_vs[i].Add(b2Vec2.Multiply(h, this.m_gravity)) - } - this.m_vs[i].Multiply(d); - this.m_ps[i].Add(b2Vec2.Multiply(h, this.m_vs[i])) - } - for (var i = 0; i < iterations; ++i) { - this.SolveC2(); - this.SolveC3(); - this.SolveC2() - } - var inv_h = 1 / h; - for (var i = 0; i < this.m_count; ++i) { - this.m_vs[i] = b2Vec2.Multiply(inv_h, b2Vec2.Subtract(this.m_ps[i], this.m_p0s[i])) - } - }, - GetVertexCount: function () { - return this.m_count - }, - GetVertices: function () { - return this.m_ps - }, - Draw: function (draw) { - var c = new b2Color(0.4, 0.5, 0.7); - for (var i = 0; i < this.m_count - 1; ++i) { - draw.DrawSegment(this.m_ps[i], this.m_ps[i + 1], c) - } - }, - SetAngle: function (angle) { - var count3 = this.m_count - 2; - for (var i = 0; i < count3; ++i) { - this.m_as[i] = angle - } - }, - SolveC2: function () { - var count2 = this.m_count - 1; - for (var i = 0; i < count2; ++i) { - var p1 = this.m_ps[i]; - var p2 = this.m_ps[i + 1]; - var d = b2Vec2.Subtract(p2, p1); - var L = d.Normalize(); - var im1 = this.m_ims[i]; - var im2 = this.m_ims[i + 1]; - if (im1 + im2 == 0) { - continue - } - var s1 = im1 / (im1 + im2); - var s2 = im2 / (im1 + im2); - p1.Subtract(b2Vec2.Multiply(this.m_k2 * s1 * (this.m_Ls[i] - L), d)); - p2.Add(b2Vec2.Multiply(this.m_k2 * s2 * (this.m_Ls[i] - L), d)) - } - }, - SolveC3: function () { - var count3 = this.m_count - 2; - for (var i = 0; i < count3; ++i) { - var p1 = this.m_ps[i]; - var p2 = this.m_ps[i + 1]; - var p3 = this.m_ps[i + 2]; - var m1 = this.m_ims[i]; - var m2 = this.m_ims[i + 1]; - var m3 = this.m_ims[i + 2]; - var d1 = b2Vec2.Subtract(p2, p1); - var d2 = b2Vec2.Subtract(p3, p2); - var L1sqr = d1.LengthSquared(); - var L2sqr = d2.LengthSquared(); - if (L1sqr * L2sqr == 0) { - continue - } - var a = b2Cross_v2_v2(d1, d2); - var b = b2Dot_v2_v2(d1, d2); - var angle = b2Atan2(a, b); - var Jd1 = b2Vec2.Multiply((-1 / L1sqr), d1.Skew()); - var Jd2 = b2Vec2.Multiply((1 / L2sqr), d2.Skew()); - var J1 = b2Vec2.Negate(Jd1); - var J2 = b2Vec2.Subtract(Jd1, Jd2); - var J3 = Jd2; - var mass = m1 * b2Dot_v2_v2(J1, J1) + m2 * b2Dot_v2_v2(J2, J2) + m3 * b2Dot_v2_v2(J3, J3); - if (mass == 0) { - continue - } - mass = 1 / mass; - var C = angle - this.m_as[i]; - while (C > b2_pi) { - angle -= 2 * b2_pi; - C = angle - this.m_as[i] - } - while (C < -b2_pi) { - angle += 2 * b2_pi; - C = angle - this.m_as[i] - } - var impulse = -this.m_k3 * mass * C; - p1.Add(b2Vec2.Multiply((m1 * impulse), J1)); - p2.Add(b2Vec2.Multiply((m2 * impulse), J2)); - p3.Add(b2Vec2.Multiply((m3 * impulse), J3)) +}; +var b2JsonSerializer = { + serialize: function (world) { + var shapes = []; + var i; + var serialized; + var b; + var f; + var shape; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + for (f = b.GetFixtureList(); f; f = f.GetNext()) { + shape = f.GetShape(); + f.__temp_shape_id = shapes.length; + shapes.push(shape._serialize()) } } - }; - var b2JsonSerializer = { - serialize: function (world) { - var shapes = []; - var i; - var serialized; - var b; - var f; - var shape; - for (b = world.GetBodyList(); b; b = b.GetNext()) { - for (f = b.GetFixtureList(); f; f = f.GetNext()) { - shape = f.GetShape(); - f.__temp_shape_id = shapes.length; - shapes.push(shape._serialize()) - } - } - var fixtures = []; - for (b = world.GetBodyList(); b; b = b.GetNext()) { - b.__temp_fixture_ids = []; - for (f = b.GetFixtureList(); f; f = f.GetNext()) { - serialized = f._serialize(); - serialized.shape = f.__temp_shape_id; - delete f.__temp_shape_id; - b.__temp_fixture_ids.push(fixtures.length); - fixtures.push(serialized) - } - } - var bodies = []; - for (b = world.GetBodyList(); b; b = b.GetNext()) { - serialized = b._serialize(); - serialized.fixtures = []; - for (i = 0; i < b.__temp_fixture_ids.length; ++i) { - serialized.fixtures.push(b.__temp_fixture_ids[i]) - } - delete b.__temp_fixture_ids; - b.__temp_body_id = bodies.length; - bodies.push(serialized) - } - var joints = []; - var j; - for (j = world.GetJointList(), i = 0; j; j = j.GetNext(), ++i) { - j.__temp_joint_id = i - } - for (j = world.GetJointList(); j; j = j.GetNext()) { - if (j.GetType() === b2Joint.e_mouseJoint) { - continue - } - serialized = j._serialize(); - serialized.bodyA = j.GetBodyA().__temp_body_id; - serialized.bodyB = j.GetBodyB().__temp_body_id; - joints.push(serialized) - } - for (j = world.GetJointList(); j; j = j.GetNext()) { - delete j.__temp_joint_id - } - for (b = world.GetBodyList(); b; b = b.GetNext()) { - delete b.__temp_body_id - } - return { - shapes: shapes, - fixtures: fixtures, - bodies: bodies, - joints: joints - } - }, - deserialize: function (serialized, world, clear) { - var deserialized = JSON.parse(serialized); - if (clear) { - for (var b = world.GetBodyList(); b;) { - var next = b.GetNext(); - world.DestroyBody(b); - b = next - } - for (var j = world.GetJointList(); j;) { - var next = j.GetNext(); - world.DestroyJoint(j); - j = next - } - } - var shapes = []; - for (var i = 0; i < deserialized.shapes.length; ++i) { - var shapeData = deserialized.shapes[i]; - var shape; - switch (shapeData.m_type) { - case b2Shape.e_circle: - shape = new b2CircleShape(); - break; - case b2Shape.e_edge: - shape = new b2EdgeShape(); - break; - case b2Shape.e_chain: - shape = new b2ChainShape(); - break; - case b2Shape.e_polygon: - shape = new b2PolygonShape(); - break - } - shape._deserialize(shapeData); - shapes.push(shape) - } - var fixtures = []; - for (i = 0; i < deserialized.fixtures.length; ++i) { - var fixtureData = deserialized.fixtures[i]; - var fixture = new b2FixtureDef(); - fixture._deserialize(fixtureData); - fixture.shape = shapes[fixtureData.shape]; - fixtures.push(fixture) - } - var bodies = []; - for (i = 0; i < deserialized.bodies.length; ++i) { - var bodyData = deserialized.bodies[i]; - var def = new b2BodyDef(); - def._deserialize(bodyData); - var body = world.CreateBody(def); - for (var x = 0; x < bodyData.fixtures.length; ++x) { - body.CreateFixture(fixtures[bodyData.fixtures[x]]) - } - bodies.push(body) - } - var joints = []; - var gears = []; - for (i = 0; i < deserialized.joints.length; ++i) { - var jointData = deserialized.joints[i]; - var jointDef; - switch (jointData.type) { - case b2Joint.e_revoluteJoint: - jointDef = new b2RevoluteJointDef(); - break; - case b2Joint.e_prismaticJoint: - jointDef = new b2PrismaticJointDef(); - break; - case b2Joint.e_distanceJoint: - jointDef = new b2DistanceJointDef(); - break; - case b2Joint.e_pulleyJoint: - jointDef = new b2PulleyJointDef(); - break; - case b2Joint.e_gearJoint: - jointDef = new b2GearJointDef(); - break; - case b2Joint.e_wheelJoint: - jointDef = new b2WheelJointDef(); - break; - case b2Joint.e_weldJoint: - jointDef = new b2WeldJointDef(); - break; - case b2Joint.e_frictionJoint: - jointDef = new b2FrictionJointDef(); - break; - case b2Joint.e_ropeJoint: - jointDef = new b2RopeJointDef(); - break; - case b2Joint.e_motorJoint: - jointDef = new b2MotorJointDef(); - break; - default: - throw new Error("unknown joint") - } - jointDef._deserialize(jointData, bodies); - if (jointData.type === b2Joint.e_gearJoint) { - gears.push([jointDef, joints.length]); - joints.push(null) - } else { - var joint = world.CreateJoint(jointDef); - joints.push(joint) - } - } - for (i = 0; i < gears.length; ++i) { - gears[i][0].joint1 = joints[gears[i][0].joint1]; - gears[i][0].joint2 = joints[gears[i][0].joint2]; - joint = world.CreateJoint(gears[i][0]); - joints[gears[i][1]] = joint + var fixtures = []; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + b.__temp_fixture_ids = []; + for (f = b.GetFixtureList(); f; f = f.GetNext()) { + serialized = f._serialize(); + serialized.shape = f.__temp_shape_id; + delete f.__temp_shape_id; + b.__temp_fixture_ids.push(fixtures.length); + fixtures.push(serialized) } } - }; - var b2RUBELoader = (function () { - function parseVector(obj) { - return new b2Vec2(obj ? (obj.x || 0) : 0, obj ? (obj.y || 0) : 0) + var bodies = []; + for (b = world.GetBodyList(); b; b = b.GetNext()) { + serialized = b._serialize(); + serialized.fixtures = []; + for (i = 0; i < b.__temp_fixture_ids.length; ++i) { + serialized.fixtures.push(b.__temp_fixture_ids[i]) + } + delete b.__temp_fixture_ids; + b.__temp_body_id = bodies.length; + bodies.push(serialized) } - - function parseVectorArray(obj) { - var vals = new Array(obj.x.length); - for (var i = 0; i < vals.length; ++i) { - vals[i] = new b2Vec2(obj.x[i], obj.y[i]) - } - return vals + var joints = []; + var j; + for (j = world.GetJointList(), i = 0; j; j = j.GetNext(), ++i) { + j.__temp_joint_id = i } - - function parseProperty(obj, instance) { - var name = obj.name; - var val; - if (typeof (obj["int"]) !== "undefined") { - val = obj["int"] - } else { - if (typeof (obj["float"]) !== "undefined") { - val = obj["float"] - } else { - if (typeof (obj.string) !== "undefined") { - val = obj.string - } else { - if (typeof (obj.bool) !== "undefined") { - val = obj.bool - } else { - if (typeof (obj.vec2) !== "undefined") { - val = parseVector(obj.vec2) - } else { - throw new Error("unknown property type") - } - } - } - } + for (j = world.GetJointList(); j; j = j.GetNext()) { + if (j.GetType() === b2Joint.e_mouseJoint) { + continue } - if (instance.hasOwnProperty(name)) { - throw new Error("custom property possibly overwriting an existing one") - } - instance[name] = val + serialized = j._serialize(); + serialized.bodyA = j.GetBodyA().__temp_body_id; + serialized.bodyB = j.GetBodyB().__temp_body_id; + joints.push(serialized) } - - function parseFixture(obj, body) { - var def = new b2FixtureDef(); - def.density = obj.density || 0; - def.filter.categoryBits = typeof (obj["filter-categoryBits"]) === "undefined" ? 1 : obj["filter-categoryBits"]; - def.filter.maskBits = typeof (obj["filter-maskBits"]) === "undefined" ? 65535 : obj["filter-maskBits"]; - def.filter.groupIndex = typeof (obj["filter-groupIndex"]) === "undefined" ? 0 : obj["filter-groupIndex"]; - def.friction = obj.friction || 0; - def.restitution = obj.restitution || 0; - def.isSensor = obj.sensor || 0; - var shape; - if (typeof (obj.circle) !== "undefined") { - shape = new b2CircleShape(); - shape.m_p = parseVector(obj.circle.center); - shape.m_radius = obj.circle.radius || 0 - } else { - if (typeof (obj.polygon) !== "undefined") { - var vertices = parseVectorArray(obj.polygon.vertices); - shape = new b2PolygonShape(); - shape.Set(vertices, vertices.length) - } else { - if (typeof (obj.chain) !== "undefined") { - var vertices = parseVectorArray(obj.chain.vertices); - shape = new b2ChainShape(); - shape.m_count = vertices.length; - shape.m_vertices = vertices; - if (shape.m_hasNextVertex = obj.chain.hasNextVertex) { - shape.m_nextVertex = parseVector(obj.chain.nextVertex) - } - if (shape.m_hasPrevVertex = obj.chain.hasPrevVertex) { - shape.m_prevVertex = parseVector(obj.chain.prevVertex) - } - } else { - throw new Error("unknown shape type") - } - } - } - def.shape = shape; - var fixture = body.CreateFixture(def); - fixture.name = obj.name; - if (obj.customProperties) { - for (var i = 0; i < obj.customProperties.length; ++i) { - parseProperty(obj, fixture) - } - } + for (j = world.GetJointList(); j; j = j.GetNext()) { + delete j.__temp_joint_id } - - function parseBody(obj, world) { - var def = new b2BodyDef(); - def.type = obj.type || b2Body.b2_staticBody; - def.angle = obj.angle || 0; - def.angularDamping = obj.angularDamping || 0; - def.angularVelocity = obj.angularVelocity || 0; - def.awake = obj.awake || false; - def.bullet = obj.bullet || false; - def.fixedRotation = obj.fixedRotation || false; - def.linearDamping = obj.linearDamping || false; - def.linearVelocity = parseVector(obj.linearVelocity); - def.gravityScale = typeof (obj.gravityScale) !== "undefined" ? obj.gravityScale : 1; - var md = new b2MassData(); - md.mass = obj["massData-mass"] || 0; - md.center = parseVector(obj["massData-center"]); - md.I = obj["massData-I"] || 0; - def.position = parseVector(obj.position); - var body = world.CreateBody(def); - body.name = obj.name; - body.SetMassData(md); - if (obj.fixture) { - for (var i = 0; i < obj.fixture.length; ++i) { - parseFixture(obj.fixture[i], body) - } - } - if (obj.customProperties) { - for (i = 0; i < obj.customProperties.length; ++i) { - parseProperty(obj, body) - } - } - return body - } - var jointsList = { - revolute: b2RevoluteJointDef, - distance: b2DistanceJointDef, - prismatic: b2PrismaticJointDef, - wheel: b2WheelJointDef, - rope: b2RopeJointDef, - motor: b2MotorJointDef, - weld: b2WeldJointDef, - friction: b2FrictionJointDef - }; - - function parseJoint(obj, world, bodies) { - if (!jointsList[obj.type]) { - throw new Error("unknown joint type") - } - var jd = new jointsList[obj.type](); - switch (jd.type) { - case b2Joint.e_revoluteJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.enableLimit = obj.enableLimit || false; - jd.enableMotor = obj.enableMotor || false; - jd.lowerAngle = obj.lowerLimit || 0; - jd.maxMotorTorque = obj.maxMotorTorque || 0; - jd.motorSpeed = obj.motorSpeed || 0; - jd.referenceAngle = obj.refAngle || 0; - jd.upperAngle = obj.upperLimit || 0; - break; - case b2Joint.e_distanceJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.dampingRatio = obj.dampingRatio || 0; - jd.frequencyHz = obj.frequency || 0; - jd.length = obj.length || 0; - break; - case b2Joint.e_prismaticJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.enableLimit = obj.enableLimit || false; - jd.enableMotor = obj.enableMotor || false; - jd.localAxisA = parseVector(obj.localAxisA); - jd.lowerTranslation = obj.lowerLimit || 0; - jd.maxMotorForce = obj.maxMotorForce || 0; - jd.motorSpeed = obj.motorSpeed || 0; - jd.referenceAngle = obj.refAngle || 0; - jd.upperTranslation = obj.upperLimit || 0; - break; - case b2Joint.e_wheelJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.enableMotor = obj.enableMotor || false; - jd.localAxisA = parseVector(obj.localAxisA); - jd.maxMotorTorque = obj.maxMotorTorque || 0; - jd.motorSpeed = obj.motorSpeed || 0; - jd.dampingRatio = obj.springDampingRatio || 0; - jd.frequencyHz = obj.springFrequency || 0; - break; - case b2Joint.e_ropeJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.maxLength = obj.maxLength || 0; - break; - case b2Joint.e_motorJoint: - jd.linearOffset = parseVector(obj.anchorA); - jd.angularOffset = obj.refAngle || 0; - jd.maxForce = obj.maxForce || 0; - jd.maxTorque = obj.maxTorque || 0; - jd.correctionFactor = obj.correctionFactor || 0; - break; - case b2Joint.e_weldJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.referenceAngle = obj.refAngle || 0; - jd.dampingRatio = obj.dampingRatio || 0; - jd.frequencyHz = obj.frequencyHz || 0; - break; - case b2Joint.e_frictionJoint: - jd.localAnchorA = parseVector(obj.anchorA); - jd.localAnchorB = parseVector(obj.anchorB); - jd.maxForce = obj.maxForce || 0; - jd.maxTorque = obj.maxTorque || 0; - break; - default: - throw new Error("wat?") - } - jd.bodyA = bodies[obj.bodyA || 0]; - jd.bodyB = bodies[obj.bodyB || 0]; - jd.collideConnected = obj.collideConnected || false; - var joint = world.CreateJoint(jd); - joint.name = obj.name; - if (obj.customProperties) { - for (var i = 0; i < obj.customProperties.length; ++i) { - parseProperty(obj, joint) - } - } - return joint - } - - function b2RubeParameters() { - this.world = null; - this.positionIterations = 0; - this.velocityIterations = 0; - this.stepsPerSecond = 0; - this.fixtures = {}; - this.bodies = {}; - this.joints = {}; - Object.seal(this) - } - - function parseWorld(obj, world) { - var params = new b2RubeParameters(); - params.world = world = world || new b2World(new b2Vec2(0, 0)); - params.positionIterations = obj.positionIterations || 0; - params.velocityIterations = obj.velocityIterations || 0; - params.stepsPerSecond = obj.stepsPerSecond || 0; - if (obj.gravity) { - world.SetGravity(parseVector(obj.gravity)) - } - world.SetAllowSleeping(obj.allowSleep || false); - world.SetAutoClearForces(obj.autoClearForces || false); - world.SetWarmStarting(obj.warmStarting || false); - world.SetContinuousPhysics(obj.continuousPhysics || false); - world.SetSubStepping(obj.subStepping || false); - var bodies = []; - var bl = obj.body; - if (bl) { - for (var i = 0; i < bl.length; ++i) { - var body = parseBody(bl[i], world); - bodies.push(body); - for (var f = body.GetFixtureList(); f; f = f.GetNext()) { - if (!params.fixtures[f.name]) { - params.fixtures[f.name] = [] - } - params.fixtures[f.name].push(f) - } - if (!params.bodies[body.name]) { - params.bodies[body.name] = [] - } - params.bodies[body.name].push(body) - } - } - var joints = []; - var jl = obj.joint; - if (jl) { - for (i = 0; i < jl.length; ++i) { - var joint = parseJoint(jl[i], world, bodies); - joints.push(joint); - if (!params.joints[joint.name]) { - params.joints[joint.name] = [] - } - params.joints[joint.name].push(joint) - } - } - return params + for (b = world.GetBodyList(); b; b = b.GetNext()) { + delete b.__temp_body_id } return { - parseWorld: parseWorld + shapes: shapes, + fixtures: fixtures, + bodies: bodies, + joints: joints } - })(); - var mappings = [{ - trimmed: "version", - name: "b2_version", - def: b2_version - }, { - trimmed: "Vec2", - name: "b2Vec2", - def: b2Vec2 - }, { - trimmed: "Vec3", - name: "b2Vec3", - def: b2Vec3 - }, { - trimmed: "Mat22", - name: "b2Mat22", - def: b2Mat22 - }, { - trimmed: "Mat33", - name: "b2Mat33", - def: b2Mat33 - }, { - trimmed: "Rot", - name: "b2Rot", - def: b2Rot - }, { - trimmed: "Transform", - name: "b2Transform", - def: b2Transform - }, { - trimmed: "Sweep", - name: "b2Sweep", - def: b2Sweep - }, { - trimmed: "Dot_v2_v2", - name: "b2Dot_v2_v2", - def: b2Dot_v2_v2 - }, { - trimmed: "Cross_v2_v2", - name: "b2Cross_v2_v2", - def: b2Cross_v2_v2 - }, { - trimmed: "Cross_v2_f", - name: "b2Cross_v2_f", - def: b2Cross_v2_f - }, { - trimmed: "Cross_f_v2", - name: "b2Cross_f_v2", - def: b2Cross_f_v2 - }, { - trimmed: "Mul_m22_v2", - name: "b2Mul_m22_v2", - def: b2Mul_m22_v2 - }, { - trimmed: "MulT_m22_v2", - name: "b2MulT_m22_v2", - def: b2MulT_m22_v2 - }, { - trimmed: "Distance", - name: "b2Distance", - def: b2Distance - }, { - trimmed: "DistanceSquared", - name: "b2DistanceSquared", - def: b2DistanceSquared - }, { - trimmed: "Dot_v3_v3", - name: "b2Dot_v3_v3", - def: b2Dot_v3_v3 - }, { - trimmed: "Cross_v3_v3", - name: "b2Cross_v3_v3", - def: b2Cross_v3_v3 - }, { - trimmed: "Mul_m22_m22", - name: "b2Mul_m22_m22", - def: b2Mul_m22_m22 - }, { - trimmed: "MulT_m22_m22", - name: "b2MulT_m22_m22", - def: b2MulT_m22_m22 - }, { - trimmed: "Mul_m33_v3", - name: "b2Mul_m33_v3", - def: b2Mul_m33_v3 - }, { - trimmed: "Mul22_m33_v2", - name: "b2Mul22_m33_v2", - def: b2Mul22_m33_v2 - }, { - trimmed: "Mul_r_r", - name: "b2Mul_r_r", - def: b2Mul_r_r - }, { - trimmed: "MulT_r_r", - name: "b2MulT_r_r", - def: b2MulT_r_r - }, { - trimmed: "Mul_r_v2", - name: "b2Mul_r_v2", - def: b2Mul_r_v2 - }, { - trimmed: "MulT_r_v2", - name: "b2MulT_r_v2", - def: b2MulT_r_v2 - }, { - trimmed: "Mul_t_v2", - name: "b2Mul_t_v2", - def: b2Mul_t_v2 - }, { - trimmed: "Min_v2", - name: "b2Min_v2", - def: b2Min_v2 - }, { - trimmed: "Max_v2", - name: "b2Max_v2", - def: b2Max_v2 - }, { - trimmed: "Clamp", - name: "b2Clamp", - def: b2Clamp - }, { - trimmed: "MulT_t_v2", - name: "b2MulT_t_v2", - def: b2MulT_t_v2 - }, { - trimmed: "Mul_t_t", - name: "b2Mul_t_t", - def: b2Mul_t_t - }, { - trimmed: "MulT_t_t", - name: "b2MulT_t_t", - def: b2MulT_t_t - }, { - trimmed: "Clamp_v2", - name: "b2Clamp_v2", - def: b2Clamp_v2 - }, { - trimmed: "NextPowerOfTwo", - name: "b2NextPowerOfTwo", - def: b2NextPowerOfTwo - }, { - trimmed: "Abs_v2", - name: "b2Abs_v2", - def: b2Abs_v2 - }, { - trimmed: "Abs_m22", - name: "b2Abs_m22", - def: b2Abs_m22 - }, { - trimmed: "IsPowerOfTwo", - name: "b2IsPowerOfTwo", - def: b2IsPowerOfTwo - }, { - trimmed: "RandomFloat", - name: "b2RandomFloat", - def: b2RandomFloat - }, { - trimmed: "Timer", - name: "b2Timer", - def: b2Timer - }, { - trimmed: "Color", - name: "b2Color", - def: b2Color - }, { - trimmed: "Draw", - name: "b2Draw", - def: b2Draw - }, { - trimmed: "ContactID", - name: "b2ContactID", - def: b2ContactID - }, { - trimmed: "ManifoldPoint", - name: "b2ManifoldPoint", - def: b2ManifoldPoint - }, { - trimmed: "Manifold", - name: "b2Manifold", - def: b2Manifold - }, { - trimmed: "WorldManifold", - name: "b2WorldManifold", - def: b2WorldManifold - }, { - trimmed: "GetPointStates", - name: "b2GetPointStates", - def: b2GetPointStates - }, { - trimmed: "ClipVertex", - name: "b2ClipVertex", - def: b2ClipVertex - }, { - trimmed: "RayCastInput", - name: "b2RayCastInput", - def: b2RayCastInput - }, { - trimmed: "RayCastOutput", - name: "b2RayCastOutput", - def: b2RayCastOutput - }, { - trimmed: "AABB", - name: "b2AABB", - def: b2AABB - }, { - trimmed: "CollideCircles", - name: "b2CollideCircles", - def: b2CollideCircles - }, { - trimmed: "CollidePolygonAndCircle", - name: "b2CollidePolygonAndCircle", - def: b2CollidePolygonAndCircle - }, { - trimmed: "FindMaxSeparation", - name: "b2FindMaxSeparation", - def: b2FindMaxSeparation - }, { - trimmed: "FindIncidentEdge", - name: "b2FindIncidentEdge", - def: b2FindIncidentEdge - }, { - trimmed: "CollidePolygons", - name: "b2CollidePolygons", - def: b2CollidePolygons - }, { - trimmed: "CollideEdgeAndCircle", - name: "b2CollideEdgeAndCircle", - def: b2CollideEdgeAndCircle - }, { - trimmed: "EPAxis", - name: "b2EPAxis", - def: b2EPAxis - }, { - trimmed: "TempPolygon", - name: "b2TempPolygon", - def: b2TempPolygon - }, { - trimmed: "ReferenceFace", - name: "b2ReferenceFace", - def: b2ReferenceFace - }, { - trimmed: "EPCollider", - name: "b2EPCollider", - def: b2EPCollider - }, { - trimmed: "CollideEdgeAndPolygon", - name: "b2CollideEdgeAndPolygon", - def: b2CollideEdgeAndPolygon - }, { - trimmed: "ClipSegmentToLine", - name: "b2ClipSegmentToLine", - def: b2ClipSegmentToLine - }, { - trimmed: "TestShapeOverlap", - name: "b2TestShapeOverlap", - def: b2TestShapeOverlap - }, { - trimmed: "TestOverlap", - name: "b2TestOverlap", - def: b2TestOverlap - }, { - trimmed: "Shape", - name: "b2Shape", - def: b2Shape - }, { - trimmed: "CircleShape", - name: "b2CircleShape", - def: b2CircleShape - }, { - trimmed: "EdgeShape", - name: "b2EdgeShape", - def: b2EdgeShape - }, { - trimmed: "ChainShape", - name: "b2ChainShape", - def: b2ChainShape - }, { - trimmed: "PolygonShape", - name: "b2PolygonShape", - def: b2PolygonShape - }, { - trimmed: "Pair", - name: "b2Pair", - def: b2Pair - }, { - trimmed: "PairLessThan", - name: "b2PairLessThan", - def: b2PairLessThan - }, { - trimmed: "BroadPhase", - name: "b2BroadPhase", - def: b2BroadPhase - }, { - trimmed: "DistanceProxy", - name: "b2DistanceProxy", - def: b2DistanceProxy - }, { - trimmed: "SimplexCache", - name: "b2SimplexCache", - def: b2SimplexCache - }, { - trimmed: "DistanceInput", - name: "b2DistanceInput", - def: b2DistanceInput - }, { - trimmed: "DistanceOutput", - name: "b2DistanceOutput", - def: b2DistanceOutput - }, { - trimmed: "SimplexVertex", - name: "b2SimplexVertex", - def: b2SimplexVertex - }, { - trimmed: "Simplex", - name: "b2Simplex", - def: b2Simplex - }, { - trimmed: "DistanceFunc", - name: "b2DistanceFunc", - def: b2DistanceFunc - }, { - trimmed: "TreeNode", - name: "b2TreeNode", - def: b2TreeNode - }, { - trimmed: "DynamicTree", - name: "b2DynamicTree", - def: b2DynamicTree - }, { - trimmed: "TOIInput", - name: "b2TOIInput", - def: b2TOIInput - }, { - trimmed: "TOIOutput", - name: "b2TOIOutput", - def: b2TOIOutput - }, { - trimmed: "SeparationFunction", - name: "b2SeparationFunction", - def: b2SeparationFunction - }, { - trimmed: "TimeOfImpact", - name: "b2TimeOfImpact", - def: b2TimeOfImpact - }, { - trimmed: "BodyDef", - name: "b2BodyDef", - def: b2BodyDef - }, { - trimmed: "Body", - name: "b2Body", - def: b2Body - }, { - trimmed: "Filter", - name: "b2Filter", - def: b2Filter - }, { - trimmed: "FixtureDef", - name: "b2FixtureDef", - def: b2FixtureDef - }, { - trimmed: "Fixture", - name: "b2Fixture", - def: b2Fixture - }, { - trimmed: "DestructionListener", - name: "b2DestructionListener", - def: b2DestructionListener - }, { - trimmed: "ContactFilter", - name: "b2ContactFilter", - def: b2ContactFilter - }, { - trimmed: "ContactImpulse", - name: "b2ContactImpulse", - def: b2ContactImpulse - }, { - trimmed: "ContactListener", - name: "b2ContactListener", - def: b2ContactListener - }, { - trimmed: "QueryCallback", - name: "b2QueryCallback", - def: b2QueryCallback - }, { - trimmed: "RayCastCallback", - name: "b2RayCastCallback", - def: b2RayCastCallback - }, { - trimmed: "TimeStep", - name: "b2TimeStep", - def: b2TimeStep - }, { - trimmed: "Position", - name: "b2Position", - def: b2Position - }, { - trimmed: "Velocity", - name: "b2Velocity", - def: b2Velocity - }, { - trimmed: "SolverData", - name: "b2SolverData", - def: b2SolverData - }, { - trimmed: "World", - name: "b2World", - def: b2World - }, { - trimmed: "MixFriction", - name: "b2MixFriction", - def: b2MixFriction - }, { - trimmed: "MixRestitution", - name: "b2MixRestitution", - def: b2MixRestitution - }, { - trimmed: "ContactRegister", - name: "b2ContactRegister", - def: b2ContactRegister - }, { - trimmed: "ContactEdge", - name: "b2ContactEdge", - def: b2ContactEdge - }, { - trimmed: "Contact", - name: "b2Contact", - def: b2Contact - }, { - trimmed: "CircleContact", - name: "b2CircleContact", - def: b2CircleContact - }, { - trimmed: "PolygonContact", - name: "b2PolygonContact", - def: b2PolygonContact - }, { - trimmed: "ChainAndCircleContact", - name: "b2ChainAndCircleContact", - def: b2ChainAndCircleContact - }, { - trimmed: "ChainAndPolygonContact", - name: "b2ChainAndPolygonContact", - def: b2ChainAndPolygonContact - }, { - trimmed: "EdgeAndCircleContact", - name: "b2EdgeAndCircleContact", - def: b2EdgeAndCircleContact - }, { - trimmed: "EdgeAndPolygonContact", - name: "b2EdgeAndPolygonContact", - def: b2EdgeAndPolygonContact - }, { - trimmed: "PolygonAndCircleContact", - name: "b2PolygonAndCircleContact", - def: b2PolygonAndCircleContact - }, { - trimmed: "defaultFilter", - name: "b2_defaultFilter", - def: b2_defaultFilter - }, { - trimmed: "defaultListener", - name: "b2_defaultListener", - def: b2_defaultListener - }, { - trimmed: "ContactManager", - name: "b2ContactManager", - def: b2ContactManager - }, { - trimmed: "VelocityConstraintPoint", - name: "b2VelocityConstraintPoint", - def: b2VelocityConstraintPoint - }, { - trimmed: "ContactPositionConstraint", - name: "b2ContactPositionConstraint", - def: b2ContactPositionConstraint - }, { - trimmed: "ContactVelocityConstraint", - name: "b2ContactVelocityConstraint", - def: b2ContactVelocityConstraint - }, { - trimmed: "PositionSolverManifold", - name: "b2PositionSolverManifold", - def: b2PositionSolverManifold - }, { - trimmed: "ContactSolverDef", - name: "b2ContactSolverDef", - def: b2ContactSolverDef - }, { - trimmed: "ContactSolver", - name: "b2ContactSolver", - def: b2ContactSolver - }, { - trimmed: "Island", - name: "b2Island", - def: b2Island - }, { - trimmed: "Jacobian", - name: "b2Jacobian", - def: b2Jacobian - }, { - trimmed: "JointEdge", - name: "b2JointEdge", - def: b2JointEdge - }, { - trimmed: "JointDef", - name: "b2JointDef", - def: b2JointDef - }, { - trimmed: "Joint", - name: "b2Joint", - def: b2Joint - }, { - trimmed: "RevoluteJointDef", - name: "b2RevoluteJointDef", - def: b2RevoluteJointDef - }, { - trimmed: "RevoluteJoint", - name: "b2RevoluteJoint", - def: b2RevoluteJoint - }, { - trimmed: "MouseJointDef", - name: "b2MouseJointDef", - def: b2MouseJointDef - }, { - trimmed: "MouseJoint", - name: "b2MouseJoint", - def: b2MouseJoint - }, { - trimmed: "DistanceJointDef", - name: "b2DistanceJointDef", - def: b2DistanceJointDef - }, { - trimmed: "DistanceJoint", - name: "b2DistanceJoint", - def: b2DistanceJoint - }, { - trimmed: "PrismaticJointDef", - name: "b2PrismaticJointDef", - def: b2PrismaticJointDef - }, { - trimmed: "PrismaticJoint", - name: "b2PrismaticJoint", - def: b2PrismaticJoint - }, { - trimmed: "FrictionJointDef", - name: "b2FrictionJointDef", - def: b2FrictionJointDef - }, { - trimmed: "FrictionJoint", - name: "b2FrictionJoint", - def: b2FrictionJoint - }, { - trimmed: "WeldJointDef", - name: "b2WeldJointDef", - def: b2WeldJointDef - }, { - trimmed: "WeldJoint", - name: "b2WeldJoint", - def: b2WeldJoint - }, { - trimmed: "WheelJointDef", - name: "b2WheelJointDef", - def: b2WheelJointDef - }, { - trimmed: "WheelJoint", - name: "b2WheelJoint", - def: b2WheelJoint - }, { - trimmed: "GearJointDef", - name: "b2GearJointDef", - def: b2GearJointDef - }, { - trimmed: "GearJoint", - name: "b2GearJoint", - def: b2GearJoint - }, { - trimmed: "MotorJointDef", - name: "b2MotorJointDef", - def: b2MotorJointDef - }, { - trimmed: "MotorJoint", - name: "b2MotorJoint", - def: b2MotorJoint - }, { - trimmed: "PulleyJointDef", - name: "b2PulleyJointDef", - def: b2PulleyJointDef - }, { - trimmed: "PulleyJoint", - name: "b2PulleyJoint", - def: b2PulleyJoint - }, { - trimmed: "RopeJointDef", - name: "b2RopeJointDef", - def: b2RopeJointDef - }, { - trimmed: "RopeJoint", - name: "b2RopeJoint", - def: b2RopeJoint - }, { - trimmed: "RopeDef", - name: "b2RopeDef", - def: b2RopeDef - }, { - trimmed: "Rope", - name: "b2Rope", - def: b2Rope - }, { - trimmed: "maxManifoldPoints", - name: "b2_maxManifoldPoints", - def: b2_maxManifoldPoints - }, { - trimmed: "maxPolygonVertices", - name: "b2_maxPolygonVertices", - def: b2_maxPolygonVertices - }, { - trimmed: "aabbExtension", - name: "b2_aabbExtension", - def: b2_aabbExtension - }, { - trimmed: "aabbMultiplier", - name: "b2_aabbMultiplier", - def: b2_aabbMultiplier - }, { - trimmed: "linearSlop", - name: "b2_linearSlop", - def: b2_linearSlop - }, { - trimmed: "angularSlop", - name: "b2_angularSlop", - def: b2_angularSlop - }, { - trimmed: "polygonRadius", - name: "b2_polygonRadius", - def: b2_polygonRadius - }, { - trimmed: "maxSubSteps", - name: "b2_maxSubSteps", - def: b2_maxSubSteps - }, { - trimmed: "maxTOIContacts", - name: "b2_maxTOIContacts", - def: b2_maxTOIContacts - }, { - trimmed: "velocityThreshold", - name: "b2_velocityThreshold", - def: b2_velocityThreshold - }, { - trimmed: "maxLinearCorrection", - name: "b2_maxLinearCorrection", - def: b2_maxLinearCorrection - }, { - trimmed: "maxAngularCorrection", - name: "b2_maxAngularCorrection", - def: b2_maxAngularCorrection - }, { - trimmed: "maxTranslation", - name: "b2_maxTranslation", - def: b2_maxTranslation - }, { - trimmed: "maxTranslationSquared", - name: "b2_maxTranslationSquared", - def: b2_maxTranslationSquared - }, { - trimmed: "maxRotation", - name: "b2_maxRotation", - def: b2_maxRotation - }, { - trimmed: "maxRotationSquared", - name: "b2_maxRotationSquared", - def: b2_maxRotationSquared - }, { - trimmed: "baumgarte", - name: "b2_baumgarte", - def: b2_baumgarte - }, { - trimmed: "toiBaugarte", - name: "b2_toiBaugarte", - def: b2_toiBaugarte - }, { - trimmed: "timeToSleep", - name: "b2_timeToSleep", - def: b2_timeToSleep - }, { - trimmed: "linearSleepTolerance", - name: "b2_linearSleepTolerance", - def: b2_linearSleepTolerance - }, { - trimmed: "angularSleepTolerance", - name: "b2_angularSleepTolerance", - def: b2_angularSleepTolerance - }, { - trimmed: "epsilon", - name: "b2_epsilon", - def: b2_epsilon - }, { - trimmed: "JsonSerializer", - name: "b2JsonSerializer", - def: b2JsonSerializer - }, { - trimmed: "RUBELoader", - name: "b2RUBELoader", - def: b2RUBELoader - }, { - trimmed: "Profiler", - name: "b2Profiler", - def: b2Profiler - }]; - - - if (typeof (b2_compatibility) !== "undefined" && typeof (window) !== "undefined") { - for (var i = 0; i < mappings.length; ++i) { - window[mappings[i].name] = mappings[i].def + }, + deserialize: function (serialized, world, clear) { + var deserialized = JSON.parse(serialized); + if (clear) { + for (var b = world.GetBodyList(); b;) { + var next = b.GetNext(); + world.DestroyBody(b); + b = next + } + for (var j = world.GetJointList(); j;) { + var next = j.GetNext(); + world.DestroyJoint(j); + j = next + } } - } else { - var b2 = {}; - for (var i = 0; i < mappings.length; ++i) { - b2[mappings[i].trimmed] = mappings[i].def + var shapes = []; + for (var i = 0; i < deserialized.shapes.length; ++i) { + var shapeData = deserialized.shapes[i]; + var shape; + switch (shapeData.m_type) { + case b2Shape.e_circle: + shape = new b2CircleShape(); + break; + case b2Shape.e_edge: + shape = new b2EdgeShape(); + break; + case b2Shape.e_chain: + shape = new b2ChainShape(); + break; + case b2Shape.e_polygon: + shape = new b2PolygonShape(); + break + } + shape._deserialize(shapeData); + shapes.push(shape) } - if (typeof (module) !== "undefined") { - module.exports = b2 - } else { - window.b2 = b2 + var fixtures = []; + for (i = 0; i < deserialized.fixtures.length; ++i) { + var fixtureData = deserialized.fixtures[i]; + var fixture = new b2FixtureDef(); + fixture._deserialize(fixtureData); + fixture.shape = shapes[fixtureData.shape]; + fixtures.push(fixture) + } + var bodies = []; + for (i = 0; i < deserialized.bodies.length; ++i) { + var bodyData = deserialized.bodies[i]; + var def = new b2BodyDef(); + def._deserialize(bodyData); + var body = world.CreateBody(def); + for (var x = 0; x < bodyData.fixtures.length; ++x) { + body.CreateFixture(fixtures[bodyData.fixtures[x]]) + } + bodies.push(body) + } + var joints = []; + var gears = []; + for (i = 0; i < deserialized.joints.length; ++i) { + var jointData = deserialized.joints[i]; + var jointDef; + switch (jointData.type) { + case b2Joint.e_revoluteJoint: + jointDef = new b2RevoluteJointDef(); + break; + case b2Joint.e_prismaticJoint: + jointDef = new b2PrismaticJointDef(); + break; + case b2Joint.e_distanceJoint: + jointDef = new b2DistanceJointDef(); + break; + case b2Joint.e_pulleyJoint: + jointDef = new b2PulleyJointDef(); + break; + case b2Joint.e_gearJoint: + jointDef = new b2GearJointDef(); + break; + case b2Joint.e_wheelJoint: + jointDef = new b2WheelJointDef(); + break; + case b2Joint.e_weldJoint: + jointDef = new b2WeldJointDef(); + break; + case b2Joint.e_frictionJoint: + jointDef = new b2FrictionJointDef(); + break; + case b2Joint.e_ropeJoint: + jointDef = new b2RopeJointDef(); + break; + case b2Joint.e_motorJoint: + jointDef = new b2MotorJointDef(); + break; + default: + throw new Error("unknown joint") + } + jointDef._deserialize(jointData, bodies); + if (jointData.type === b2Joint.e_gearJoint) { + gears.push([jointDef, joints.length]); + joints.push(null) + } else { + var joint = world.CreateJoint(jointDef); + joints.push(joint) + } + } + for (i = 0; i < gears.length; ++i) { + gears[i][0].joint1 = joints[gears[i][0].joint1]; + gears[i][0].joint2 = joints[gears[i][0].joint2]; + joint = world.CreateJoint(gears[i][0]); + joints[gears[i][1]] = joint } } +}; +var b2RUBELoader = (function () { + function parseVector(obj) { + return new b2Vec2(obj ? (obj.x || 0) : 0, obj ? (obj.y || 0) : 0) + } + + function parseVectorArray(obj) { + var vals = new Array(obj.x.length); + for (var i = 0; i < vals.length; ++i) { + vals[i] = new b2Vec2(obj.x[i], obj.y[i]) + } + return vals + } + + function parseProperty(obj, instance) { + var name = obj.name; + var val; + if (typeof (obj["int"]) !== "undefined") { + val = obj["int"] + } else { + if (typeof (obj["float"]) !== "undefined") { + val = obj["float"] + } else { + if (typeof (obj.string) !== "undefined") { + val = obj.string + } else { + if (typeof (obj.bool) !== "undefined") { + val = obj.bool + } else { + if (typeof (obj.vec2) !== "undefined") { + val = parseVector(obj.vec2) + } else { + throw new Error("unknown property type") + } + } + } + } + } + if (instance.hasOwnProperty(name)) { + throw new Error("custom property possibly overwriting an existing one") + } + instance[name] = val + } + + function parseFixture(obj, body) { + var def = new b2FixtureDef(); + def.density = obj.density || 0; + def.filter.categoryBits = typeof (obj["filter-categoryBits"]) === "undefined" ? 1 : obj["filter-categoryBits"]; + def.filter.maskBits = typeof (obj["filter-maskBits"]) === "undefined" ? 65535 : obj["filter-maskBits"]; + def.filter.groupIndex = typeof (obj["filter-groupIndex"]) === "undefined" ? 0 : obj["filter-groupIndex"]; + def.friction = obj.friction || 0; + def.restitution = obj.restitution || 0; + def.isSensor = obj.sensor || 0; + var shape; + if (typeof (obj.circle) !== "undefined") { + shape = new b2CircleShape(); + shape.m_p = parseVector(obj.circle.center); + shape.m_radius = obj.circle.radius || 0 + } else { + if (typeof (obj.polygon) !== "undefined") { + var vertices = parseVectorArray(obj.polygon.vertices); + shape = new b2PolygonShape(); + shape.Set(vertices, vertices.length) + } else { + if (typeof (obj.chain) !== "undefined") { + var vertices = parseVectorArray(obj.chain.vertices); + shape = new b2ChainShape(); + shape.m_count = vertices.length; + shape.m_vertices = vertices; + if (shape.m_hasNextVertex = obj.chain.hasNextVertex) { + shape.m_nextVertex = parseVector(obj.chain.nextVertex) + } + if (shape.m_hasPrevVertex = obj.chain.hasPrevVertex) { + shape.m_prevVertex = parseVector(obj.chain.prevVertex) + } + } else { + throw new Error("unknown shape type") + } + } + } + def.shape = shape; + var fixture = body.CreateFixture(def); + fixture.name = obj.name; + if (obj.customProperties) { + for (var i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, fixture) + } + } + } + + function parseBody(obj, world) { + var def = new b2BodyDef(); + def.type = obj.type || b2Body.b2_staticBody; + def.angle = obj.angle || 0; + def.angularDamping = obj.angularDamping || 0; + def.angularVelocity = obj.angularVelocity || 0; + def.awake = obj.awake || false; + def.bullet = obj.bullet || false; + def.fixedRotation = obj.fixedRotation || false; + def.linearDamping = obj.linearDamping || false; + def.linearVelocity = parseVector(obj.linearVelocity); + def.gravityScale = typeof (obj.gravityScale) !== "undefined" ? obj.gravityScale : 1; + var md = new b2MassData(); + md.mass = obj["massData-mass"] || 0; + md.center = parseVector(obj["massData-center"]); + md.I = obj["massData-I"] || 0; + def.position = parseVector(obj.position); + var body = world.CreateBody(def); + body.name = obj.name; + body.SetMassData(md); + if (obj.fixture) { + for (var i = 0; i < obj.fixture.length; ++i) { + parseFixture(obj.fixture[i], body) + } + } + if (obj.customProperties) { + for (i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, body) + } + } + return body + } + var jointsList = { + revolute: b2RevoluteJointDef, + distance: b2DistanceJointDef, + prismatic: b2PrismaticJointDef, + wheel: b2WheelJointDef, + rope: b2RopeJointDef, + motor: b2MotorJointDef, + weld: b2WeldJointDef, + friction: b2FrictionJointDef + }; + + function parseJoint(obj, world, bodies) { + if (!jointsList[obj.type]) { + throw new Error("unknown joint type") + } + var jd = new jointsList[obj.type](); + switch (jd.type) { + case b2Joint.e_revoluteJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableLimit = obj.enableLimit || false; + jd.enableMotor = obj.enableMotor || false; + jd.lowerAngle = obj.lowerLimit || 0; + jd.maxMotorTorque = obj.maxMotorTorque || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.referenceAngle = obj.refAngle || 0; + jd.upperAngle = obj.upperLimit || 0; + break; + case b2Joint.e_distanceJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.dampingRatio = obj.dampingRatio || 0; + jd.frequencyHz = obj.frequency || 0; + jd.length = obj.length || 0; + break; + case b2Joint.e_prismaticJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableLimit = obj.enableLimit || false; + jd.enableMotor = obj.enableMotor || false; + jd.localAxisA = parseVector(obj.localAxisA); + jd.lowerTranslation = obj.lowerLimit || 0; + jd.maxMotorForce = obj.maxMotorForce || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.referenceAngle = obj.refAngle || 0; + jd.upperTranslation = obj.upperLimit || 0; + break; + case b2Joint.e_wheelJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.enableMotor = obj.enableMotor || false; + jd.localAxisA = parseVector(obj.localAxisA); + jd.maxMotorTorque = obj.maxMotorTorque || 0; + jd.motorSpeed = obj.motorSpeed || 0; + jd.dampingRatio = obj.springDampingRatio || 0; + jd.frequencyHz = obj.springFrequency || 0; + break; + case b2Joint.e_ropeJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.maxLength = obj.maxLength || 0; + break; + case b2Joint.e_motorJoint: + jd.linearOffset = parseVector(obj.anchorA); + jd.angularOffset = obj.refAngle || 0; + jd.maxForce = obj.maxForce || 0; + jd.maxTorque = obj.maxTorque || 0; + jd.correctionFactor = obj.correctionFactor || 0; + break; + case b2Joint.e_weldJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.referenceAngle = obj.refAngle || 0; + jd.dampingRatio = obj.dampingRatio || 0; + jd.frequencyHz = obj.frequencyHz || 0; + break; + case b2Joint.e_frictionJoint: + jd.localAnchorA = parseVector(obj.anchorA); + jd.localAnchorB = parseVector(obj.anchorB); + jd.maxForce = obj.maxForce || 0; + jd.maxTorque = obj.maxTorque || 0; + break; + default: + throw new Error("wat?") + } + jd.bodyA = bodies[obj.bodyA || 0]; + jd.bodyB = bodies[obj.bodyB || 0]; + jd.collideConnected = obj.collideConnected || false; + var joint = world.CreateJoint(jd); + joint.name = obj.name; + if (obj.customProperties) { + for (var i = 0; i < obj.customProperties.length; ++i) { + parseProperty(obj, joint) + } + } + return joint + } + + function b2RubeParameters() { + this.world = null; + this.positionIterations = 0; + this.velocityIterations = 0; + this.stepsPerSecond = 0; + this.fixtures = {}; + this.bodies = {}; + this.joints = {}; + Object.seal(this) + } + + function parseWorld(obj, world) { + var params = new b2RubeParameters(); + params.world = world = world || new b2World(new b2Vec2(0, 0)); + params.positionIterations = obj.positionIterations || 0; + params.velocityIterations = obj.velocityIterations || 0; + params.stepsPerSecond = obj.stepsPerSecond || 0; + if (obj.gravity) { + world.SetGravity(parseVector(obj.gravity)) + } + world.SetAllowSleeping(obj.allowSleep || false); + world.SetAutoClearForces(obj.autoClearForces || false); + world.SetWarmStarting(obj.warmStarting || false); + world.SetContinuousPhysics(obj.continuousPhysics || false); + world.SetSubStepping(obj.subStepping || false); + var bodies = []; + var bl = obj.body; + if (bl) { + for (var i = 0; i < bl.length; ++i) { + var body = parseBody(bl[i], world); + bodies.push(body); + for (var f = body.GetFixtureList(); f; f = f.GetNext()) { + if (!params.fixtures[f.name]) { + params.fixtures[f.name] = [] + } + params.fixtures[f.name].push(f) + } + if (!params.bodies[body.name]) { + params.bodies[body.name] = [] + } + params.bodies[body.name].push(body) + } + } + var joints = []; + var jl = obj.joint; + if (jl) { + for (i = 0; i < jl.length; ++i) { + var joint = parseJoint(jl[i], world, bodies); + joints.push(joint); + if (!params.joints[joint.name]) { + params.joints[joint.name] = [] + } + params.joints[joint.name].push(joint) + } + } + return params + } + return { + parseWorld: parseWorld + } })(); +var mappings = [{ + trimmed: "version", + name: "b2_version", + def: b2_version +}, { + trimmed: "Vec2", + name: "b2Vec2", + def: b2Vec2 +}, { + trimmed: "Vec3", + name: "b2Vec3", + def: b2Vec3 +}, { + trimmed: "Mat22", + name: "b2Mat22", + def: b2Mat22 +}, { + trimmed: "Mat33", + name: "b2Mat33", + def: b2Mat33 +}, { + trimmed: "Rot", + name: "b2Rot", + def: b2Rot +}, { + trimmed: "Transform", + name: "b2Transform", + def: b2Transform +}, { + trimmed: "Sweep", + name: "b2Sweep", + def: b2Sweep +}, { + trimmed: "Dot_v2_v2", + name: "b2Dot_v2_v2", + def: b2Dot_v2_v2 +}, { + trimmed: "Cross_v2_v2", + name: "b2Cross_v2_v2", + def: b2Cross_v2_v2 +}, { + trimmed: "Cross_v2_f", + name: "b2Cross_v2_f", + def: b2Cross_v2_f +}, { + trimmed: "Cross_f_v2", + name: "b2Cross_f_v2", + def: b2Cross_f_v2 +}, { + trimmed: "Mul_m22_v2", + name: "b2Mul_m22_v2", + def: b2Mul_m22_v2 +}, { + trimmed: "MulT_m22_v2", + name: "b2MulT_m22_v2", + def: b2MulT_m22_v2 +}, { + trimmed: "Distance", + name: "b2Distance", + def: b2Distance +}, { + trimmed: "DistanceSquared", + name: "b2DistanceSquared", + def: b2DistanceSquared +}, { + trimmed: "Dot_v3_v3", + name: "b2Dot_v3_v3", + def: b2Dot_v3_v3 +}, { + trimmed: "Cross_v3_v3", + name: "b2Cross_v3_v3", + def: b2Cross_v3_v3 +}, { + trimmed: "Mul_m22_m22", + name: "b2Mul_m22_m22", + def: b2Mul_m22_m22 +}, { + trimmed: "MulT_m22_m22", + name: "b2MulT_m22_m22", + def: b2MulT_m22_m22 +}, { + trimmed: "Mul_m33_v3", + name: "b2Mul_m33_v3", + def: b2Mul_m33_v3 +}, { + trimmed: "Mul22_m33_v2", + name: "b2Mul22_m33_v2", + def: b2Mul22_m33_v2 +}, { + trimmed: "Mul_r_r", + name: "b2Mul_r_r", + def: b2Mul_r_r +}, { + trimmed: "MulT_r_r", + name: "b2MulT_r_r", + def: b2MulT_r_r +}, { + trimmed: "Mul_r_v2", + name: "b2Mul_r_v2", + def: b2Mul_r_v2 +}, { + trimmed: "MulT_r_v2", + name: "b2MulT_r_v2", + def: b2MulT_r_v2 +}, { + trimmed: "Mul_t_v2", + name: "b2Mul_t_v2", + def: b2Mul_t_v2 +}, { + trimmed: "Min_v2", + name: "b2Min_v2", + def: b2Min_v2 +}, { + trimmed: "Max_v2", + name: "b2Max_v2", + def: b2Max_v2 +}, { + trimmed: "Clamp", + name: "b2Clamp", + def: b2Clamp +}, { + trimmed: "MulT_t_v2", + name: "b2MulT_t_v2", + def: b2MulT_t_v2 +}, { + trimmed: "Mul_t_t", + name: "b2Mul_t_t", + def: b2Mul_t_t +}, { + trimmed: "MulT_t_t", + name: "b2MulT_t_t", + def: b2MulT_t_t +}, { + trimmed: "Clamp_v2", + name: "b2Clamp_v2", + def: b2Clamp_v2 +}, { + trimmed: "NextPowerOfTwo", + name: "b2NextPowerOfTwo", + def: b2NextPowerOfTwo +}, { + trimmed: "Abs_v2", + name: "b2Abs_v2", + def: b2Abs_v2 +}, { + trimmed: "Abs_m22", + name: "b2Abs_m22", + def: b2Abs_m22 +}, { + trimmed: "IsPowerOfTwo", + name: "b2IsPowerOfTwo", + def: b2IsPowerOfTwo +}, { + trimmed: "RandomFloat", + name: "b2RandomFloat", + def: b2RandomFloat +}, { + trimmed: "Timer", + name: "b2Timer", + def: b2Timer +}, { + trimmed: "Color", + name: "b2Color", + def: b2Color +}, { + trimmed: "Draw", + name: "b2Draw", + def: b2Draw +}, { + trimmed: "ContactID", + name: "b2ContactID", + def: b2ContactID +}, { + trimmed: "ManifoldPoint", + name: "b2ManifoldPoint", + def: b2ManifoldPoint +}, { + trimmed: "Manifold", + name: "b2Manifold", + def: b2Manifold +}, { + trimmed: "WorldManifold", + name: "b2WorldManifold", + def: b2WorldManifold +}, { + trimmed: "GetPointStates", + name: "b2GetPointStates", + def: b2GetPointStates +}, { + trimmed: "ClipVertex", + name: "b2ClipVertex", + def: b2ClipVertex +}, { + trimmed: "RayCastInput", + name: "b2RayCastInput", + def: b2RayCastInput +}, { + trimmed: "RayCastOutput", + name: "b2RayCastOutput", + def: b2RayCastOutput +}, { + trimmed: "AABB", + name: "b2AABB", + def: b2AABB +}, { + trimmed: "CollideCircles", + name: "b2CollideCircles", + def: b2CollideCircles +}, { + trimmed: "CollidePolygonAndCircle", + name: "b2CollidePolygonAndCircle", + def: b2CollidePolygonAndCircle +}, { + trimmed: "FindMaxSeparation", + name: "b2FindMaxSeparation", + def: b2FindMaxSeparation +}, { + trimmed: "FindIncidentEdge", + name: "b2FindIncidentEdge", + def: b2FindIncidentEdge +}, { + trimmed: "CollidePolygons", + name: "b2CollidePolygons", + def: b2CollidePolygons +}, { + trimmed: "CollideEdgeAndCircle", + name: "b2CollideEdgeAndCircle", + def: b2CollideEdgeAndCircle +}, { + trimmed: "EPAxis", + name: "b2EPAxis", + def: b2EPAxis +}, { + trimmed: "TempPolygon", + name: "b2TempPolygon", + def: b2TempPolygon +}, { + trimmed: "ReferenceFace", + name: "b2ReferenceFace", + def: b2ReferenceFace +}, { + trimmed: "EPCollider", + name: "b2EPCollider", + def: b2EPCollider +}, { + trimmed: "CollideEdgeAndPolygon", + name: "b2CollideEdgeAndPolygon", + def: b2CollideEdgeAndPolygon +}, { + trimmed: "ClipSegmentToLine", + name: "b2ClipSegmentToLine", + def: b2ClipSegmentToLine +}, { + trimmed: "TestShapeOverlap", + name: "b2TestShapeOverlap", + def: b2TestShapeOverlap +}, { + trimmed: "TestOverlap", + name: "b2TestOverlap", + def: b2TestOverlap +}, { + trimmed: "Shape", + name: "b2Shape", + def: b2Shape +}, { + trimmed: "CircleShape", + name: "b2CircleShape", + def: b2CircleShape +}, { + trimmed: "EdgeShape", + name: "b2EdgeShape", + def: b2EdgeShape +}, { + trimmed: "ChainShape", + name: "b2ChainShape", + def: b2ChainShape +}, { + trimmed: "PolygonShape", + name: "b2PolygonShape", + def: b2PolygonShape +}, { + trimmed: "Pair", + name: "b2Pair", + def: b2Pair +}, { + trimmed: "PairLessThan", + name: "b2PairLessThan", + def: b2PairLessThan +}, { + trimmed: "BroadPhase", + name: "b2BroadPhase", + def: b2BroadPhase +}, { + trimmed: "DistanceProxy", + name: "b2DistanceProxy", + def: b2DistanceProxy +}, { + trimmed: "SimplexCache", + name: "b2SimplexCache", + def: b2SimplexCache +}, { + trimmed: "DistanceInput", + name: "b2DistanceInput", + def: b2DistanceInput +}, { + trimmed: "DistanceOutput", + name: "b2DistanceOutput", + def: b2DistanceOutput +}, { + trimmed: "SimplexVertex", + name: "b2SimplexVertex", + def: b2SimplexVertex +}, { + trimmed: "Simplex", + name: "b2Simplex", + def: b2Simplex +}, { + trimmed: "DistanceFunc", + name: "b2DistanceFunc", + def: b2DistanceFunc +}, { + trimmed: "TreeNode", + name: "b2TreeNode", + def: b2TreeNode +}, { + trimmed: "DynamicTree", + name: "b2DynamicTree", + def: b2DynamicTree +}, { + trimmed: "TOIInput", + name: "b2TOIInput", + def: b2TOIInput +}, { + trimmed: "TOIOutput", + name: "b2TOIOutput", + def: b2TOIOutput +}, { + trimmed: "SeparationFunction", + name: "b2SeparationFunction", + def: b2SeparationFunction +}, { + trimmed: "TimeOfImpact", + name: "b2TimeOfImpact", + def: b2TimeOfImpact +}, { + trimmed: "BodyDef", + name: "b2BodyDef", + def: b2BodyDef +}, { + trimmed: "Body", + name: "b2Body", + def: b2Body +}, { + trimmed: "Filter", + name: "b2Filter", + def: b2Filter +}, { + trimmed: "FixtureDef", + name: "b2FixtureDef", + def: b2FixtureDef +}, { + trimmed: "Fixture", + name: "b2Fixture", + def: b2Fixture +}, { + trimmed: "DestructionListener", + name: "b2DestructionListener", + def: b2DestructionListener +}, { + trimmed: "ContactFilter", + name: "b2ContactFilter", + def: b2ContactFilter +}, { + trimmed: "ContactImpulse", + name: "b2ContactImpulse", + def: b2ContactImpulse +}, { + trimmed: "ContactListener", + name: "b2ContactListener", + def: b2ContactListener +}, { + trimmed: "QueryCallback", + name: "b2QueryCallback", + def: b2QueryCallback +}, { + trimmed: "RayCastCallback", + name: "b2RayCastCallback", + def: b2RayCastCallback +}, { + trimmed: "TimeStep", + name: "b2TimeStep", + def: b2TimeStep +}, { + trimmed: "Position", + name: "b2Position", + def: b2Position +}, { + trimmed: "Velocity", + name: "b2Velocity", + def: b2Velocity +}, { + trimmed: "SolverData", + name: "b2SolverData", + def: b2SolverData +}, { + trimmed: "World", + name: "b2World", + def: b2World +}, { + trimmed: "MixFriction", + name: "b2MixFriction", + def: b2MixFriction +}, { + trimmed: "MixRestitution", + name: "b2MixRestitution", + def: b2MixRestitution +}, { + trimmed: "ContactRegister", + name: "b2ContactRegister", + def: b2ContactRegister +}, { + trimmed: "ContactEdge", + name: "b2ContactEdge", + def: b2ContactEdge +}, { + trimmed: "Contact", + name: "b2Contact", + def: b2Contact +}, { + trimmed: "CircleContact", + name: "b2CircleContact", + def: b2CircleContact +}, { + trimmed: "PolygonContact", + name: "b2PolygonContact", + def: b2PolygonContact +}, { + trimmed: "ChainAndCircleContact", + name: "b2ChainAndCircleContact", + def: b2ChainAndCircleContact +}, { + trimmed: "ChainAndPolygonContact", + name: "b2ChainAndPolygonContact", + def: b2ChainAndPolygonContact +}, { + trimmed: "EdgeAndCircleContact", + name: "b2EdgeAndCircleContact", + def: b2EdgeAndCircleContact +}, { + trimmed: "EdgeAndPolygonContact", + name: "b2EdgeAndPolygonContact", + def: b2EdgeAndPolygonContact +}, { + trimmed: "PolygonAndCircleContact", + name: "b2PolygonAndCircleContact", + def: b2PolygonAndCircleContact +}, { + trimmed: "defaultFilter", + name: "b2_defaultFilter", + def: b2_defaultFilter +}, { + trimmed: "defaultListener", + name: "b2_defaultListener", + def: b2_defaultListener +}, { + trimmed: "ContactManager", + name: "b2ContactManager", + def: b2ContactManager +}, { + trimmed: "VelocityConstraintPoint", + name: "b2VelocityConstraintPoint", + def: b2VelocityConstraintPoint +}, { + trimmed: "ContactPositionConstraint", + name: "b2ContactPositionConstraint", + def: b2ContactPositionConstraint +}, { + trimmed: "ContactVelocityConstraint", + name: "b2ContactVelocityConstraint", + def: b2ContactVelocityConstraint +}, { + trimmed: "PositionSolverManifold", + name: "b2PositionSolverManifold", + def: b2PositionSolverManifold +}, { + trimmed: "ContactSolverDef", + name: "b2ContactSolverDef", + def: b2ContactSolverDef +}, { + trimmed: "ContactSolver", + name: "b2ContactSolver", + def: b2ContactSolver +}, { + trimmed: "Island", + name: "b2Island", + def: b2Island +}, { + trimmed: "Jacobian", + name: "b2Jacobian", + def: b2Jacobian +}, { + trimmed: "JointEdge", + name: "b2JointEdge", + def: b2JointEdge +}, { + trimmed: "JointDef", + name: "b2JointDef", + def: b2JointDef +}, { + trimmed: "Joint", + name: "b2Joint", + def: b2Joint +}, { + trimmed: "RevoluteJointDef", + name: "b2RevoluteJointDef", + def: b2RevoluteJointDef +}, { + trimmed: "RevoluteJoint", + name: "b2RevoluteJoint", + def: b2RevoluteJoint +}, { + trimmed: "MouseJointDef", + name: "b2MouseJointDef", + def: b2MouseJointDef +}, { + trimmed: "MouseJoint", + name: "b2MouseJoint", + def: b2MouseJoint +}, { + trimmed: "DistanceJointDef", + name: "b2DistanceJointDef", + def: b2DistanceJointDef +}, { + trimmed: "DistanceJoint", + name: "b2DistanceJoint", + def: b2DistanceJoint +}, { + trimmed: "PrismaticJointDef", + name: "b2PrismaticJointDef", + def: b2PrismaticJointDef +}, { + trimmed: "PrismaticJoint", + name: "b2PrismaticJoint", + def: b2PrismaticJoint +}, { + trimmed: "FrictionJointDef", + name: "b2FrictionJointDef", + def: b2FrictionJointDef +}, { + trimmed: "FrictionJoint", + name: "b2FrictionJoint", + def: b2FrictionJoint +}, { + trimmed: "WeldJointDef", + name: "b2WeldJointDef", + def: b2WeldJointDef +}, { + trimmed: "WeldJoint", + name: "b2WeldJoint", + def: b2WeldJoint +}, { + trimmed: "WheelJointDef", + name: "b2WheelJointDef", + def: b2WheelJointDef +}, { + trimmed: "WheelJoint", + name: "b2WheelJoint", + def: b2WheelJoint +}, { + trimmed: "GearJointDef", + name: "b2GearJointDef", + def: b2GearJointDef +}, { + trimmed: "GearJoint", + name: "b2GearJoint", + def: b2GearJoint +}, { + trimmed: "MotorJointDef", + name: "b2MotorJointDef", + def: b2MotorJointDef +}, { + trimmed: "MotorJoint", + name: "b2MotorJoint", + def: b2MotorJoint +}, { + trimmed: "PulleyJointDef", + name: "b2PulleyJointDef", + def: b2PulleyJointDef +}, { + trimmed: "PulleyJoint", + name: "b2PulleyJoint", + def: b2PulleyJoint +}, { + trimmed: "RopeJointDef", + name: "b2RopeJointDef", + def: b2RopeJointDef +}, { + trimmed: "RopeJoint", + name: "b2RopeJoint", + def: b2RopeJoint +}, { + trimmed: "RopeDef", + name: "b2RopeDef", + def: b2RopeDef +}, { + trimmed: "Rope", + name: "b2Rope", + def: b2Rope +}, { + trimmed: "maxManifoldPoints", + name: "b2_maxManifoldPoints", + def: b2_maxManifoldPoints +}, { + trimmed: "maxPolygonVertices", + name: "b2_maxPolygonVertices", + def: b2_maxPolygonVertices +}, { + trimmed: "aabbExtension", + name: "b2_aabbExtension", + def: b2_aabbExtension +}, { + trimmed: "aabbMultiplier", + name: "b2_aabbMultiplier", + def: b2_aabbMultiplier +}, { + trimmed: "linearSlop", + name: "b2_linearSlop", + def: b2_linearSlop +}, { + trimmed: "angularSlop", + name: "b2_angularSlop", + def: b2_angularSlop +}, { + trimmed: "polygonRadius", + name: "b2_polygonRadius", + def: b2_polygonRadius +}, { + trimmed: "maxSubSteps", + name: "b2_maxSubSteps", + def: b2_maxSubSteps +}, { + trimmed: "maxTOIContacts", + name: "b2_maxTOIContacts", + def: b2_maxTOIContacts +}, { + trimmed: "velocityThreshold", + name: "b2_velocityThreshold", + def: b2_velocityThreshold +}, { + trimmed: "maxLinearCorrection", + name: "b2_maxLinearCorrection", + def: b2_maxLinearCorrection +}, { + trimmed: "maxAngularCorrection", + name: "b2_maxAngularCorrection", + def: b2_maxAngularCorrection +}, { + trimmed: "maxTranslation", + name: "b2_maxTranslation", + def: b2_maxTranslation +}, { + trimmed: "maxTranslationSquared", + name: "b2_maxTranslationSquared", + def: b2_maxTranslationSquared +}, { + trimmed: "maxRotation", + name: "b2_maxRotation", + def: b2_maxRotation +}, { + trimmed: "maxRotationSquared", + name: "b2_maxRotationSquared", + def: b2_maxRotationSquared +}, { + trimmed: "baumgarte", + name: "b2_baumgarte", + def: b2_baumgarte +}, { + trimmed: "toiBaugarte", + name: "b2_toiBaugarte", + def: b2_toiBaugarte +}, { + trimmed: "timeToSleep", + name: "b2_timeToSleep", + def: b2_timeToSleep +}, { + trimmed: "linearSleepTolerance", + name: "b2_linearSleepTolerance", + def: b2_linearSleepTolerance +}, { + trimmed: "angularSleepTolerance", + name: "b2_angularSleepTolerance", + def: b2_angularSleepTolerance +}, { + trimmed: "epsilon", + name: "b2_epsilon", + def: b2_epsilon +}, { + trimmed: "JsonSerializer", + name: "b2JsonSerializer", + def: b2JsonSerializer +}, { + trimmed: "RUBELoader", + name: "b2RUBELoader", + def: b2RUBELoader +}, { + trimmed: "Profiler", + name: "b2Profiler", + def: b2Profiler +}]; + + +var b2 = {}; +for (var i = 0; i < mappings.length; ++i) { + b2[mappings[i].trimmed] = mappings[i].def +} + +export { b2 } diff --git a/webpack.config.js b/webpack.config.js index 9903bc5..7106a5a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,15 +16,23 @@ module.exports = { filename: '[name].bundle.js', }, optimization: { + usedExports: true, splitChunks: { cacheGroups: { - lib: { + box2d: { test: /jsbox2d/, chunks: 'initial', - name: 'lib', + name: 'box2d', priority:20, enforce:true }, + tfjs: { + test: /[\\/]node_modules[\\/]\@tensorflow/, + chunks: 'initial', + name: 'tfjs', + priority: 15, + enforce: true, + }, vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'initial', @@ -49,3 +57,4 @@ module.exports = { }), ] }; +