box2d-rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/box2d-rails.gemspec +20 -0
- data/lib/box2d-rails.rb +8 -0
- data/lib/box2d-rails/version.rb +5 -0
- data/vendor/assets/javascripts/box2d/collision/ClipVertex.js +35 -0
- data/vendor/assets/javascripts/box2d/collision/Features.js +61 -0
- data/vendor/assets/javascripts/box2d/collision/b2AABB.js +45 -0
- data/vendor/assets/javascripts/box2d/collision/b2Bound.js +43 -0
- data/vendor/assets/javascripts/box2d/collision/b2BoundValues.js +31 -0
- data/vendor/assets/javascripts/box2d/collision/b2BroadPhase.js +898 -0
- data/vendor/assets/javascripts/box2d/collision/b2BufferedPair.js +26 -0
- data/vendor/assets/javascripts/box2d/collision/b2Collision.js +738 -0
- data/vendor/assets/javascripts/box2d/collision/b2ContactID.js +52 -0
- data/vendor/assets/javascripts/box2d/collision/b2ContactPoint.js +35 -0
- data/vendor/assets/javascripts/box2d/collision/b2Distance.js +333 -0
- data/vendor/assets/javascripts/box2d/collision/b2Manifold.js +34 -0
- data/vendor/assets/javascripts/box2d/collision/b2OBB.js +34 -0
- data/vendor/assets/javascripts/box2d/collision/b2Pair.js +60 -0
- data/vendor/assets/javascripts/box2d/collision/b2PairCallback.js +34 -0
- data/vendor/assets/javascripts/box2d/collision/b2PairManager.js +386 -0
- data/vendor/assets/javascripts/box2d/collision/b2Proxy.js +40 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2BoxDef.js +49 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2CircleDef.js +49 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2CircleShape.js +198 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2MassData.js +36 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2PolyDef.js +58 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2PolyShape.js +492 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2Shape.js +339 -0
- data/vendor/assets/javascripts/box2d/collision/shapes/b2ShapeDef.js +109 -0
- data/vendor/assets/javascripts/box2d/common/b2Settings.js +72 -0
- data/vendor/assets/javascripts/box2d/common/math/b2Mat22.js +130 -0
- data/vendor/assets/javascripts/box2d/common/math/b2Math.js +218 -0
- data/vendor/assets/javascripts/box2d/common/math/b2Vec2.js +131 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2Body.js +469 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2BodyDef.js +69 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2CollisionFilter.js +42 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2ContactManager.js +337 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2Island.js +331 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2TimeStep.js +27 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2World.js +522 -0
- data/vendor/assets/javascripts/box2d/dynamics/b2WorldListener.js +52 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2CircleContact.js +102 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2Conservative.js +228 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2Contact.js +201 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactConstraint.js +45 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactConstraintPoint.js +40 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactNode.js +33 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactRegister.js +30 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2ContactSolver.js +537 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2NullContact.js +65 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2PolyAndCircleContact.js +103 -0
- data/vendor/assets/javascripts/box2d/dynamics/contacts/b2PolyContact.js +163 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2DistanceJoint.js +264 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2DistanceJointDef.js +49 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2GearJoint.js +307 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2GearJointDef.js +50 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2Jacobian.js +49 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2Joint.js +200 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2JointDef.js +40 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2JointNode.js +33 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2MouseJoint.js +234 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2MouseJointDef.js +53 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2PrismaticJoint.js +676 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2PrismaticJointDef.js +56 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2PulleyJoint.js +618 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2PulleyJointDef.js +70 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2RevoluteJoint.js +491 -0
- data/vendor/assets/javascripts/box2d/dynamics/joints/b2RevoluteJointDef.js +55 -0
- metadata +133 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2012 TODO: Write your name
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Box2d::Rails
|
|
2
|
+
|
|
3
|
+
Box2d js framework for Rails.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'box2d-rails'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install box2d-rails
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Use it!
|
|
22
|
+
|
|
23
|
+
## Contributing
|
|
24
|
+
|
|
25
|
+
1. Fork it
|
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
data/box2d-rails.gemspec
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'box2d-rails/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |gem|
|
|
7
|
+
gem.name = "box2d-rails"
|
|
8
|
+
gem.version = Box2d::Rails::VERSION
|
|
9
|
+
gem.authors = ["Richard Sylvester"]
|
|
10
|
+
gem.email = ["rm.sylvester@gmail.com"]
|
|
11
|
+
gem.description = %q{Box2d js for Rails.}
|
|
12
|
+
gem.summary = %q{Box2d js for Rails.}
|
|
13
|
+
gem.homepage = "https://github.com/manwithtwowatches/box2d-rails"
|
|
14
|
+
|
|
15
|
+
gem.files = `git ls-files`.split($/)
|
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
18
|
+
gem.require_paths = ["lib/vendor"]
|
|
19
|
+
gem.add_dependency "railties", "~> 3.1"
|
|
20
|
+
end
|
data/lib/box2d-rails.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2006-2007 Erin Catto http:
|
|
3
|
+
*
|
|
4
|
+
* This software is provided 'as-is', without any express or implied
|
|
5
|
+
* warranty. In no event will the authors be held liable for any damages
|
|
6
|
+
* arising from the use of this software.
|
|
7
|
+
* Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
* including commercial applications, and to alter it and redistribute it
|
|
9
|
+
* freely, subject to the following restrictions:
|
|
10
|
+
* 1. The origin of this software must not be misrepresented; you must not
|
|
11
|
+
* claim that you wrote the original software. If you use this software
|
|
12
|
+
* in a product, an acknowledgment in the product documentation would be
|
|
13
|
+
* appreciated but is not required.
|
|
14
|
+
* 2. Altered source versions must be plainly marked, and must not be
|
|
15
|
+
* misrepresented the original software.
|
|
16
|
+
* 3. This notice may not be removed or altered from any source distribution.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
var ClipVertex = Class.create();
|
|
24
|
+
ClipVertex.prototype =
|
|
25
|
+
{
|
|
26
|
+
v: new b2Vec2(),
|
|
27
|
+
id: new b2ContactID(),
|
|
28
|
+
initialize: function() {
|
|
29
|
+
// initialize instance variables for references
|
|
30
|
+
this.v = new b2Vec2();
|
|
31
|
+
this.id = new b2ContactID();
|
|
32
|
+
//
|
|
33
|
+
}};
|
|
34
|
+
|
|
35
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2006-2007 Erin Catto http:
|
|
3
|
+
*
|
|
4
|
+
* This software is provided 'as-is', without any express or implied
|
|
5
|
+
* warranty. In no event will the authors be held liable for any damages
|
|
6
|
+
* arising from the use of this software.
|
|
7
|
+
* Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
* including commercial applications, and to alter it and redistribute it
|
|
9
|
+
* freely, subject to the following restrictions:
|
|
10
|
+
* 1. The origin of this software must not be misrepresented; you must not
|
|
11
|
+
* claim that you wrote the original software. If you use this software
|
|
12
|
+
* in a product, an acknowledgment in the product documentation would be
|
|
13
|
+
* appreciated but is not required.
|
|
14
|
+
* 2. Altered source versions must be plainly marked, and must not be
|
|
15
|
+
* misrepresented the original software.
|
|
16
|
+
* 3. This notice may not be removed or altered from any source distribution.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// We use contact ids to facilitate warm starting.
|
|
21
|
+
var Features = Class.create();
|
|
22
|
+
Features.prototype =
|
|
23
|
+
{
|
|
24
|
+
//
|
|
25
|
+
set_referenceFace: function(value){
|
|
26
|
+
this._referenceFace = value;
|
|
27
|
+
this._m_id._key = (this._m_id._key & 0xffffff00) | (this._referenceFace & 0x000000ff)
|
|
28
|
+
},
|
|
29
|
+
get_referenceFace: function(){
|
|
30
|
+
return this._referenceFace;
|
|
31
|
+
},
|
|
32
|
+
_referenceFace: 0,
|
|
33
|
+
//
|
|
34
|
+
set_incidentEdge: function(value){
|
|
35
|
+
this._incidentEdge = value;
|
|
36
|
+
this._m_id._key = (this._m_id._key & 0xffff00ff) | ((this._incidentEdge << 8) & 0x0000ff00)
|
|
37
|
+
},
|
|
38
|
+
get_incidentEdge: function(){
|
|
39
|
+
return this._incidentEdge;
|
|
40
|
+
},
|
|
41
|
+
_incidentEdge: 0,
|
|
42
|
+
//
|
|
43
|
+
set_incidentVertex: function(value){
|
|
44
|
+
this._incidentVertex = value;
|
|
45
|
+
this._m_id._key = (this._m_id._key & 0xff00ffff) | ((this._incidentVertex << 16) & 0x00ff0000)
|
|
46
|
+
},
|
|
47
|
+
get_incidentVertex: function(){
|
|
48
|
+
return this._incidentVertex;
|
|
49
|
+
},
|
|
50
|
+
_incidentVertex: 0,
|
|
51
|
+
//
|
|
52
|
+
set_flip: function(value){
|
|
53
|
+
this._flip = value;
|
|
54
|
+
this._m_id._key = (this._m_id._key & 0x00ffffff) | ((this._flip << 24) & 0xff000000)
|
|
55
|
+
},
|
|
56
|
+
get_flip: function(){
|
|
57
|
+
return this._flip;
|
|
58
|
+
},
|
|
59
|
+
_flip: 0,
|
|
60
|
+
_m_id: null,
|
|
61
|
+
initialize: function() {}};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2006-2007 Erin Catto http:
|
|
3
|
+
*
|
|
4
|
+
* This software is provided 'as-is', without any express or implied
|
|
5
|
+
* warranty. In no event will the authors be held liable for any damages
|
|
6
|
+
* arising from the use of this software.
|
|
7
|
+
* Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
* including commercial applications, and to alter it and redistribute it
|
|
9
|
+
* freely, subject to the following restrictions:
|
|
10
|
+
* 1. The origin of this software must not be misrepresented; you must not
|
|
11
|
+
* claim that you wrote the original software. If you use this software
|
|
12
|
+
* in a product, an acknowledgment in the product documentation would be
|
|
13
|
+
* appreciated but is not required.
|
|
14
|
+
* 2. Altered source versions must be plainly marked, and must not be
|
|
15
|
+
* misrepresented the original software.
|
|
16
|
+
* 3. This notice may not be removed or altered from any source distribution.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
// A manifold for two touching convex shapes.
|
|
22
|
+
var b2AABB = Class.create();
|
|
23
|
+
b2AABB.prototype =
|
|
24
|
+
{
|
|
25
|
+
IsValid: function(){
|
|
26
|
+
//var d = b2Math.SubtractVV(this.maxVertex, this.minVertex);
|
|
27
|
+
var dX = this.maxVertex.x;
|
|
28
|
+
var dY = this.maxVertex.y;
|
|
29
|
+
dX = this.maxVertex.x;
|
|
30
|
+
dY = this.maxVertex.y;
|
|
31
|
+
dX -= this.minVertex.x;
|
|
32
|
+
dY -= this.minVertex.y;
|
|
33
|
+
var valid = dX >= 0.0 && dY >= 0.0;
|
|
34
|
+
valid = valid && this.minVertex.IsValid() && this.maxVertex.IsValid();
|
|
35
|
+
return valid;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
minVertex: new b2Vec2(),
|
|
39
|
+
maxVertex: new b2Vec2(),
|
|
40
|
+
initialize: function() {
|
|
41
|
+
// initialize instance variables for references
|
|
42
|
+
this.minVertex = new b2Vec2();
|
|
43
|
+
this.maxVertex = new b2Vec2();
|
|
44
|
+
//
|
|
45
|
+
}};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2006-2007 Erin Catto http:
|
|
3
|
+
*
|
|
4
|
+
* This software is provided 'as-is', without any express or implied
|
|
5
|
+
* warranty. In no event will the authors be held liable for any damages
|
|
6
|
+
* arising from the use of this software.
|
|
7
|
+
* Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
* including commercial applications, and to alter it and redistribute it
|
|
9
|
+
* freely, subject to the following restrictions:
|
|
10
|
+
* 1. The origin of this software must not be misrepresented; you must not
|
|
11
|
+
* claim that you wrote the original software. If you use this software
|
|
12
|
+
* in a product, an acknowledgment in the product documentation would be
|
|
13
|
+
* appreciated but is not required.
|
|
14
|
+
* 2. Altered source versions must be plainly marked, and must not be
|
|
15
|
+
* misrepresented the original software.
|
|
16
|
+
* 3. This notice may not be removed or altered from any source distribution.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var b2Bound = Class.create();
|
|
22
|
+
b2Bound.prototype = {
|
|
23
|
+
IsLower: function(){ return (this.value & 1) == 0; },
|
|
24
|
+
IsUpper: function(){ return (this.value & 1) == 1; },
|
|
25
|
+
Swap: function(b){
|
|
26
|
+
var tempValue = this.value;
|
|
27
|
+
var tempProxyId = this.proxyId;
|
|
28
|
+
var tempStabbingCount = this.stabbingCount;
|
|
29
|
+
|
|
30
|
+
this.value = b.value;
|
|
31
|
+
this.proxyId = b.proxyId;
|
|
32
|
+
this.stabbingCount = b.stabbingCount;
|
|
33
|
+
|
|
34
|
+
b.value = tempValue;
|
|
35
|
+
b.proxyId = tempProxyId;
|
|
36
|
+
b.stabbingCount = tempStabbingCount;
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
value: 0,
|
|
40
|
+
proxyId: 0,
|
|
41
|
+
stabbingCount: 0,
|
|
42
|
+
|
|
43
|
+
initialize: function() {}}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2006-2007 Erin Catto http:
|
|
3
|
+
*
|
|
4
|
+
* This software is provided 'as-is', without any express or implied
|
|
5
|
+
* warranty. In no event will the authors be held liable for any damages
|
|
6
|
+
* arising from the use of this software.
|
|
7
|
+
* Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
* including commercial applications, and to alter it and redistribute it
|
|
9
|
+
* freely, subject to the following restrictions:
|
|
10
|
+
* 1. The origin of this software must not be misrepresented; you must not
|
|
11
|
+
* claim that you wrote the original software. If you use this software
|
|
12
|
+
* in a product, an acknowledgment in the product documentation would be
|
|
13
|
+
* appreciated but is not required.
|
|
14
|
+
* 2. Altered source versions must be plainly marked, and must not be
|
|
15
|
+
* misrepresented the original software.
|
|
16
|
+
* 3. This notice may not be removed or altered from any source distribution.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var b2BoundValues = Class.create();
|
|
22
|
+
b2BoundValues.prototype = {
|
|
23
|
+
lowerValues: [0,0],
|
|
24
|
+
upperValues: [0,0],
|
|
25
|
+
|
|
26
|
+
initialize: function() {
|
|
27
|
+
// initialize instance variables for references
|
|
28
|
+
this.lowerValues = [0,0];
|
|
29
|
+
this.upperValues = [0,0];
|
|
30
|
+
//
|
|
31
|
+
}}
|
|
@@ -0,0 +1,898 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2006-2007 Erin Catto http:
|
|
3
|
+
*
|
|
4
|
+
* This software is provided 'as-is', without any express or implied
|
|
5
|
+
* warranty. In no event will the authors be held liable for any damages
|
|
6
|
+
* arising from the use of this software.
|
|
7
|
+
* Permission is granted to anyone to use this software for any purpose,
|
|
8
|
+
* including commercial applications, and to alter it and redistribute it
|
|
9
|
+
* freely, subject to the following restrictions:
|
|
10
|
+
* 1. The origin of this software must not be misrepresented; you must not
|
|
11
|
+
* claim that you wrote the original software. If you use this software
|
|
12
|
+
* in a product, an acknowledgment in the product documentation would be
|
|
13
|
+
* appreciated but is not required.
|
|
14
|
+
* 2. Altered source versions must be plainly marked, and must not be
|
|
15
|
+
* misrepresented the original software.
|
|
16
|
+
* 3. This notice may not be removed or altered from any source distribution.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
This broad phase uses the Sweep and Prune algorithm in:
|
|
25
|
+
Collision Detection in Interactive 3D Environments by Gino van den Bergen
|
|
26
|
+
Also, some ideas, such integral values for fast compares comes from
|
|
27
|
+
Bullet (http:/www.bulletphysics.com).
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
// Notes:
|
|
32
|
+
// - we use bound arrays instead of linked lists for cache coherence.
|
|
33
|
+
// - we use quantized integral values for fast compares.
|
|
34
|
+
// - we use short indices rather than pointers to save memory.
|
|
35
|
+
// - we use a stabbing count for fast overlap queries (less than order N).
|
|
36
|
+
// - we also use a time stamp on each proxy to speed up the registration of
|
|
37
|
+
// overlap query results.
|
|
38
|
+
// - where possible, we compare bound indices instead of values to reduce
|
|
39
|
+
// cache misses (TODO_ERIN).
|
|
40
|
+
// - no broadphase is perfect and neither is this one: it is not great for huge
|
|
41
|
+
// worlds (use a multi-SAP instead), it is not great for large objects.
|
|
42
|
+
|
|
43
|
+
var b2BroadPhase = Class.create();
|
|
44
|
+
b2BroadPhase.prototype =
|
|
45
|
+
{
|
|
46
|
+
//public:
|
|
47
|
+
initialize: function(worldAABB, callback){
|
|
48
|
+
// initialize instance variables for references
|
|
49
|
+
this.m_pairManager = new b2PairManager();
|
|
50
|
+
this.m_proxyPool = new Array(b2Settings.b2_maxPairs);
|
|
51
|
+
this.m_bounds = new Array(2*b2Settings.b2_maxProxies);
|
|
52
|
+
this.m_queryResults = new Array(b2Settings.b2_maxProxies);
|
|
53
|
+
this.m_quantizationFactor = new b2Vec2();
|
|
54
|
+
//
|
|
55
|
+
|
|
56
|
+
//b2Settings.b2Assert(worldAABB.IsValid());
|
|
57
|
+
var i = 0;
|
|
58
|
+
|
|
59
|
+
this.m_pairManager.Initialize(this, callback);
|
|
60
|
+
|
|
61
|
+
this.m_worldAABB = worldAABB;
|
|
62
|
+
|
|
63
|
+
this.m_proxyCount = 0;
|
|
64
|
+
|
|
65
|
+
// query results
|
|
66
|
+
for (i = 0; i < b2Settings.b2_maxProxies; i++){
|
|
67
|
+
this.m_queryResults[i] = 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// bounds array
|
|
71
|
+
this.m_bounds = new Array(2);
|
|
72
|
+
for (i = 0; i < 2; i++){
|
|
73
|
+
this.m_bounds[i] = new Array(2*b2Settings.b2_maxProxies);
|
|
74
|
+
for (var j = 0; j < 2*b2Settings.b2_maxProxies; j++){
|
|
75
|
+
this.m_bounds[i][j] = new b2Bound();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//var d = b2Math.SubtractVV(worldAABB.maxVertex, worldAABB.minVertex);
|
|
80
|
+
var dX = worldAABB.maxVertex.x;
|
|
81
|
+
var dY = worldAABB.maxVertex.y;
|
|
82
|
+
dX -= worldAABB.minVertex.x;
|
|
83
|
+
dY -= worldAABB.minVertex.y;
|
|
84
|
+
|
|
85
|
+
this.m_quantizationFactor.x = b2Settings.USHRT_MAX / dX;
|
|
86
|
+
this.m_quantizationFactor.y = b2Settings.USHRT_MAX / dY;
|
|
87
|
+
|
|
88
|
+
var tProxy;
|
|
89
|
+
for (i = 0; i < b2Settings.b2_maxProxies - 1; ++i)
|
|
90
|
+
{
|
|
91
|
+
tProxy = new b2Proxy();
|
|
92
|
+
this.m_proxyPool[i] = tProxy;
|
|
93
|
+
tProxy.SetNext(i + 1);
|
|
94
|
+
tProxy.timeStamp = 0;
|
|
95
|
+
tProxy.overlapCount = b2BroadPhase.b2_invalid;
|
|
96
|
+
tProxy.userData = null;
|
|
97
|
+
}
|
|
98
|
+
tProxy = new b2Proxy();
|
|
99
|
+
this.m_proxyPool[b2Settings.b2_maxProxies-1] = tProxy;
|
|
100
|
+
tProxy.SetNext(b2Pair.b2_nullProxy);
|
|
101
|
+
tProxy.timeStamp = 0;
|
|
102
|
+
tProxy.overlapCount = b2BroadPhase.b2_invalid;
|
|
103
|
+
tProxy.userData = null;
|
|
104
|
+
this.m_freeProxy = 0;
|
|
105
|
+
|
|
106
|
+
this.m_timeStamp = 1;
|
|
107
|
+
this.m_queryResultCount = 0;
|
|
108
|
+
},
|
|
109
|
+
//~b2BroadPhase();
|
|
110
|
+
|
|
111
|
+
// Use this to see if your proxy is in range. If it is not in range,
|
|
112
|
+
// it should be destroyed. Otherwise you may get O(m^2) pairs, where m
|
|
113
|
+
// is the number of proxies that are out of range.
|
|
114
|
+
InRange: function(aabb){
|
|
115
|
+
//var d = b2Math.b2MaxV(b2Math.SubtractVV(aabb.minVertex, this.m_worldAABB.maxVertex), b2Math.SubtractVV(this.m_worldAABB.minVertex, aabb.maxVertex));
|
|
116
|
+
var dX;
|
|
117
|
+
var dY;
|
|
118
|
+
var d2X;
|
|
119
|
+
var d2Y;
|
|
120
|
+
|
|
121
|
+
dX = aabb.minVertex.x;
|
|
122
|
+
dY = aabb.minVertex.y;
|
|
123
|
+
dX -= this.m_worldAABB.maxVertex.x;
|
|
124
|
+
dY -= this.m_worldAABB.maxVertex.y;
|
|
125
|
+
|
|
126
|
+
d2X = this.m_worldAABB.minVertex.x;
|
|
127
|
+
d2Y = this.m_worldAABB.minVertex.y;
|
|
128
|
+
d2X -= aabb.maxVertex.x;
|
|
129
|
+
d2Y -= aabb.maxVertex.y;
|
|
130
|
+
|
|
131
|
+
dX = b2Math.b2Max(dX, d2X);
|
|
132
|
+
dY = b2Math.b2Max(dY, d2Y);
|
|
133
|
+
|
|
134
|
+
return b2Math.b2Max(dX, dY) < 0.0;
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// Get a single proxy. Returns NULL if the id is invalid.
|
|
138
|
+
GetProxy: function(proxyId){
|
|
139
|
+
if (proxyId == b2Pair.b2_nullProxy || this.m_proxyPool[proxyId].IsValid() == false)
|
|
140
|
+
{
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return this.m_proxyPool[ proxyId ];
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
// Create and destroy proxies. These call Flush first.
|
|
148
|
+
CreateProxy: function(aabb, userData){
|
|
149
|
+
var index = 0;
|
|
150
|
+
var proxy;
|
|
151
|
+
|
|
152
|
+
//b2Settings.b2Assert(this.m_proxyCount < b2_maxProxies);
|
|
153
|
+
//b2Settings.b2Assert(this.m_freeProxy != b2Pair.b2_nullProxy);
|
|
154
|
+
|
|
155
|
+
var proxyId = this.m_freeProxy;
|
|
156
|
+
proxy = this.m_proxyPool[ proxyId ];
|
|
157
|
+
this.m_freeProxy = proxy.GetNext();
|
|
158
|
+
|
|
159
|
+
proxy.overlapCount = 0;
|
|
160
|
+
proxy.userData = userData;
|
|
161
|
+
|
|
162
|
+
var boundCount = 2 * this.m_proxyCount;
|
|
163
|
+
|
|
164
|
+
var lowerValues = new Array();
|
|
165
|
+
var upperValues = new Array();
|
|
166
|
+
this.ComputeBounds(lowerValues, upperValues, aabb);
|
|
167
|
+
|
|
168
|
+
for (var axis = 0; axis < 2; ++axis)
|
|
169
|
+
{
|
|
170
|
+
var bounds = this.m_bounds[axis];
|
|
171
|
+
var lowerIndex = 0;
|
|
172
|
+
var upperIndex = 0;
|
|
173
|
+
var lowerIndexOut = [lowerIndex];
|
|
174
|
+
var upperIndexOut = [upperIndex];
|
|
175
|
+
this.Query(lowerIndexOut, upperIndexOut, lowerValues[axis], upperValues[axis], bounds, boundCount, axis);
|
|
176
|
+
lowerIndex = lowerIndexOut[0];
|
|
177
|
+
upperIndex = upperIndexOut[0];
|
|
178
|
+
|
|
179
|
+
// Replace memmove calls
|
|
180
|
+
//memmove(bounds + upperIndex + 2, bounds + upperIndex, (edgeCount - upperIndex) * sizeof(b2Bound));
|
|
181
|
+
var tArr = new Array();
|
|
182
|
+
var j = 0;
|
|
183
|
+
var tEnd = boundCount - upperIndex
|
|
184
|
+
var tBound1;
|
|
185
|
+
var tBound2;
|
|
186
|
+
// make temp array
|
|
187
|
+
for (j = 0; j < tEnd; j++){
|
|
188
|
+
tArr[j] = new b2Bound();
|
|
189
|
+
tBound1 = tArr[j];
|
|
190
|
+
tBound2 = bounds[upperIndex+j];
|
|
191
|
+
tBound1.value = tBound2.value;
|
|
192
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
193
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
194
|
+
}
|
|
195
|
+
// move temp array back in to bounds
|
|
196
|
+
tEnd = tArr.length;
|
|
197
|
+
var tIndex = upperIndex+2;
|
|
198
|
+
for (j = 0; j < tEnd; j++){
|
|
199
|
+
//bounds[tIndex+j] = tArr[j];
|
|
200
|
+
tBound2 = tArr[j];
|
|
201
|
+
tBound1 = bounds[tIndex+j]
|
|
202
|
+
tBound1.value = tBound2.value;
|
|
203
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
204
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
205
|
+
}
|
|
206
|
+
//memmove(bounds + lowerIndex + 1, bounds + lowerIndex, (upperIndex - lowerIndex) * sizeof(b2Bound));
|
|
207
|
+
// make temp array
|
|
208
|
+
tArr = new Array();
|
|
209
|
+
tEnd = upperIndex - lowerIndex;
|
|
210
|
+
for (j = 0; j < tEnd; j++){
|
|
211
|
+
tArr[j] = new b2Bound();
|
|
212
|
+
tBound1 = tArr[j];
|
|
213
|
+
tBound2 = bounds[lowerIndex+j];
|
|
214
|
+
tBound1.value = tBound2.value;
|
|
215
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
216
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
217
|
+
}
|
|
218
|
+
// move temp array back in to bounds
|
|
219
|
+
tEnd = tArr.length;
|
|
220
|
+
tIndex = lowerIndex+1;
|
|
221
|
+
for (j = 0; j < tEnd; j++){
|
|
222
|
+
//bounds[tIndex+j] = tArr[j];
|
|
223
|
+
tBound2 = tArr[j];
|
|
224
|
+
tBound1 = bounds[tIndex+j]
|
|
225
|
+
tBound1.value = tBound2.value;
|
|
226
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
227
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// The upper index has increased because of the lower bound insertion.
|
|
231
|
+
++upperIndex;
|
|
232
|
+
|
|
233
|
+
// Copy in the new bounds.
|
|
234
|
+
bounds[lowerIndex].value = lowerValues[axis];
|
|
235
|
+
bounds[lowerIndex].proxyId = proxyId;
|
|
236
|
+
bounds[upperIndex].value = upperValues[axis];
|
|
237
|
+
bounds[upperIndex].proxyId = proxyId;
|
|
238
|
+
|
|
239
|
+
bounds[lowerIndex].stabbingCount = lowerIndex == 0 ? 0 : bounds[lowerIndex-1].stabbingCount;
|
|
240
|
+
bounds[upperIndex].stabbingCount = bounds[upperIndex-1].stabbingCount;
|
|
241
|
+
|
|
242
|
+
// Adjust the stabbing count between the new bounds.
|
|
243
|
+
for (index = lowerIndex; index < upperIndex; ++index)
|
|
244
|
+
{
|
|
245
|
+
bounds[index].stabbingCount++;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Adjust the all the affected bound indices.
|
|
249
|
+
for (index = lowerIndex; index < boundCount + 2; ++index)
|
|
250
|
+
{
|
|
251
|
+
var proxy2 = this.m_proxyPool[ bounds[index].proxyId ];
|
|
252
|
+
if (bounds[index].IsLower())
|
|
253
|
+
{
|
|
254
|
+
proxy2.lowerBounds[axis] = index;
|
|
255
|
+
}
|
|
256
|
+
else
|
|
257
|
+
{
|
|
258
|
+
proxy2.upperBounds[axis] = index;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
++this.m_proxyCount;
|
|
264
|
+
|
|
265
|
+
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
|
266
|
+
|
|
267
|
+
for (var i = 0; i < this.m_queryResultCount; ++i)
|
|
268
|
+
{
|
|
269
|
+
//b2Settings.b2Assert(this.m_queryResults[i] < b2_maxProxies);
|
|
270
|
+
//b2Settings.b2Assert(this.m_proxyPool[this.m_queryResults[i]].IsValid());
|
|
271
|
+
|
|
272
|
+
this.m_pairManager.AddBufferedPair(proxyId, this.m_queryResults[i]);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
this.m_pairManager.Commit();
|
|
276
|
+
|
|
277
|
+
// Prepare for next query.
|
|
278
|
+
this.m_queryResultCount = 0;
|
|
279
|
+
this.IncrementTimeStamp();
|
|
280
|
+
|
|
281
|
+
return proxyId;
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
DestroyProxy: function(proxyId){
|
|
285
|
+
|
|
286
|
+
//b2Settings.b2Assert(0 < this.m_proxyCount && this.m_proxyCount <= b2_maxProxies);
|
|
287
|
+
|
|
288
|
+
var proxy = this.m_proxyPool[ proxyId ];
|
|
289
|
+
//b2Settings.b2Assert(proxy.IsValid());
|
|
290
|
+
|
|
291
|
+
var boundCount = 2 * this.m_proxyCount;
|
|
292
|
+
|
|
293
|
+
for (var axis = 0; axis < 2; ++axis)
|
|
294
|
+
{
|
|
295
|
+
var bounds = this.m_bounds[axis];
|
|
296
|
+
|
|
297
|
+
var lowerIndex = proxy.lowerBounds[axis];
|
|
298
|
+
var upperIndex = proxy.upperBounds[axis];
|
|
299
|
+
var lowerValue = bounds[lowerIndex].value;
|
|
300
|
+
var upperValue = bounds[upperIndex].value;
|
|
301
|
+
|
|
302
|
+
// replace memmove calls
|
|
303
|
+
//memmove(bounds + lowerIndex, bounds + lowerIndex + 1, (upperIndex - lowerIndex - 1) * sizeof(b2Bound));
|
|
304
|
+
var tArr = new Array();
|
|
305
|
+
var j = 0;
|
|
306
|
+
var tEnd = upperIndex - lowerIndex - 1;
|
|
307
|
+
var tBound1;
|
|
308
|
+
var tBound2;
|
|
309
|
+
// make temp array
|
|
310
|
+
for (j = 0; j < tEnd; j++){
|
|
311
|
+
tArr[j] = new b2Bound();
|
|
312
|
+
tBound1 = tArr[j];
|
|
313
|
+
tBound2 = bounds[lowerIndex+1+j];
|
|
314
|
+
tBound1.value = tBound2.value;
|
|
315
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
316
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
317
|
+
}
|
|
318
|
+
// move temp array back in to bounds
|
|
319
|
+
tEnd = tArr.length;
|
|
320
|
+
var tIndex = lowerIndex;
|
|
321
|
+
for (j = 0; j < tEnd; j++){
|
|
322
|
+
//bounds[tIndex+j] = tArr[j];
|
|
323
|
+
tBound2 = tArr[j];
|
|
324
|
+
tBound1 = bounds[tIndex+j]
|
|
325
|
+
tBound1.value = tBound2.value;
|
|
326
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
327
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
328
|
+
}
|
|
329
|
+
//memmove(bounds + upperIndex-1, bounds + upperIndex + 1, (edgeCount - upperIndex - 1) * sizeof(b2Bound));
|
|
330
|
+
// make temp array
|
|
331
|
+
tArr = new Array();
|
|
332
|
+
tEnd = boundCount - upperIndex - 1;
|
|
333
|
+
for (j = 0; j < tEnd; j++){
|
|
334
|
+
tArr[j] = new b2Bound();
|
|
335
|
+
tBound1 = tArr[j];
|
|
336
|
+
tBound2 = bounds[upperIndex+1+j];
|
|
337
|
+
tBound1.value = tBound2.value;
|
|
338
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
339
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
340
|
+
}
|
|
341
|
+
// move temp array back in to bounds
|
|
342
|
+
tEnd = tArr.length;
|
|
343
|
+
tIndex = upperIndex-1;
|
|
344
|
+
for (j = 0; j < tEnd; j++){
|
|
345
|
+
//bounds[tIndex+j] = tArr[j];
|
|
346
|
+
tBound2 = tArr[j];
|
|
347
|
+
tBound1 = bounds[tIndex+j]
|
|
348
|
+
tBound1.value = tBound2.value;
|
|
349
|
+
tBound1.proxyId = tBound2.proxyId;
|
|
350
|
+
tBound1.stabbingCount = tBound2.stabbingCount;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Fix bound indices.
|
|
354
|
+
tEnd = boundCount - 2;
|
|
355
|
+
for (var index = lowerIndex; index < tEnd; ++index)
|
|
356
|
+
{
|
|
357
|
+
var proxy2 = this.m_proxyPool[ bounds[index].proxyId ];
|
|
358
|
+
if (bounds[index].IsLower())
|
|
359
|
+
{
|
|
360
|
+
proxy2.lowerBounds[axis] = index;
|
|
361
|
+
}
|
|
362
|
+
else
|
|
363
|
+
{
|
|
364
|
+
proxy2.upperBounds[axis] = index;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Fix stabbing count.
|
|
369
|
+
tEnd = upperIndex - 1;
|
|
370
|
+
for (var index2 = lowerIndex; index2 < tEnd; ++index2)
|
|
371
|
+
{
|
|
372
|
+
bounds[index2].stabbingCount--;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// this.Query for pairs to be removed. lowerIndex and upperIndex are not needed.
|
|
376
|
+
// make lowerIndex and upper output using an array and do this for others if compiler doesn't pick them up
|
|
377
|
+
this.Query([0], [0], lowerValue, upperValue, bounds, boundCount - 2, axis);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
|
381
|
+
|
|
382
|
+
for (var i = 0; i < this.m_queryResultCount; ++i)
|
|
383
|
+
{
|
|
384
|
+
//b2Settings.b2Assert(this.m_proxyPool[this.m_queryResults[i]].IsValid());
|
|
385
|
+
|
|
386
|
+
this.m_pairManager.RemoveBufferedPair(proxyId, this.m_queryResults[i]);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
this.m_pairManager.Commit();
|
|
390
|
+
|
|
391
|
+
// Prepare for next query.
|
|
392
|
+
this.m_queryResultCount = 0;
|
|
393
|
+
this.IncrementTimeStamp();
|
|
394
|
+
|
|
395
|
+
// Return the proxy to the pool.
|
|
396
|
+
proxy.userData = null;
|
|
397
|
+
proxy.overlapCount = b2BroadPhase.b2_invalid;
|
|
398
|
+
proxy.lowerBounds[0] = b2BroadPhase.b2_invalid;
|
|
399
|
+
proxy.lowerBounds[1] = b2BroadPhase.b2_invalid;
|
|
400
|
+
proxy.upperBounds[0] = b2BroadPhase.b2_invalid;
|
|
401
|
+
proxy.upperBounds[1] = b2BroadPhase.b2_invalid;
|
|
402
|
+
|
|
403
|
+
proxy.SetNext(this.m_freeProxy);
|
|
404
|
+
this.m_freeProxy = proxyId;
|
|
405
|
+
--this.m_proxyCount;
|
|
406
|
+
},
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
// Call this.MoveProxy times like, then when you are done
|
|
410
|
+
// call this.Commit to finalized the proxy pairs (for your time step).
|
|
411
|
+
MoveProxy: function(proxyId, aabb){
|
|
412
|
+
var axis = 0;
|
|
413
|
+
var index = 0;
|
|
414
|
+
var bound;
|
|
415
|
+
var prevBound
|
|
416
|
+
var nextBound
|
|
417
|
+
var nextProxyId = 0;
|
|
418
|
+
var nextProxy;
|
|
419
|
+
|
|
420
|
+
if (proxyId == b2Pair.b2_nullProxy || b2Settings.b2_maxProxies <= proxyId)
|
|
421
|
+
{
|
|
422
|
+
//b2Settings.b2Assert(false);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (aabb.IsValid() == false)
|
|
427
|
+
{
|
|
428
|
+
//b2Settings.b2Assert(false);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
var boundCount = 2 * this.m_proxyCount;
|
|
433
|
+
|
|
434
|
+
var proxy = this.m_proxyPool[ proxyId ];
|
|
435
|
+
// Get new bound values
|
|
436
|
+
var newValues = new b2BoundValues();
|
|
437
|
+
this.ComputeBounds(newValues.lowerValues, newValues.upperValues, aabb);
|
|
438
|
+
|
|
439
|
+
// Get old bound values
|
|
440
|
+
var oldValues = new b2BoundValues();
|
|
441
|
+
for (axis = 0; axis < 2; ++axis)
|
|
442
|
+
{
|
|
443
|
+
oldValues.lowerValues[axis] = this.m_bounds[axis][proxy.lowerBounds[axis]].value;
|
|
444
|
+
oldValues.upperValues[axis] = this.m_bounds[axis][proxy.upperBounds[axis]].value;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
for (axis = 0; axis < 2; ++axis)
|
|
448
|
+
{
|
|
449
|
+
var bounds = this.m_bounds[axis];
|
|
450
|
+
|
|
451
|
+
var lowerIndex = proxy.lowerBounds[axis];
|
|
452
|
+
var upperIndex = proxy.upperBounds[axis];
|
|
453
|
+
|
|
454
|
+
var lowerValue = newValues.lowerValues[axis];
|
|
455
|
+
var upperValue = newValues.upperValues[axis];
|
|
456
|
+
|
|
457
|
+
var deltaLower = lowerValue - bounds[lowerIndex].value;
|
|
458
|
+
var deltaUpper = upperValue - bounds[upperIndex].value;
|
|
459
|
+
|
|
460
|
+
bounds[lowerIndex].value = lowerValue;
|
|
461
|
+
bounds[upperIndex].value = upperValue;
|
|
462
|
+
|
|
463
|
+
//
|
|
464
|
+
// Expanding adds overlaps
|
|
465
|
+
//
|
|
466
|
+
|
|
467
|
+
// Should we move the lower bound down?
|
|
468
|
+
if (deltaLower < 0)
|
|
469
|
+
{
|
|
470
|
+
index = lowerIndex;
|
|
471
|
+
while (index > 0 && lowerValue < bounds[index-1].value)
|
|
472
|
+
{
|
|
473
|
+
bound = bounds[index];
|
|
474
|
+
prevBound = bounds[index - 1];
|
|
475
|
+
|
|
476
|
+
var prevProxyId = prevBound.proxyId;
|
|
477
|
+
var prevProxy = this.m_proxyPool[ prevBound.proxyId ];
|
|
478
|
+
|
|
479
|
+
prevBound.stabbingCount++;
|
|
480
|
+
|
|
481
|
+
if (prevBound.IsUpper() == true)
|
|
482
|
+
{
|
|
483
|
+
if (this.TestOverlap(newValues, prevProxy))
|
|
484
|
+
{
|
|
485
|
+
this.m_pairManager.AddBufferedPair(proxyId, prevProxyId);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
prevProxy.upperBounds[axis]++;
|
|
489
|
+
bound.stabbingCount++;
|
|
490
|
+
}
|
|
491
|
+
else
|
|
492
|
+
{
|
|
493
|
+
prevProxy.lowerBounds[axis]++;
|
|
494
|
+
bound.stabbingCount--;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
proxy.lowerBounds[axis]--;
|
|
498
|
+
|
|
499
|
+
// swap
|
|
500
|
+
//var temp = bound;
|
|
501
|
+
//bound = prevEdge;
|
|
502
|
+
//prevEdge = temp;
|
|
503
|
+
bound.Swap(prevBound);
|
|
504
|
+
//b2Math.b2Swap(bound, prevEdge);
|
|
505
|
+
--index;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Should we move the upper bound up?
|
|
510
|
+
if (deltaUpper > 0)
|
|
511
|
+
{
|
|
512
|
+
index = upperIndex;
|
|
513
|
+
while (index < boundCount-1 && bounds[index+1].value <= upperValue)
|
|
514
|
+
{
|
|
515
|
+
bound = bounds[ index ];
|
|
516
|
+
nextBound = bounds[ index + 1 ];
|
|
517
|
+
nextProxyId = nextBound.proxyId;
|
|
518
|
+
nextProxy = this.m_proxyPool[ nextProxyId ];
|
|
519
|
+
|
|
520
|
+
nextBound.stabbingCount++;
|
|
521
|
+
|
|
522
|
+
if (nextBound.IsLower() == true)
|
|
523
|
+
{
|
|
524
|
+
if (this.TestOverlap(newValues, nextProxy))
|
|
525
|
+
{
|
|
526
|
+
this.m_pairManager.AddBufferedPair(proxyId, nextProxyId);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
nextProxy.lowerBounds[axis]--;
|
|
530
|
+
bound.stabbingCount++;
|
|
531
|
+
}
|
|
532
|
+
else
|
|
533
|
+
{
|
|
534
|
+
nextProxy.upperBounds[axis]--;
|
|
535
|
+
bound.stabbingCount--;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
proxy.upperBounds[axis]++;
|
|
539
|
+
// swap
|
|
540
|
+
//var temp = bound;
|
|
541
|
+
//bound = nextEdge;
|
|
542
|
+
//nextEdge = temp;
|
|
543
|
+
bound.Swap(nextBound);
|
|
544
|
+
//b2Math.b2Swap(bound, nextEdge);
|
|
545
|
+
index++;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
//
|
|
550
|
+
// Shrinking removes overlaps
|
|
551
|
+
//
|
|
552
|
+
|
|
553
|
+
// Should we move the lower bound up?
|
|
554
|
+
if (deltaLower > 0)
|
|
555
|
+
{
|
|
556
|
+
index = lowerIndex;
|
|
557
|
+
while (index < boundCount-1 && bounds[index+1].value <= lowerValue)
|
|
558
|
+
{
|
|
559
|
+
bound = bounds[ index ];
|
|
560
|
+
nextBound = bounds[ index + 1 ];
|
|
561
|
+
|
|
562
|
+
nextProxyId = nextBound.proxyId;
|
|
563
|
+
nextProxy = this.m_proxyPool[ nextProxyId ];
|
|
564
|
+
|
|
565
|
+
nextBound.stabbingCount--;
|
|
566
|
+
|
|
567
|
+
if (nextBound.IsUpper())
|
|
568
|
+
{
|
|
569
|
+
if (this.TestOverlap(oldValues, nextProxy))
|
|
570
|
+
{
|
|
571
|
+
this.m_pairManager.RemoveBufferedPair(proxyId, nextProxyId);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
nextProxy.upperBounds[axis]--;
|
|
575
|
+
bound.stabbingCount--;
|
|
576
|
+
}
|
|
577
|
+
else
|
|
578
|
+
{
|
|
579
|
+
nextProxy.lowerBounds[axis]--;
|
|
580
|
+
bound.stabbingCount++;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
proxy.lowerBounds[axis]++;
|
|
584
|
+
// swap
|
|
585
|
+
//var temp = bound;
|
|
586
|
+
//bound = nextEdge;
|
|
587
|
+
//nextEdge = temp;
|
|
588
|
+
bound.Swap(nextBound);
|
|
589
|
+
//b2Math.b2Swap(bound, nextEdge);
|
|
590
|
+
index++;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Should we move the upper bound down?
|
|
595
|
+
if (deltaUpper < 0)
|
|
596
|
+
{
|
|
597
|
+
index = upperIndex;
|
|
598
|
+
while (index > 0 && upperValue < bounds[index-1].value)
|
|
599
|
+
{
|
|
600
|
+
bound = bounds[index];
|
|
601
|
+
prevBound = bounds[index - 1];
|
|
602
|
+
|
|
603
|
+
prevProxyId = prevBound.proxyId;
|
|
604
|
+
prevProxy = this.m_proxyPool[ prevProxyId ];
|
|
605
|
+
|
|
606
|
+
prevBound.stabbingCount--;
|
|
607
|
+
|
|
608
|
+
if (prevBound.IsLower() == true)
|
|
609
|
+
{
|
|
610
|
+
if (this.TestOverlap(oldValues, prevProxy))
|
|
611
|
+
{
|
|
612
|
+
this.m_pairManager.RemoveBufferedPair(proxyId, prevProxyId);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
prevProxy.lowerBounds[axis]++;
|
|
616
|
+
bound.stabbingCount--;
|
|
617
|
+
}
|
|
618
|
+
else
|
|
619
|
+
{
|
|
620
|
+
prevProxy.upperBounds[axis]++;
|
|
621
|
+
bound.stabbingCount++;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
proxy.upperBounds[axis]--;
|
|
625
|
+
// swap
|
|
626
|
+
//var temp = bound;
|
|
627
|
+
//bound = prevEdge;
|
|
628
|
+
//prevEdge = temp;
|
|
629
|
+
bound.Swap(prevBound);
|
|
630
|
+
//b2Math.b2Swap(bound, prevEdge);
|
|
631
|
+
index--;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
},
|
|
636
|
+
|
|
637
|
+
Commit: function(){
|
|
638
|
+
this.m_pairManager.Commit();
|
|
639
|
+
},
|
|
640
|
+
|
|
641
|
+
// this.Query an AABB for overlapping proxies, returns the user data and
|
|
642
|
+
// the count, up to the supplied maximum count.
|
|
643
|
+
QueryAABB: function(aabb, userData, maxCount){
|
|
644
|
+
var lowerValues = new Array();
|
|
645
|
+
var upperValues = new Array();
|
|
646
|
+
this.ComputeBounds(lowerValues, upperValues, aabb);
|
|
647
|
+
|
|
648
|
+
var lowerIndex = 0;
|
|
649
|
+
var upperIndex = 0;
|
|
650
|
+
var lowerIndexOut = [lowerIndex];
|
|
651
|
+
var upperIndexOut = [upperIndex];
|
|
652
|
+
this.Query(lowerIndexOut, upperIndexOut, lowerValues[0], upperValues[0], this.m_bounds[0], 2*this.m_proxyCount, 0);
|
|
653
|
+
this.Query(lowerIndexOut, upperIndexOut, lowerValues[1], upperValues[1], this.m_bounds[1], 2*this.m_proxyCount, 1);
|
|
654
|
+
|
|
655
|
+
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
|
656
|
+
|
|
657
|
+
var count = 0;
|
|
658
|
+
for (var i = 0; i < this.m_queryResultCount && count < maxCount; ++i, ++count)
|
|
659
|
+
{
|
|
660
|
+
//b2Settings.b2Assert(this.m_queryResults[i] < b2Settings.b2_maxProxies);
|
|
661
|
+
var proxy = this.m_proxyPool[ this.m_queryResults[i] ];
|
|
662
|
+
//b2Settings.b2Assert(proxy.IsValid());
|
|
663
|
+
userData[i] = proxy.userData;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Prepare for next query.
|
|
667
|
+
this.m_queryResultCount = 0;
|
|
668
|
+
this.IncrementTimeStamp();
|
|
669
|
+
|
|
670
|
+
return count;
|
|
671
|
+
},
|
|
672
|
+
|
|
673
|
+
Validate: function(){
|
|
674
|
+
var pair;
|
|
675
|
+
var proxy1;
|
|
676
|
+
var proxy2;
|
|
677
|
+
var overlap;
|
|
678
|
+
|
|
679
|
+
for (var axis = 0; axis < 2; ++axis)
|
|
680
|
+
{
|
|
681
|
+
var bounds = this.m_bounds[axis];
|
|
682
|
+
|
|
683
|
+
var boundCount = 2 * this.m_proxyCount;
|
|
684
|
+
var stabbingCount = 0;
|
|
685
|
+
|
|
686
|
+
for (var i = 0; i < boundCount; ++i)
|
|
687
|
+
{
|
|
688
|
+
var bound = bounds[i];
|
|
689
|
+
//b2Settings.b2Assert(i == 0 || bounds[i-1].value <= bound->value);
|
|
690
|
+
//b2Settings.b2Assert(bound->proxyId != b2_nullProxy);
|
|
691
|
+
//b2Settings.b2Assert(this.m_proxyPool[bound->proxyId].IsValid());
|
|
692
|
+
|
|
693
|
+
if (bound.IsLower() == true)
|
|
694
|
+
{
|
|
695
|
+
//b2Settings.b2Assert(this.m_proxyPool[bound.proxyId].lowerBounds[axis] == i);
|
|
696
|
+
stabbingCount++;
|
|
697
|
+
}
|
|
698
|
+
else
|
|
699
|
+
{
|
|
700
|
+
//b2Settings.b2Assert(this.m_proxyPool[bound.proxyId].upperBounds[axis] == i);
|
|
701
|
+
stabbingCount--;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
//b2Settings.b2Assert(bound.stabbingCount == stabbingCount);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
},
|
|
709
|
+
|
|
710
|
+
//private:
|
|
711
|
+
ComputeBounds: function(lowerValues, upperValues, aabb)
|
|
712
|
+
{
|
|
713
|
+
//b2Settings.b2Assert(aabb.maxVertex.x > aabb.minVertex.x);
|
|
714
|
+
//b2Settings.b2Assert(aabb.maxVertex.y > aabb.minVertex.y);
|
|
715
|
+
|
|
716
|
+
//var minVertex = b2Math.b2ClampV(aabb.minVertex, this.m_worldAABB.minVertex, this.m_worldAABB.maxVertex);
|
|
717
|
+
var minVertexX = aabb.minVertex.x;
|
|
718
|
+
var minVertexY = aabb.minVertex.y;
|
|
719
|
+
minVertexX = b2Math.b2Min(minVertexX, this.m_worldAABB.maxVertex.x);
|
|
720
|
+
minVertexY = b2Math.b2Min(minVertexY, this.m_worldAABB.maxVertex.y);
|
|
721
|
+
minVertexX = b2Math.b2Max(minVertexX, this.m_worldAABB.minVertex.x);
|
|
722
|
+
minVertexY = b2Math.b2Max(minVertexY, this.m_worldAABB.minVertex.y);
|
|
723
|
+
|
|
724
|
+
//var maxVertex = b2Math.b2ClampV(aabb.maxVertex, this.m_worldAABB.minVertex, this.m_worldAABB.maxVertex);
|
|
725
|
+
var maxVertexX = aabb.maxVertex.x;
|
|
726
|
+
var maxVertexY = aabb.maxVertex.y;
|
|
727
|
+
maxVertexX = b2Math.b2Min(maxVertexX, this.m_worldAABB.maxVertex.x);
|
|
728
|
+
maxVertexY = b2Math.b2Min(maxVertexY, this.m_worldAABB.maxVertex.y);
|
|
729
|
+
maxVertexX = b2Math.b2Max(maxVertexX, this.m_worldAABB.minVertex.x);
|
|
730
|
+
maxVertexY = b2Math.b2Max(maxVertexY, this.m_worldAABB.minVertex.y);
|
|
731
|
+
|
|
732
|
+
// Bump lower bounds downs and upper bounds up. This ensures correct sorting of
|
|
733
|
+
// lower/upper bounds that would have equal values.
|
|
734
|
+
// TODO_ERIN implement fast float to uint16 conversion.
|
|
735
|
+
lowerValues[0] = /*uint*/(this.m_quantizationFactor.x * (minVertexX - this.m_worldAABB.minVertex.x)) & (b2Settings.USHRT_MAX - 1);
|
|
736
|
+
upperValues[0] = (/*uint*/(this.m_quantizationFactor.x * (maxVertexX - this.m_worldAABB.minVertex.x))& 0x0000ffff) | 1;
|
|
737
|
+
|
|
738
|
+
lowerValues[1] = /*uint*/(this.m_quantizationFactor.y * (minVertexY - this.m_worldAABB.minVertex.y)) & (b2Settings.USHRT_MAX - 1);
|
|
739
|
+
upperValues[1] = (/*uint*/(this.m_quantizationFactor.y * (maxVertexY - this.m_worldAABB.minVertex.y))& 0x0000ffff) | 1;
|
|
740
|
+
},
|
|
741
|
+
|
|
742
|
+
// This one is only used for validation.
|
|
743
|
+
TestOverlapValidate: function(p1, p2){
|
|
744
|
+
|
|
745
|
+
for (var axis = 0; axis < 2; ++axis)
|
|
746
|
+
{
|
|
747
|
+
var bounds = this.m_bounds[axis];
|
|
748
|
+
|
|
749
|
+
//b2Settings.b2Assert(p1.lowerBounds[axis] < 2 * this.m_proxyCount);
|
|
750
|
+
//b2Settings.b2Assert(p1.upperBounds[axis] < 2 * this.m_proxyCount);
|
|
751
|
+
//b2Settings.b2Assert(p2.lowerBounds[axis] < 2 * this.m_proxyCount);
|
|
752
|
+
//b2Settings.b2Assert(p2.upperBounds[axis] < 2 * this.m_proxyCount);
|
|
753
|
+
|
|
754
|
+
if (bounds[p1.lowerBounds[axis]].value > bounds[p2.upperBounds[axis]].value)
|
|
755
|
+
return false;
|
|
756
|
+
|
|
757
|
+
if (bounds[p1.upperBounds[axis]].value < bounds[p2.lowerBounds[axis]].value)
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
return true;
|
|
762
|
+
},
|
|
763
|
+
|
|
764
|
+
TestOverlap: function(b, p)
|
|
765
|
+
{
|
|
766
|
+
for (var axis = 0; axis < 2; ++axis)
|
|
767
|
+
{
|
|
768
|
+
var bounds = this.m_bounds[axis];
|
|
769
|
+
|
|
770
|
+
//b2Settings.b2Assert(p.lowerBounds[axis] < 2 * this.m_proxyCount);
|
|
771
|
+
//b2Settings.b2Assert(p.upperBounds[axis] < 2 * this.m_proxyCount);
|
|
772
|
+
|
|
773
|
+
if (b.lowerValues[axis] > bounds[p.upperBounds[axis]].value)
|
|
774
|
+
return false;
|
|
775
|
+
|
|
776
|
+
if (b.upperValues[axis] < bounds[p.lowerBounds[axis]].value)
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
return true;
|
|
781
|
+
},
|
|
782
|
+
|
|
783
|
+
Query: function(lowerQueryOut, upperQueryOut, lowerValue, upperValue, bounds, boundCount, axis){
|
|
784
|
+
|
|
785
|
+
var lowerQuery = b2BroadPhase.BinarySearch(bounds, boundCount, lowerValue);
|
|
786
|
+
var upperQuery = b2BroadPhase.BinarySearch(bounds, boundCount, upperValue);
|
|
787
|
+
|
|
788
|
+
// Easy case: lowerQuery <= lowerIndex(i) < upperQuery
|
|
789
|
+
// Solution: search query range for min bounds.
|
|
790
|
+
for (var j = lowerQuery; j < upperQuery; ++j)
|
|
791
|
+
{
|
|
792
|
+
if (bounds[j].IsLower())
|
|
793
|
+
{
|
|
794
|
+
this.IncrementOverlapCount(bounds[j].proxyId);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// Hard case: lowerIndex(i) < lowerQuery < upperIndex(i)
|
|
799
|
+
// Solution: use the stabbing count to search down the bound array.
|
|
800
|
+
if (lowerQuery > 0)
|
|
801
|
+
{
|
|
802
|
+
var i = lowerQuery - 1;
|
|
803
|
+
var s = bounds[i].stabbingCount;
|
|
804
|
+
|
|
805
|
+
// Find the s overlaps.
|
|
806
|
+
while (s)
|
|
807
|
+
{
|
|
808
|
+
//b2Settings.b2Assert(i >= 0);
|
|
809
|
+
|
|
810
|
+
if (bounds[i].IsLower())
|
|
811
|
+
{
|
|
812
|
+
var proxy = this.m_proxyPool[ bounds[i].proxyId ];
|
|
813
|
+
if (lowerQuery <= proxy.upperBounds[axis])
|
|
814
|
+
{
|
|
815
|
+
this.IncrementOverlapCount(bounds[i].proxyId);
|
|
816
|
+
--s;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
--i;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
lowerQueryOut[0] = lowerQuery;
|
|
824
|
+
upperQueryOut[0] = upperQuery;
|
|
825
|
+
},
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
IncrementOverlapCount: function(proxyId){
|
|
829
|
+
var proxy = this.m_proxyPool[ proxyId ];
|
|
830
|
+
if (proxy.timeStamp < this.m_timeStamp)
|
|
831
|
+
{
|
|
832
|
+
proxy.timeStamp = this.m_timeStamp;
|
|
833
|
+
proxy.overlapCount = 1;
|
|
834
|
+
}
|
|
835
|
+
else
|
|
836
|
+
{
|
|
837
|
+
proxy.overlapCount = 2;
|
|
838
|
+
//b2Settings.b2Assert(this.m_queryResultCount < b2Settings.b2_maxProxies);
|
|
839
|
+
this.m_queryResults[this.m_queryResultCount] = proxyId;
|
|
840
|
+
++this.m_queryResultCount;
|
|
841
|
+
}
|
|
842
|
+
},
|
|
843
|
+
IncrementTimeStamp: function(){
|
|
844
|
+
if (this.m_timeStamp == b2Settings.USHRT_MAX)
|
|
845
|
+
{
|
|
846
|
+
for (var i = 0; i < b2Settings.b2_maxProxies; ++i)
|
|
847
|
+
{
|
|
848
|
+
this.m_proxyPool[i].timeStamp = 0;
|
|
849
|
+
}
|
|
850
|
+
this.m_timeStamp = 1;
|
|
851
|
+
}
|
|
852
|
+
else
|
|
853
|
+
{
|
|
854
|
+
++this.m_timeStamp;
|
|
855
|
+
}
|
|
856
|
+
},
|
|
857
|
+
|
|
858
|
+
//public:
|
|
859
|
+
m_pairManager: new b2PairManager(),
|
|
860
|
+
|
|
861
|
+
m_proxyPool: new Array(b2Settings.b2_maxPairs),
|
|
862
|
+
m_freeProxy: 0,
|
|
863
|
+
|
|
864
|
+
m_bounds: new Array(2*b2Settings.b2_maxProxies),
|
|
865
|
+
|
|
866
|
+
m_queryResults: new Array(b2Settings.b2_maxProxies),
|
|
867
|
+
m_queryResultCount: 0,
|
|
868
|
+
|
|
869
|
+
m_worldAABB: null,
|
|
870
|
+
m_quantizationFactor: new b2Vec2(),
|
|
871
|
+
m_proxyCount: 0,
|
|
872
|
+
m_timeStamp: 0};
|
|
873
|
+
b2BroadPhase.s_validate = false;
|
|
874
|
+
b2BroadPhase.b2_invalid = b2Settings.USHRT_MAX;
|
|
875
|
+
b2BroadPhase.b2_nullEdge = b2Settings.USHRT_MAX;
|
|
876
|
+
b2BroadPhase.BinarySearch = function(bounds, count, value)
|
|
877
|
+
{
|
|
878
|
+
var low = 0;
|
|
879
|
+
var high = count - 1;
|
|
880
|
+
while (low <= high)
|
|
881
|
+
{
|
|
882
|
+
var mid = Math.floor((low + high) / 2);
|
|
883
|
+
if (bounds[mid].value > value)
|
|
884
|
+
{
|
|
885
|
+
high = mid - 1;
|
|
886
|
+
}
|
|
887
|
+
else if (bounds[mid].value < value)
|
|
888
|
+
{
|
|
889
|
+
low = mid + 1;
|
|
890
|
+
}
|
|
891
|
+
else
|
|
892
|
+
{
|
|
893
|
+
return /*uint*/(mid);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
return /*uint*/(low);
|
|
898
|
+
};
|