├── .gitignore ├── Box2D ├── Collision │ ├── Shapes │ │ ├── b2ChainShape.js │ │ ├── b2CircleShape.js │ │ ├── b2EdgeShape.js │ │ ├── b2PolygonShape.js │ │ └── b2Shape.js │ ├── b2BroadPhase.js │ ├── b2CollideCircle.js │ ├── b2CollideEdge.js │ ├── b2CollidePolygon.js │ ├── b2Collision.js │ ├── b2Distance.js │ ├── b2DynamicTree.js │ └── b2TimeOfImpact.js ├── Common │ ├── b2BlockAllocator.js │ ├── b2Draw.js │ ├── b2GrowableStack.js │ ├── b2Math.js │ ├── b2Settings.js │ ├── b2StackAllocator.js │ └── b2Timer.js ├── Dynamics │ ├── Contacts │ │ ├── b2ChainAndCircleContact.js │ │ ├── b2ChainAndPolygonContact.js │ │ ├── b2CircleContact.js │ │ ├── b2Contact.js │ │ ├── b2ContactFactory.js │ │ ├── b2ContactSolver.js │ │ ├── b2EdgeAndCircleContact.js │ │ ├── b2EdgeAndPolygonContact.js │ │ ├── b2PolygonAndCircleContact.js │ │ └── b2PolygonContact.js │ ├── Joints │ │ ├── b2AreaJoint.js │ │ ├── b2DistanceJoint.js │ │ ├── b2FrictionJoint.js │ │ ├── b2GearJoint.js │ │ ├── b2Joint.js │ │ ├── b2JointFactory.js │ │ ├── b2MotorJoint.js │ │ ├── b2MouseJoint.js │ │ ├── b2PrismaticJoint.js │ │ ├── b2PulleyJoint.js │ │ ├── b2RevoluteJoint.js │ │ ├── b2RopeJoint.js │ │ ├── b2WeldJoint.js │ │ └── b2WheelJoint.js │ ├── b2Body.js │ ├── b2ContactManager.js │ ├── b2Fixture.js │ ├── b2Island.js │ ├── b2TimeStep.js │ ├── b2World.js │ └── b2WorldCallbacks.js ├── Particle │ ├── b2Particle.js │ ├── b2ParticleGroup.js │ ├── b2ParticleSystem.js │ ├── b2StackQueue.js │ └── b2VoronoiDiagram.js └── Rope │ └── b2Rope.js ├── Contributions ├── Enhancements │ └── Controllers │ │ ├── b2BuoyancyController.js │ │ ├── b2ConstantAccelController.js │ │ ├── b2ConstantForceController.js │ │ ├── b2Controller.js │ │ ├── b2GravityController.js │ │ └── b2TensorDampingController.js └── Readme.txt ├── README.md ├── Renderer.js ├── box2d.ext.js ├── index.html ├── inherit.js └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | google 3 | Box2D/Build/google/closure-compiler 4 | Box2D/Build/google/closure-library 5 | -------------------------------------------------------------------------------- /Box2D/Collision/Shapes/b2CircleShape.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2CircleShape'); 20 | 21 | // goog.require('box2d.b2Shape'); 22 | 23 | /** 24 | * A circle shape. 25 | * @export 26 | * @constructor 27 | * @extends {box2d.b2Shape} 28 | * @param {number=} radius 29 | */ 30 | box2d.b2CircleShape = function(radius) { 31 | box2d.b2Shape.call(this, box2d.b2ShapeType.e_circleShape, radius || 0); // base class constructor 32 | 33 | this.m_p = new box2d.b2Vec2(); 34 | } 35 | 36 | box2d.b2CircleShape.prototype = new box2d.b2Shape(); 37 | 38 | /** 39 | * @export 40 | * @type {box2d.b2Vec2} 41 | */ 42 | box2d.b2CircleShape.prototype.m_p = null; 43 | 44 | /** 45 | * Implement box2d.b2Shape. 46 | * @export 47 | * @return {box2d.b2Shape} 48 | */ 49 | box2d.b2CircleShape.prototype.Clone = function() { 50 | return new box2d.b2CircleShape().Copy(this); 51 | } 52 | 53 | /** 54 | * @export 55 | * @return {box2d.b2Shape} 56 | * @param {box2d.b2Shape} other 57 | */ 58 | box2d.b2CircleShape.prototype.Copy = function(other) { 59 | box2d.b2Shape.prototype.Copy.call(this, other); 60 | 61 | if (box2d.ENABLE_ASSERTS) { 62 | box2d.b2Assert(other instanceof box2d.b2CircleShape); 63 | } 64 | 65 | this.m_p.Copy(other.m_p); 66 | return this; 67 | } 68 | 69 | /** 70 | * Implement box2d.b2Shape. 71 | * @export 72 | * @return {number} 73 | */ 74 | box2d.b2CircleShape.prototype.GetChildCount = function() { 75 | return 1; 76 | } 77 | 78 | /** 79 | * Implement box2d.b2Shape. 80 | * @export 81 | * @return {boolean} 82 | * @param {box2d.b2Transform} transform 83 | * @param {box2d.b2Vec2} p 84 | */ 85 | box2d.b2CircleShape.prototype.TestPoint = function(transform, p) { 86 | var center = box2d.b2Mul_X_V2(transform, this.m_p, box2d.b2CircleShape.prototype.TestPoint.s_center); 87 | var d = box2d.b2Sub_V2_V2(p, center, box2d.b2CircleShape.prototype.TestPoint.s_d); 88 | return box2d.b2Dot_V2_V2(d, d) <= box2d.b2Sq(this.m_radius); 89 | } 90 | box2d.b2CircleShape.prototype.TestPoint.s_center = new box2d.b2Vec2(); 91 | box2d.b2CircleShape.prototype.TestPoint.s_d = new box2d.b2Vec2(); 92 | 93 | //#if B2_ENABLE_PARTICLE 94 | 95 | /** 96 | * @see b2Shape::ComputeDistance 97 | * @export 98 | * @return {number} 99 | * @param {box2d.b2Transform} xf 100 | * @param {box2d.b2Vec2} p 101 | * @param {box2d.b2Vec2} normal 102 | * @param {number} childIndex 103 | */ 104 | box2d.b2CircleShape.prototype.ComputeDistance = function(xf, p, normal, childIndex) { 105 | var center = box2d.b2Mul_X_V2(xf, this.m_p, box2d.b2CircleShape.prototype.ComputeDistance.s_center); 106 | var d = box2d.b2Sub_V2_V2(p, center, normal); 107 | return normal.Normalize() - this.m_radius; 108 | } 109 | box2d.b2CircleShape.prototype.ComputeDistance.s_center = new box2d.b2Vec2(); 110 | 111 | //#endif 112 | 113 | /** 114 | * Implement box2d.b2Shape. 115 | * Collision Detection in Interactive 3D Environments by Gino 116 | * van den Bergen From Section 3.1.2 117 | * x = s + a * r 118 | * norm(x) = radius 119 | * @export 120 | * @return {boolean} 121 | * @param {box2d.b2RayCastOutput} output 122 | * @param {box2d.b2RayCastInput} input 123 | * @param {box2d.b2Transform} transform 124 | * @param {number} childIndex 125 | */ 126 | box2d.b2CircleShape.prototype.RayCast = function(output, input, transform, childIndex) { 127 | var position = box2d.b2Mul_X_V2(transform, this.m_p, box2d.b2CircleShape.prototype.RayCast.s_position); 128 | var s = box2d.b2Sub_V2_V2(input.p1, position, box2d.b2CircleShape.prototype.RayCast.s_s); 129 | var b = box2d.b2Dot_V2_V2(s, s) - box2d.b2Sq(this.m_radius); 130 | 131 | // Solve quadratic equation. 132 | var r = box2d.b2Sub_V2_V2(input.p2, input.p1, box2d.b2CircleShape.prototype.RayCast.s_r); 133 | var c = box2d.b2Dot_V2_V2(s, r); 134 | var rr = box2d.b2Dot_V2_V2(r, r); 135 | var sigma = c * c - rr * b; 136 | 137 | // Check for negative discriminant and short segment. 138 | if (sigma < 0 || rr < box2d.b2_epsilon) { 139 | return false; 140 | } 141 | 142 | // Find the point of intersection of the line with the circle. 143 | var a = (-(c + box2d.b2Sqrt(sigma))); 144 | 145 | // Is the intersection point on the segment? 146 | if (0 <= a && a <= input.maxFraction * rr) { 147 | a /= rr; 148 | output.fraction = a; 149 | box2d.b2AddMul_V2_S_V2(s, a, r, output.normal).SelfNormalize(); 150 | return true; 151 | } 152 | 153 | return false; 154 | } 155 | box2d.b2CircleShape.prototype.RayCast.s_position = new box2d.b2Vec2(); 156 | box2d.b2CircleShape.prototype.RayCast.s_s = new box2d.b2Vec2(); 157 | box2d.b2CircleShape.prototype.RayCast.s_r = new box2d.b2Vec2(); 158 | 159 | /** 160 | * @see box2d.b2Shape::ComputeAABB 161 | * @export 162 | * @return {void} 163 | * @param {box2d.b2AABB} aabb 164 | * @param {box2d.b2Transform} transform 165 | * @param {number} childIndex 166 | */ 167 | box2d.b2CircleShape.prototype.ComputeAABB = function(aabb, transform, childIndex) { 168 | var p = box2d.b2Mul_X_V2(transform, this.m_p, box2d.b2CircleShape.prototype.ComputeAABB.s_p); 169 | aabb.lowerBound.Set(p.x - this.m_radius, p.y - this.m_radius); 170 | aabb.upperBound.Set(p.x + this.m_radius, p.y + this.m_radius); 171 | } 172 | box2d.b2CircleShape.prototype.ComputeAABB.s_p = new box2d.b2Vec2(); 173 | 174 | /** 175 | * @see box2d.b2Shape::ComputeMass 176 | * @export 177 | * @return {void} 178 | * @param {box2d.b2MassData} massData 179 | * @param {number} density 180 | */ 181 | box2d.b2CircleShape.prototype.ComputeMass = function(massData, density) { 182 | var radius_sq = box2d.b2Sq(this.m_radius); 183 | massData.mass = density * box2d.b2_pi * radius_sq; 184 | massData.center.Copy(this.m_p); 185 | 186 | // inertia about the local origin 187 | massData.I = massData.mass * (0.5 * radius_sq + box2d.b2Dot_V2_V2(this.m_p, this.m_p)); 188 | } 189 | 190 | /** 191 | * @return {void} 192 | * @param {box2d.b2DistanceProxy} proxy 193 | * @param {number} index 194 | */ 195 | box2d.b2CircleShape.prototype.SetupDistanceProxy = function(proxy, index) { 196 | proxy.m_vertices = proxy.m_buffer; 197 | proxy.m_vertices[0].Copy(this.m_p); 198 | proxy.m_count = 1; 199 | proxy.m_radius = this.m_radius; 200 | } 201 | 202 | /** 203 | * @export 204 | * @return {number} 205 | * @param {box2d.b2Vec2} normal 206 | * @param {number} offset 207 | * @param {box2d.b2Transform} xf 208 | * @param {box2d.b2Vec2} c 209 | */ 210 | box2d.b2CircleShape.prototype.ComputeSubmergedArea = function(normal, offset, xf, c) { 211 | /** @type {box2d.b2Vec2} */ 212 | var p = box2d.b2Mul_X_V2(xf, this.m_p, new box2d.b2Vec2()); 213 | /** @type {number} */ 214 | var l = (-(box2d.b2Dot_V2_V2(normal, p) - offset)); 215 | 216 | if (l < (-this.m_radius) + box2d.b2_epsilon) { 217 | //Completely dry 218 | return 0; 219 | } 220 | if (l > this.m_radius) { 221 | //Completely wet 222 | c.Copy(p); 223 | return box2d.b2_pi * this.m_radius * this.m_radius; 224 | } 225 | 226 | //Magic 227 | /** @type {number} */ 228 | var r2 = this.m_radius * this.m_radius; 229 | /** @type {number} */ 230 | var l2 = l * l; 231 | /** @type {number} */ 232 | var area = r2 * (box2d.b2Asin(l / this.m_radius) + box2d.b2_pi / 2) + l * box2d.b2Sqrt(r2 - l2); 233 | /** @type {number} */ 234 | var com = (-2 / 3 * box2d.b2Pow(r2 - l2, 1.5) / area); 235 | 236 | c.x = p.x + normal.x * com; 237 | c.y = p.y + normal.y * com; 238 | 239 | return area; 240 | } 241 | 242 | /** 243 | * Dump this shape to the log file. 244 | * @export 245 | * @return {void} 246 | */ 247 | box2d.b2CircleShape.prototype.Dump = function() { 248 | box2d.b2Log(" /*box2d.b2CircleShape*/ var shape = new box2d.b2CircleShape();\n"); 249 | box2d.b2Log(" shape.m_radius = %.15f;\n", this.m_radius); 250 | box2d.b2Log(" shape.m_p.Set(%.15f, %.15f);\n", this.m_p.x, this.m_p.y); 251 | } 252 | -------------------------------------------------------------------------------- /Box2D/Collision/Shapes/b2EdgeShape.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2010 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2EdgeShape'); 20 | 21 | // goog.require('box2d.b2Shape'); 22 | 23 | /** 24 | * A line segment (edge) shape. These can be connected in chains 25 | * or loops to other edge shapes. The connectivity information 26 | * is used to ensure correct contact normals. 27 | * @export 28 | * @constructor 29 | * @extends {box2d.b2Shape} 30 | */ 31 | box2d.b2EdgeShape = function() { 32 | box2d.b2Shape.call(this, box2d.b2ShapeType.e_edgeShape, box2d.b2_polygonRadius); // base class constructor 33 | 34 | this.m_vertex1 = new box2d.b2Vec2(); 35 | this.m_vertex2 = new box2d.b2Vec2(); 36 | 37 | this.m_vertex0 = new box2d.b2Vec2(); 38 | this.m_vertex3 = new box2d.b2Vec2(); 39 | } 40 | 41 | box2d.b2EdgeShape.prototype = new box2d.b2Shape() 42 | 43 | /** 44 | * These are the edge vertices 45 | * @export 46 | * @type {box2d.b2Vec2} 47 | */ 48 | box2d.b2EdgeShape.prototype.m_vertex1 = null; 49 | /** 50 | * @export 51 | * @type {box2d.b2Vec2} 52 | */ 53 | box2d.b2EdgeShape.prototype.m_vertex2 = null; 54 | 55 | /** 56 | * Optional adjacent vertices. These are used for smooth 57 | * collision. 58 | * @export 59 | * @type {box2d.b2Vec2} 60 | */ 61 | box2d.b2EdgeShape.prototype.m_vertex0 = null; 62 | /** 63 | * @export 64 | * @type {box2d.b2Vec2} 65 | */ 66 | box2d.b2EdgeShape.prototype.m_vertex3 = null; 67 | /** 68 | * @export 69 | * @type {boolean} 70 | */ 71 | box2d.b2EdgeShape.prototype.m_hasVertex0 = false; 72 | /** 73 | * @export 74 | * @type {boolean} 75 | */ 76 | box2d.b2EdgeShape.prototype.m_hasVertex3 = false; 77 | 78 | /** 79 | * Set this as an isolated edge. 80 | * @export 81 | * @return {box2d.b2EdgeShape} 82 | * @param {box2d.b2Vec2} v1 83 | * @param {box2d.b2Vec2} v2 84 | */ 85 | box2d.b2EdgeShape.prototype.Set = function(v1, v2) { 86 | this.m_vertex1.Copy(v1); 87 | this.m_vertex2.Copy(v2); 88 | this.m_hasVertex0 = false; 89 | this.m_hasVertex3 = false; 90 | return this; 91 | } 92 | 93 | box2d.b2EdgeShape.prototype.SetAsEdge = box2d.b2EdgeShape.prototype.Set; 94 | 95 | /** 96 | * Implement box2d.b2Shape. 97 | * @export 98 | * @return {box2d.b2Shape} 99 | */ 100 | box2d.b2EdgeShape.prototype.Clone = function() { 101 | return new box2d.b2EdgeShape().Copy(this); 102 | } 103 | 104 | /** 105 | * @export 106 | * @return {box2d.b2Shape} 107 | * @param {box2d.b2Shape} other 108 | */ 109 | box2d.b2EdgeShape.prototype.Copy = function(other) { 110 | box2d.b2Shape.prototype.Copy.call(this, other); 111 | 112 | if (box2d.ENABLE_ASSERTS) { 113 | box2d.b2Assert(other instanceof box2d.b2EdgeShape); 114 | } 115 | 116 | this.m_vertex1.Copy(other.m_vertex1); 117 | this.m_vertex2.Copy(other.m_vertex2); 118 | this.m_vertex0.Copy(other.m_vertex0); 119 | this.m_vertex3.Copy(other.m_vertex3); 120 | this.m_hasVertex0 = other.m_hasVertex0; 121 | this.m_hasVertex3 = other.m_hasVertex3; 122 | 123 | return this; 124 | } 125 | 126 | /** 127 | * @see box2d.b2Shape::GetChildCount 128 | * @export 129 | * @return {number} 130 | */ 131 | box2d.b2EdgeShape.prototype.GetChildCount = function() { 132 | return 1; 133 | } 134 | 135 | /** 136 | * @see box2d.b2Shape::TestPoint 137 | * @export 138 | * @return {boolean} 139 | * @param {box2d.b2Transform} xf 140 | * @param {box2d.b2Vec2} p 141 | */ 142 | box2d.b2EdgeShape.prototype.TestPoint = function(xf, p) { 143 | return false; 144 | } 145 | 146 | //#if B2_ENABLE_PARTICLE 147 | 148 | /** 149 | * @see b2Shape::ComputeDistance 150 | * @export 151 | * @return {number} 152 | * @param {box2d.b2Transform} xf 153 | * @param {box2d.b2Vec2} p 154 | * @param {box2d.b2Vec2} normal 155 | * @param {number} childIndex 156 | */ 157 | box2d.b2EdgeShape.prototype.ComputeDistance = function(xf, p, normal, childIndex) { 158 | var v1 = box2d.b2Mul_X_V2(xf, this.m_vertex1, box2d.b2EdgeShape.prototype.ComputeDistance.s_v1); 159 | var v2 = box2d.b2Mul_X_V2(xf, this.m_vertex2, box2d.b2EdgeShape.prototype.ComputeDistance.s_v2); 160 | 161 | var d = box2d.b2Sub_V2_V2(p, v1, box2d.b2EdgeShape.prototype.ComputeDistance.s_d); 162 | var s = box2d.b2Sub_V2_V2(v2, v1, box2d.b2EdgeShape.prototype.ComputeDistance.s_s); 163 | var ds = box2d.b2Dot_V2_V2(d, s); 164 | if (ds > 0) { 165 | var s2 = box2d.b2Dot_V2_V2(s, s); 166 | if (ds > s2) { 167 | box2d.b2Sub_V2_V2(p, v2, d); 168 | } else { 169 | d.SelfMulSub(ds / s2, s); 170 | } 171 | } 172 | normal.Copy(d); 173 | return normal.Normalize(); 174 | } 175 | box2d.b2EdgeShape.prototype.ComputeDistance.s_v1 = new box2d.b2Vec2(); 176 | box2d.b2EdgeShape.prototype.ComputeDistance.s_v2 = new box2d.b2Vec2(); 177 | box2d.b2EdgeShape.prototype.ComputeDistance.s_d = new box2d.b2Vec2(); 178 | box2d.b2EdgeShape.prototype.ComputeDistance.s_s = new box2d.b2Vec2(); 179 | 180 | //#endif 181 | 182 | /** 183 | * Implement box2d.b2Shape. 184 | * p = p1 + t * d 185 | * v = v1 + s * e 186 | * p1 + t * d = v1 + s * e 187 | * s * e - t * d = p1 - v1 188 | * @export 189 | * @return {boolean} 190 | * @param {box2d.b2RayCastOutput} output 191 | * @param {box2d.b2RayCastInput} input 192 | * @param {box2d.b2Transform} xf 193 | * @param {number} childIndex 194 | */ 195 | box2d.b2EdgeShape.prototype.RayCast = function(output, input, xf, childIndex) { 196 | // Put the ray into the edge's frame of reference. 197 | var p1 = box2d.b2MulT_X_V2(xf, input.p1, box2d.b2EdgeShape.prototype.RayCast.s_p1); 198 | var p2 = box2d.b2MulT_X_V2(xf, input.p2, box2d.b2EdgeShape.prototype.RayCast.s_p2); 199 | var d = box2d.b2Sub_V2_V2(p2, p1, box2d.b2EdgeShape.prototype.RayCast.s_d); 200 | 201 | var v1 = this.m_vertex1; 202 | var v2 = this.m_vertex2; 203 | var e = box2d.b2Sub_V2_V2(v2, v1, box2d.b2EdgeShape.prototype.RayCast.s_e); 204 | var normal = output.normal.Set(e.y, -e.x).SelfNormalize(); 205 | 206 | // q = p1 + t * d 207 | // dot(normal, q - v1) = 0 208 | // dot(normal, p1 - v1) + t * dot(normal, d) = 0 209 | var numerator = box2d.b2Dot_V2_V2(normal, box2d.b2Sub_V2_V2(v1, p1, box2d.b2Vec2.s_t0)); 210 | var denominator = box2d.b2Dot_V2_V2(normal, d); 211 | 212 | if (denominator === 0) { 213 | return false; 214 | } 215 | 216 | var t = numerator / denominator; 217 | if (t < 0 || input.maxFraction < t) { 218 | return false; 219 | } 220 | 221 | var q = box2d.b2AddMul_V2_S_V2(p1, t, d, box2d.b2EdgeShape.prototype.RayCast.s_q); 222 | 223 | // q = v1 + s * r 224 | // s = dot(q - v1, r) / dot(r, r) 225 | var r = box2d.b2Sub_V2_V2(v2, v1, box2d.b2EdgeShape.prototype.RayCast.s_r); 226 | var rr = box2d.b2Dot_V2_V2(r, r); 227 | if (rr === 0) { 228 | return false; 229 | } 230 | 231 | var s = box2d.b2Dot_V2_V2(box2d.b2Sub_V2_V2(q, v1, box2d.b2Vec2.s_t0), r) / rr; 232 | if (s < 0 || 1 < s) { 233 | return false; 234 | } 235 | 236 | output.fraction = t; 237 | box2d.b2Mul_R_V2(xf.q, output.normal, output.normal); 238 | if (numerator > 0) { 239 | output.normal.SelfNeg(); 240 | } 241 | return true; 242 | } 243 | box2d.b2EdgeShape.prototype.RayCast.s_p1 = new box2d.b2Vec2(); 244 | box2d.b2EdgeShape.prototype.RayCast.s_p2 = new box2d.b2Vec2(); 245 | box2d.b2EdgeShape.prototype.RayCast.s_d = new box2d.b2Vec2(); 246 | box2d.b2EdgeShape.prototype.RayCast.s_e = new box2d.b2Vec2(); 247 | box2d.b2EdgeShape.prototype.RayCast.s_q = new box2d.b2Vec2(); 248 | box2d.b2EdgeShape.prototype.RayCast.s_r = new box2d.b2Vec2(); 249 | 250 | /** 251 | * @see box2d.b2Shape::ComputeAABB 252 | * @export 253 | * @return {void} 254 | * @param {box2d.b2AABB} aabb 255 | * @param {box2d.b2Transform} xf 256 | * @param {number} childIndex 257 | */ 258 | box2d.b2EdgeShape.prototype.ComputeAABB = function(aabb, xf, childIndex) { 259 | var v1 = box2d.b2Mul_X_V2(xf, this.m_vertex1, box2d.b2EdgeShape.prototype.ComputeAABB.s_v1); 260 | var v2 = box2d.b2Mul_X_V2(xf, this.m_vertex2, box2d.b2EdgeShape.prototype.ComputeAABB.s_v2); 261 | 262 | box2d.b2Min_V2_V2(v1, v2, aabb.lowerBound); 263 | box2d.b2Max_V2_V2(v1, v2, aabb.upperBound); 264 | 265 | var r = this.m_radius; 266 | aabb.lowerBound.SelfSubXY(r, r); 267 | aabb.upperBound.SelfAddXY(r, r); 268 | } 269 | box2d.b2EdgeShape.prototype.ComputeAABB.s_v1 = new box2d.b2Vec2(); 270 | box2d.b2EdgeShape.prototype.ComputeAABB.s_v2 = new box2d.b2Vec2(); 271 | 272 | /** 273 | * @see box2d.b2Shape::ComputeMass 274 | * @export 275 | * @return {void} 276 | * @param {box2d.b2MassData} massData 277 | * @param {number} density 278 | */ 279 | box2d.b2EdgeShape.prototype.ComputeMass = function(massData, density) { 280 | massData.mass = 0; 281 | box2d.b2Mid_V2_V2(this.m_vertex1, this.m_vertex2, massData.center); 282 | massData.I = 0; 283 | } 284 | 285 | /** 286 | * @return {void} 287 | * @param {box2d.b2DistanceProxy} proxy 288 | * @param {number} index 289 | */ 290 | box2d.b2EdgeShape.prototype.SetupDistanceProxy = function(proxy, index) { 291 | proxy.m_vertices = proxy.m_buffer; 292 | proxy.m_vertices[0].Copy(this.m_vertex1); 293 | proxy.m_vertices[1].Copy(this.m_vertex2); 294 | proxy.m_count = 2; 295 | proxy.m_radius = this.m_radius; 296 | } 297 | 298 | /** 299 | * @export 300 | * @return {number} 301 | * @param {box2d.b2Vec2} normal 302 | * @param {number} offset 303 | * @param {box2d.b2Transform} xf 304 | * @param {box2d.b2Vec2} c 305 | */ 306 | box2d.b2EdgeShape.prototype.ComputeSubmergedArea = function(normal, offset, xf, c) { 307 | c.SetZero(); 308 | return 0; 309 | } 310 | 311 | /** 312 | * Dump this shape to the log file. 313 | * @export 314 | * @return {void} 315 | */ 316 | box2d.b2EdgeShape.prototype.Dump = function() { 317 | box2d.b2Log(" /*box2d.b2EdgeShape*/ var shape = new box2d.b2EdgeShape();\n"); 318 | box2d.b2Log(" shape.m_radius = %.15f;\n", this.m_radius); 319 | box2d.b2Log(" shape.m_vertex0.Set(%.15f, %.15f);\n", this.m_vertex0.x, this.m_vertex0.y); 320 | box2d.b2Log(" shape.m_vertex1.Set(%.15f, %.15f);\n", this.m_vertex1.x, this.m_vertex1.y); 321 | box2d.b2Log(" shape.m_vertex2.Set(%.15f, %.15f);\n", this.m_vertex2.x, this.m_vertex2.y); 322 | box2d.b2Log(" shape.m_vertex3.Set(%.15f, %.15f);\n", this.m_vertex3.x, this.m_vertex3.y); 323 | box2d.b2Log(" shape.m_hasVertex0 = %s;\n", this.m_hasVertex0); 324 | box2d.b2Log(" shape.m_hasVertex3 = %s;\n", this.m_hasVertex3); 325 | } 326 | -------------------------------------------------------------------------------- /Box2D/Collision/Shapes/b2Shape.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2Shape'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Math'); 23 | // goog.require('box2d.b2ShapeDistance'); 24 | 25 | /** 26 | * This holds the mass data computed for a shape. 27 | * @export 28 | * @constructor 29 | */ 30 | box2d.b2MassData = function() { 31 | this.center = new box2d.b2Vec2(0, 0); 32 | }; 33 | 34 | /** 35 | * The mass of the shape, usually in kilograms. 36 | * @export 37 | * @type {number} 38 | */ 39 | box2d.b2MassData.prototype.mass = 0; 40 | 41 | /** 42 | * The position of the shape's centroid relative to the shape's 43 | * origin. 44 | * @export 45 | * @type {box2d.b2Vec2} 46 | */ 47 | box2d.b2MassData.prototype.center = null; 48 | 49 | /** 50 | * The rotational inertia of the shape about the local origin. 51 | * @export 52 | * @type {number} 53 | */ 54 | box2d.b2MassData.prototype.I = 0; 55 | 56 | /** 57 | * @export 58 | * @enum 59 | */ 60 | box2d.b2ShapeType = { 61 | e_unknown: -1, 62 | e_circleShape: 0, 63 | e_edgeShape: 1, 64 | e_polygonShape: 2, 65 | e_chainShape: 3, 66 | e_shapeTypeCount: 4 67 | }; 68 | // goog.exportProperty(box2d.b2ShapeType, 'e_unknown', box2d.b2ShapeType.e_unknown); 69 | // goog.exportProperty(box2d.b2ShapeType, 'e_circleShape', box2d.b2ShapeType.e_circleShape); 70 | // goog.exportProperty(box2d.b2ShapeType, 'e_edgeShape', box2d.b2ShapeType.e_edgeShape); 71 | // goog.exportProperty(box2d.b2ShapeType, 'e_polygonShape', box2d.b2ShapeType.e_polygonShape); 72 | // goog.exportProperty(box2d.b2ShapeType, 'e_chainShape', box2d.b2ShapeType.e_chainShape); 73 | // goog.exportProperty(box2d.b2ShapeType, 'e_shapeTypeCount', box2d.b2ShapeType.e_shapeTypeCount); 74 | 75 | /** 76 | * A shape is used for collision detection. You can create a 77 | * shape however you like. 78 | * Shapes used for simulation in box2d.b2World are created 79 | * automatically when a box2d.b2Fixture is created. Shapes may 80 | * encapsulate a one or more child shapes. 81 | * @export 82 | * @constructor 83 | * @param {box2d.b2ShapeType} type 84 | * @param {number} radius 85 | */ 86 | box2d.b2Shape = function(type, radius) { 87 | this.m_type = type; 88 | this.m_radius = radius; 89 | } 90 | 91 | /** 92 | * @export 93 | * @type {box2d.b2ShapeType} 94 | */ 95 | box2d.b2Shape.prototype.m_type = box2d.b2ShapeType.e_unknown; 96 | /** 97 | * @export 98 | * @type {number} 99 | */ 100 | box2d.b2Shape.prototype.m_radius = 0; 101 | 102 | /** 103 | * Clone the concrete shape using the provided allocator. 104 | * @export 105 | * @return {box2d.b2Shape} 106 | */ 107 | box2d.b2Shape.prototype.Clone = function() { 108 | if (box2d.ENABLE_ASSERTS) { 109 | box2d.b2Assert(false); 110 | } 111 | return null; 112 | } 113 | 114 | /** 115 | * @export 116 | * @return {box2d.b2Shape} 117 | * @param {box2d.b2Shape} other 118 | */ 119 | box2d.b2Shape.prototype.Copy = function(other) { 120 | if (box2d.ENABLE_ASSERTS) { 121 | box2d.b2Assert(this.m_type === other.m_type); 122 | } 123 | this.m_radius = other.m_radius; 124 | return this; 125 | } 126 | 127 | /** 128 | * Get the type of this shape. You can use this to down cast to 129 | * the concrete shape. 130 | * @export 131 | * @return {box2d.b2ShapeType} the shape type. 132 | */ 133 | box2d.b2Shape.prototype.GetType = function() { 134 | return this.m_type; 135 | } 136 | 137 | /** 138 | * Get the number of child primitives. 139 | * @export 140 | * @return {number} 141 | */ 142 | box2d.b2Shape.prototype.GetChildCount = function() { 143 | if (box2d.ENABLE_ASSERTS) { 144 | box2d.b2Assert(false, "pure virtual"); 145 | } 146 | return 0; 147 | } 148 | 149 | /** 150 | * Test a point for containment in this shape. This only works 151 | * for convex shapes. 152 | * @export 153 | * @return {boolean} 154 | * @param {box2d.b2Transform} xf the shape world transform. 155 | * @param {box2d.b2Vec2} p a point in world coordinates. 156 | */ 157 | box2d.b2Shape.prototype.TestPoint = function(xf, p) { 158 | if (box2d.ENABLE_ASSERTS) { 159 | box2d.b2Assert(false, "pure virtual"); 160 | } 161 | return false; 162 | } 163 | 164 | //#if B2_ENABLE_PARTICLE 165 | 166 | /** 167 | * Compute the distance from the current shape to the specified 168 | * point. This only works for convex shapes. 169 | * @export 170 | * @return {number} returns the distance from the current shape. 171 | * @param {box2d.b2Transform} xf the shape world transform. 172 | * @param {box2d.b2Vec2} p a point in world coordinates. 173 | * @param {box2d.b2Vec2} normal returns the direction in which 174 | * the distance increases. 175 | * @param {number} childIndex 176 | */ 177 | box2d.b2Shape.prototype.ComputeDistance = function(xf, p, normal, childIndex) { 178 | if (box2d.ENABLE_ASSERTS) { 179 | box2d.b2Assert(false, "pure virtual"); 180 | } 181 | return 0; 182 | } 183 | 184 | //#endif 185 | 186 | /** 187 | * Cast a ray against a child shape. 188 | * @export 189 | * @return {boolean} 190 | * @param {box2d.b2RayCastOutput} output the ray-cast results. 191 | * @param {box2d.b2RayCastInput} input the ray-cast input parameters. 192 | * @param {box2d.b2Transform} transform the transform to be applied to the shape. 193 | * @param {number} childIndex the child shape index 194 | */ 195 | box2d.b2Shape.prototype.RayCast = function(output, input, transform, childIndex) { 196 | if (box2d.ENABLE_ASSERTS) { 197 | box2d.b2Assert(false, "pure virtual"); 198 | } 199 | return false; 200 | } 201 | 202 | /** 203 | * Given a transform, compute the associated axis aligned 204 | * bounding box for a child shape. 205 | * @export 206 | * @return {void} 207 | * @param {box2d.b2AABB} aabb returns the axis aligned box. 208 | * @param {box2d.b2Transform} xf the world transform of the shape. 209 | * @param {number} childIndex the child shape 210 | */ 211 | box2d.b2Shape.prototype.ComputeAABB = function(aabb, xf, childIndex) { 212 | if (box2d.ENABLE_ASSERTS) { 213 | box2d.b2Assert(false, "pure virtual"); 214 | } 215 | } 216 | 217 | /** 218 | * Compute the mass properties of this shape using its 219 | * dimensions and density. 220 | * The inertia tensor is computed about the local origin. 221 | * @export 222 | * @return {void} 223 | * @param {box2d.b2MassData} massData returns the mass data for this shape. 224 | * @param {number} density the density in kilograms per meter squared. 225 | */ 226 | box2d.b2Shape.prototype.ComputeMass = function(massData, density) { 227 | if (box2d.ENABLE_ASSERTS) { 228 | box2d.b2Assert(false, "pure virtual"); 229 | } 230 | } 231 | 232 | /** 233 | * @return {void} 234 | * @param {box2d.b2DistanceProxy} proxy 235 | * @param {number} index 236 | */ 237 | box2d.b2Shape.prototype.SetupDistanceProxy = function(proxy, index) { 238 | if (box2d.ENABLE_ASSERTS) { 239 | box2d.b2Assert(false, "pure virtual"); 240 | } 241 | } 242 | 243 | /** 244 | * @export 245 | * @return {number} 246 | * @param {box2d.b2Vec2} normal 247 | * @param {number} offset 248 | * @param {box2d.b2Transform} xf 249 | * @param {box2d.b2Vec2} c 250 | */ 251 | box2d.b2Shape.prototype.ComputeSubmergedArea = function(normal, offset, xf, c) { 252 | if (box2d.ENABLE_ASSERTS) { 253 | box2d.b2Assert(false, "pure virtual"); 254 | } 255 | return 0; 256 | } 257 | 258 | /** 259 | * Dump this shape to the log file. 260 | * @export 261 | * @return {void} 262 | */ 263 | box2d.b2Shape.prototype.Dump = function() { 264 | if (box2d.ENABLE_ASSERTS) { 265 | box2d.b2Assert(false, "pure virtual"); 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /Box2D/Collision/b2BroadPhase.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2BroadPhase') 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2DynamicTree') 23 | 24 | /** 25 | * @export 26 | * @constructor 27 | */ 28 | box2d.b2Pair = function() {}; 29 | 30 | /** 31 | * @export 32 | * @type {box2d.b2TreeNode} 33 | */ 34 | box2d.b2Pair.prototype.proxyA = null; 35 | /** 36 | * @export 37 | * @type {box2d.b2TreeNode} 38 | */ 39 | box2d.b2Pair.prototype.proxyB = null; 40 | 41 | /** 42 | * The broad-phase is used for computing pairs and performing 43 | * volume queries and ray casts. This broad-phase does not 44 | * persist pairs. Instead, this reports potentially new pairs. 45 | * It is up to the client to consume the new pairs and to track 46 | * subsequent overlap. 47 | * @export 48 | * @constructor 49 | */ 50 | box2d.b2BroadPhase = function() { 51 | this.m_tree = new box2d.b2DynamicTree(); 52 | this.m_moveBuffer = new Array(); 53 | this.m_pairBuffer = new Array(); 54 | }; 55 | 56 | /** 57 | * @export 58 | * @type {box2d.b2DynamicTree} 59 | */ 60 | box2d.b2BroadPhase.prototype.m_tree = null; 61 | 62 | /** 63 | * @export 64 | * @type {number} 65 | */ 66 | box2d.b2BroadPhase.prototype.m_proxyCount = 0; 67 | 68 | //box2d.b2BroadPhase.prototype.m_moveCapacity = 16; 69 | /** 70 | * @export 71 | * @type {number} 72 | */ 73 | box2d.b2BroadPhase.prototype.m_moveCount = 0; 74 | /** 75 | * @export 76 | * @type {Array.} 77 | */ 78 | box2d.b2BroadPhase.prototype.m_moveBuffer = null; 79 | 80 | //box2d.b2BroadPhase.prototype.m_pairCapacity = 16; 81 | /** 82 | * @export 83 | * @type {number} 84 | */ 85 | box2d.b2BroadPhase.prototype.m_pairCount = 0; 86 | /** 87 | * @export 88 | * @type {Array.} 89 | */ 90 | box2d.b2BroadPhase.prototype.m_pairBuffer = null; 91 | 92 | //box2d.b2BroadPhase.prototype.m_queryProxyId = 0; 93 | 94 | /** 95 | * Create a proxy with an initial AABB. Pairs are not reported 96 | * until UpdatePairs is called. 97 | * @export 98 | * @return {box2d.b2TreeNode} 99 | * @param {box2d.b2AABB} aabb 100 | * @param {*} userData 101 | */ 102 | box2d.b2BroadPhase.prototype.CreateProxy = function(aabb, userData) { 103 | var proxy = this.m_tree.CreateProxy(aabb, userData); 104 | ++this.m_proxyCount; 105 | this.BufferMove(proxy); 106 | return proxy; 107 | } 108 | 109 | /** 110 | * Destroy a proxy. It is up to the client to remove any pairs. 111 | * @export 112 | * @return {void} 113 | * @param {box2d.b2TreeNode} proxy 114 | */ 115 | box2d.b2BroadPhase.prototype.DestroyProxy = function(proxy) { 116 | this.UnBufferMove(proxy); 117 | --this.m_proxyCount; 118 | this.m_tree.DestroyProxy(proxy); 119 | } 120 | 121 | /** 122 | * Call MoveProxy as many times as you like, then when you are 123 | * done call UpdatePairs to finalized the proxy pairs (for your 124 | * time step). 125 | * @export 126 | * @return {void} 127 | * @param {box2d.b2TreeNode} proxy 128 | * @param {box2d.b2AABB} aabb 129 | * @param {box2d.b2Vec2} displacement 130 | */ 131 | box2d.b2BroadPhase.prototype.MoveProxy = function(proxy, aabb, displacement) { 132 | var buffer = this.m_tree.MoveProxy(proxy, aabb, displacement); 133 | if (buffer) { 134 | this.BufferMove(proxy); 135 | } 136 | } 137 | 138 | /** 139 | * Call to trigger a re-processing of it's pairs on the next 140 | * call to UpdatePairs. 141 | * @export 142 | * @return {void} 143 | * @param {box2d.b2TreeNode} proxy 144 | */ 145 | box2d.b2BroadPhase.prototype.TouchProxy = function(proxy) { 146 | this.BufferMove(proxy); 147 | } 148 | 149 | /** 150 | * Get the fat AABB for a proxy. 151 | * @export 152 | * @return {box2d.b2AABB} 153 | * @param {box2d.b2TreeNode} proxy 154 | */ 155 | box2d.b2BroadPhase.prototype.GetFatAABB = function(proxy) { 156 | return this.m_tree.GetFatAABB(proxy); 157 | } 158 | 159 | /** 160 | * Get user data from a proxy. Returns NULL if the id is 161 | * invalid. 162 | * @export 163 | * @return {*} 164 | * @param {box2d.b2TreeNode} proxy 165 | */ 166 | box2d.b2BroadPhase.prototype.GetUserData = function(proxy) { 167 | return this.m_tree.GetUserData(proxy); 168 | } 169 | 170 | /** 171 | * Test overlap of fat AABBs. 172 | * @export 173 | * @return {boolean} 174 | * @param {box2d.b2TreeNode} proxyA 175 | * @param {box2d.b2TreeNode} proxyB 176 | */ 177 | box2d.b2BroadPhase.prototype.TestOverlap = function(proxyA, proxyB) { 178 | var aabbA = this.m_tree.GetFatAABB(proxyA); 179 | var aabbB = this.m_tree.GetFatAABB(proxyB); 180 | return box2d.b2TestOverlap_AABB(aabbA, aabbB); 181 | } 182 | 183 | /** 184 | * Get the number of proxies. 185 | * @export 186 | * @return {number} 187 | */ 188 | box2d.b2BroadPhase.prototype.GetProxyCount = function() { 189 | return this.m_proxyCount; 190 | } 191 | 192 | /** 193 | * Get the height of the embedded tree. 194 | * @export 195 | * @return {number} 196 | */ 197 | box2d.b2BroadPhase.prototype.GetTreeHeight = function() { 198 | return this.m_tree.GetHeight(); 199 | } 200 | 201 | /** 202 | * Get the balance of the embedded tree. 203 | * @export 204 | * @return {number} 205 | */ 206 | box2d.b2BroadPhase.prototype.GetTreeBalance = function() { 207 | return this.m_tree.GetMaxBalance(); 208 | } 209 | 210 | /** 211 | * Get the quality metric of the embedded tree. 212 | * @export 213 | * @return {number} 214 | */ 215 | box2d.b2BroadPhase.prototype.GetTreeQuality = function() { 216 | return this.m_tree.GetAreaRatio(); 217 | } 218 | 219 | /** 220 | * Shift the world origin. Useful for large worlds. The shift 221 | * formula is: position -= newOrigin 222 | * @export 223 | * @return {void} 224 | * @param {box2d.b2Vec2} newOrigin the new origin with respect to the old origin 225 | */ 226 | box2d.b2BroadPhase.prototype.ShiftOrigin = function(newOrigin) { 227 | this.m_tree.ShiftOrigin(newOrigin); 228 | } 229 | 230 | /** 231 | * Update the pairs. This results in pair callbacks. This can 232 | * only add pairs. 233 | * @export 234 | * @return {void} 235 | * @param contactManager 236 | */ 237 | box2d.b2BroadPhase.prototype.UpdatePairs = function(contactManager) { 238 | // Reset pair buffer 239 | this.m_pairCount = 0; 240 | 241 | // Perform tree queries for all moving proxies. 242 | for (var i = 0; i < this.m_moveCount; ++i) { 243 | var queryProxy = this.m_moveBuffer[i]; 244 | if (queryProxy === null) { 245 | continue; 246 | } 247 | 248 | var that = this; 249 | 250 | // This is called from box2d.b2DynamicTree::Query when we are gathering pairs. 251 | // bool b2BroadPhase::QueryCallback(int32 proxyId); 252 | var QueryCallback = function(proxy) { 253 | // A proxy cannot form a pair with itself. 254 | if (proxy.m_id === queryProxy.m_id) { 255 | return true; 256 | } 257 | 258 | // Grow the pair buffer as needed. 259 | if (that.m_pairCount === that.m_pairBuffer.length) { 260 | that.m_pairBuffer[that.m_pairCount] = new box2d.b2Pair(); 261 | } 262 | 263 | var pair = that.m_pairBuffer[that.m_pairCount]; 264 | //pair.proxyA = proxy < queryProxy ? proxy : queryProxy; 265 | //pair.proxyB = proxy >= queryProxy ? proxy : queryProxy; 266 | if (proxy.m_id < queryProxy.m_id) { 267 | pair.proxyA = proxy; 268 | pair.proxyB = queryProxy; 269 | } else { 270 | pair.proxyA = queryProxy; 271 | pair.proxyB = proxy; 272 | } 273 | ++that.m_pairCount; 274 | 275 | return true; 276 | }; 277 | 278 | // We have to query the tree with the fat AABB so that 279 | // we don't fail to create a pair that may touch later. 280 | var fatAABB = this.m_tree.GetFatAABB(queryProxy); 281 | 282 | // Query tree, create pairs and add them pair buffer. 283 | this.m_tree.Query(QueryCallback, fatAABB); 284 | } 285 | 286 | // Reset move buffer 287 | this.m_moveCount = 0; 288 | 289 | // Sort the pair buffer to expose duplicates. 290 | this.m_pairBuffer.length = this.m_pairCount; 291 | this.m_pairBuffer.sort(box2d.b2PairLessThan); 292 | 293 | // Send the pairs back to the client. 294 | var i = 0; 295 | while (i < this.m_pairCount) { 296 | var primaryPair = this.m_pairBuffer[i]; 297 | var userDataA = this.m_tree.GetUserData(primaryPair.proxyA); 298 | var userDataB = this.m_tree.GetUserData(primaryPair.proxyB); 299 | 300 | contactManager.AddPair(userDataA, userDataB); 301 | ++i; 302 | 303 | // Skip any duplicate pairs. 304 | while (i < this.m_pairCount) { 305 | var pair = this.m_pairBuffer[i]; 306 | if (pair.proxyA.m_id !== primaryPair.proxyA.m_id || pair.proxyB.m_id !== primaryPair.proxyB.m_id) { 307 | break; 308 | } 309 | ++i; 310 | } 311 | } 312 | 313 | // Try to keep the tree balanced. 314 | //this.m_tree.Rebalance(4); 315 | } 316 | 317 | /** 318 | * Query an AABB for overlapping proxies. The callback class is 319 | * called for each proxy that overlaps the supplied AABB. 320 | * @export 321 | * @return {void} 322 | * @param {function(box2d.b2TreeNode):boolean} callback 323 | * @param {box2d.b2AABB} aabb 324 | */ 325 | box2d.b2BroadPhase.prototype.Query = function(callback, aabb) { 326 | this.m_tree.Query(callback, aabb); 327 | } 328 | 329 | /** 330 | * Ray-cast against the proxies in the tree. This relies on the 331 | * callback to perform a exact ray-cast in the case were the 332 | * proxy contains a shape. The callback also performs the any 333 | * collision filtering. This has performance roughly equal to k 334 | * * log(n), where k is the number of collisions and n is the 335 | * number of proxies in the tree. 336 | * @export 337 | * @return {void} 338 | * @param 339 | * {function(box2d.b2RayCastInput,box2d.b2TreeNode):number} 340 | * callback a callback class that is called for each 341 | * proxy that is hit by the ray. 342 | * @param {box2d.b2RayCastInput} input the ray-cast input data. 343 | * The ray extends from p1 to p1 + maxFraction * (p2 - 344 | * p1). 345 | */ 346 | box2d.b2BroadPhase.prototype.RayCast = function(callback, input) { 347 | this.m_tree.RayCast(callback, input); 348 | } 349 | 350 | /** 351 | * @export 352 | * @return {void} 353 | * @param {box2d.b2TreeNode} proxy 354 | */ 355 | box2d.b2BroadPhase.prototype.BufferMove = function(proxy) { 356 | this.m_moveBuffer[this.m_moveCount] = proxy; 357 | ++this.m_moveCount; 358 | } 359 | 360 | /** 361 | * @export 362 | * @return {void} 363 | * @param {box2d.b2TreeNode} proxy 364 | */ 365 | box2d.b2BroadPhase.prototype.UnBufferMove = function(proxy) { 366 | var i = this.m_moveBuffer.indexOf(proxy); 367 | this.m_moveBuffer[i] = null; 368 | } 369 | 370 | /** 371 | * This is used to sort pairs. 372 | * @return {number} 373 | * @param {box2d.b2Pair} pair1 374 | * @param {box2d.b2Pair} pair2 375 | */ 376 | box2d.b2PairLessThan = function(pair1, pair2) { 377 | if (pair1.proxyA.m_id === pair2.proxyA.m_id) { 378 | return pair1.proxyB.m_id - pair2.proxyB.m_id; 379 | } 380 | 381 | return pair1.proxyA.m_id - pair2.proxyA.m_id; 382 | } 383 | -------------------------------------------------------------------------------- /Box2D/Collision/b2CollideCircle.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2CollideCircle'); 20 | 21 | // goog.require('box2d.b2Collision'); 22 | 23 | /** 24 | * Compute the collision manifold between two circles. 25 | * @export 26 | * @return {void} 27 | * @param {box2d.b2Manifold} manifold 28 | * @param {box2d.b2CircleShape} circleA 29 | * @param {box2d.b2Transform} xfA 30 | * @param {box2d.b2CircleShape} circleB 31 | * @param {box2d.b2Transform} xfB 32 | */ 33 | box2d.b2CollideCircles = function(manifold, circleA, xfA, circleB, xfB) { 34 | manifold.pointCount = 0; 35 | 36 | var pA = box2d.b2Mul_X_V2(xfA, circleA.m_p, box2d.b2CollideCircles.s_pA); 37 | var pB = box2d.b2Mul_X_V2(xfB, circleB.m_p, box2d.b2CollideCircles.s_pB); 38 | 39 | var distSqr = box2d.b2DistanceSquared(pA, pB); 40 | var radius = circleA.m_radius + circleB.m_radius; 41 | if (distSqr > radius * radius) { 42 | return; 43 | } 44 | 45 | manifold.type = box2d.b2ManifoldType.e_circles; 46 | manifold.localPoint.Copy(circleA.m_p); 47 | manifold.localNormal.SetZero(); 48 | manifold.pointCount = 1; 49 | 50 | manifold.points[0].localPoint.Copy(circleB.m_p); 51 | manifold.points[0].id.key = 0; 52 | } 53 | box2d.b2CollideCircles.s_pA = new box2d.b2Vec2(); 54 | box2d.b2CollideCircles.s_pB = new box2d.b2Vec2(); 55 | 56 | /** 57 | * Compute the collision manifold between a polygon and a 58 | * circle. 59 | * @export 60 | * @return {void} 61 | * @param {box2d.b2Manifold} manifold 62 | * @param {box2d.b2PolygonShape} polygonA 63 | * @param {box2d.b2Transform} xfA 64 | * @param {box2d.b2CircleShape} circleB 65 | * @param {box2d.b2Transform} xfB 66 | */ 67 | box2d.b2CollidePolygonAndCircle = function(manifold, polygonA, xfA, circleB, xfB) { 68 | manifold.pointCount = 0; 69 | 70 | // Compute circle position in the frame of the polygon. 71 | var c = box2d.b2Mul_X_V2(xfB, circleB.m_p, box2d.b2CollidePolygonAndCircle.s_c); 72 | var cLocal = box2d.b2MulT_X_V2(xfA, c, box2d.b2CollidePolygonAndCircle.s_cLocal); 73 | 74 | // Find the min separating edge. 75 | var normalIndex = 0; 76 | var separation = (-box2d.b2_maxFloat); 77 | var radius = polygonA.m_radius + circleB.m_radius; 78 | var vertexCount = polygonA.m_count; 79 | var vertices = polygonA.m_vertices; 80 | var normals = polygonA.m_normals; 81 | 82 | for (var i = 0; i < vertexCount; ++i) { 83 | var s = box2d.b2Dot_V2_V2(normals[i], box2d.b2Sub_V2_V2(cLocal, vertices[i], box2d.b2Vec2.s_t0)); 84 | 85 | if (s > radius) { 86 | // Early out. 87 | return; 88 | } 89 | 90 | if (s > separation) { 91 | separation = s; 92 | normalIndex = i; 93 | } 94 | } 95 | 96 | // Vertices that subtend the incident face. 97 | var vertIndex1 = normalIndex; 98 | var vertIndex2 = (vertIndex1 + 1) % vertexCount; 99 | var v1 = vertices[vertIndex1]; 100 | var v2 = vertices[vertIndex2]; 101 | 102 | // If the center is inside the polygon ... 103 | if (separation < box2d.b2_epsilon) { 104 | manifold.pointCount = 1; 105 | manifold.type = box2d.b2ManifoldType.e_faceA; 106 | manifold.localNormal.Copy(normals[normalIndex]); 107 | box2d.b2Mid_V2_V2(v1, v2, manifold.localPoint); 108 | manifold.points[0].localPoint.Copy(circleB.m_p); 109 | manifold.points[0].id.key = 0; 110 | return; 111 | } 112 | 113 | // Compute barycentric coordinates 114 | var u1 = box2d.b2Dot_V2_V2(box2d.b2Sub_V2_V2(cLocal, v1, box2d.b2Vec2.s_t0), box2d.b2Sub_V2_V2(v2, v1, box2d.b2Vec2.s_t1)); 115 | var u2 = box2d.b2Dot_V2_V2(box2d.b2Sub_V2_V2(cLocal, v2, box2d.b2Vec2.s_t0), box2d.b2Sub_V2_V2(v1, v2, box2d.b2Vec2.s_t1)); 116 | if (u1 <= 0) { 117 | if (box2d.b2DistanceSquared(cLocal, v1) > radius * radius) { 118 | return; 119 | } 120 | 121 | manifold.pointCount = 1; 122 | manifold.type = box2d.b2ManifoldType.e_faceA; 123 | box2d.b2Sub_V2_V2(cLocal, v1, manifold.localNormal).SelfNormalize(); 124 | manifold.localPoint.Copy(v1); 125 | manifold.points[0].localPoint.Copy(circleB.m_p); 126 | manifold.points[0].id.key = 0; 127 | } else if (u2 <= 0) { 128 | if (box2d.b2DistanceSquared(cLocal, v2) > radius * radius) { 129 | return; 130 | } 131 | 132 | manifold.pointCount = 1; 133 | manifold.type = box2d.b2ManifoldType.e_faceA; 134 | box2d.b2Sub_V2_V2(cLocal, v2, manifold.localNormal).SelfNormalize(); 135 | manifold.localPoint.Copy(v2); 136 | manifold.points[0].localPoint.Copy(circleB.m_p); 137 | manifold.points[0].id.key = 0; 138 | } else { 139 | var faceCenter = box2d.b2Mid_V2_V2(v1, v2, box2d.b2CollidePolygonAndCircle.s_faceCenter); 140 | separation = box2d.b2Dot_V2_V2(box2d.b2Sub_V2_V2(cLocal, faceCenter, box2d.b2Vec2.s_t1), normals[vertIndex1]); 141 | if (separation > radius) { 142 | return; 143 | } 144 | 145 | manifold.pointCount = 1; 146 | manifold.type = box2d.b2ManifoldType.e_faceA; 147 | manifold.localNormal.Copy(normals[vertIndex1]).SelfNormalize(); 148 | manifold.localPoint.Copy(faceCenter); 149 | manifold.points[0].localPoint.Copy(circleB.m_p); 150 | manifold.points[0].id.key = 0; 151 | } 152 | } 153 | box2d.b2CollidePolygonAndCircle.s_c = new box2d.b2Vec2(); 154 | box2d.b2CollidePolygonAndCircle.s_cLocal = new box2d.b2Vec2(); 155 | box2d.b2CollidePolygonAndCircle.s_faceCenter = new box2d.b2Vec2(); 156 | -------------------------------------------------------------------------------- /Box2D/Collision/b2CollidePolygon.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2CollidePolygon'); 20 | 21 | // goog.require('box2d.b2Collision'); 22 | 23 | /** 24 | * Find the max separation between poly1 and poly2 using edge 25 | * normals from poly1. 26 | * @export 27 | * @return {number} 28 | * @param {Array.} edgeIndex 29 | * @param {box2d.b2PolygonShape} poly1 30 | * @param {box2d.b2Transform} xf1 31 | * @param {box2d.b2PolygonShape} poly2 32 | * @param {box2d.b2Transform} xf2 33 | */ 34 | box2d.b2FindMaxSeparation = function(edgeIndex, poly1, xf1, poly2, xf2) { 35 | var /*int32*/ count1 = poly1.m_count; 36 | var /*int32*/ count2 = poly2.m_count; 37 | var /*const b2Vec2**/ n1s = poly1.m_normals; 38 | var /*const b2Vec2**/ v1s = poly1.m_vertices; 39 | var /*const b2Vec2**/ v2s = poly2.m_vertices; 40 | var /*b2Transform*/ xf = box2d.b2MulT_X_X(xf2, xf1, box2d.b2FindMaxSeparation.s_xf); 41 | 42 | var /*int32*/ bestIndex = 0; 43 | var /*float32*/ maxSeparation = -box2d.b2_maxFloat; 44 | for (var /*int32*/ i = 0; i < count1; ++i) { 45 | // Get poly1 normal in frame2. 46 | var /*b2Vec2*/ n = box2d.b2Mul_R_V2(xf.q, n1s[i], box2d.b2FindMaxSeparation.s_n); 47 | var /*b2Vec2*/ v1 = box2d.b2Mul_X_V2(xf, v1s[i], box2d.b2FindMaxSeparation.s_v1); 48 | 49 | // Find deepest point for normal i. 50 | var /*float32*/ si = box2d.b2_maxFloat; 51 | for (var /*int32*/ j = 0; j < count2; ++j) { 52 | var /*float32*/ sij = box2d.b2Dot_V2_V2(n, box2d.b2Sub_V2_V2(v2s[j], v1, box2d.b2Vec2.s_t0)); // b2Dot(n, v2s[j] - v1); 53 | if (sij < si) { 54 | si = sij; 55 | } 56 | } 57 | 58 | if (si > maxSeparation) { 59 | maxSeparation = si; 60 | bestIndex = i; 61 | } 62 | } 63 | 64 | edgeIndex[0] = bestIndex; // *edgeIndex = bestIndex; 65 | return maxSeparation; 66 | } 67 | box2d.b2FindMaxSeparation.s_xf = new box2d.b2Transform(); 68 | box2d.b2FindMaxSeparation.s_n = new box2d.b2Vec2(); 69 | box2d.b2FindMaxSeparation.s_v1 = new box2d.b2Vec2(); 70 | 71 | /** 72 | * @export 73 | * @return {void} 74 | * @param {Array.} c 75 | * @param {box2d.b2PolygonShape} poly1 76 | * @param {box2d.b2Transform} xf1 77 | * @param {number} edge1 78 | * @param {box2d.b2PolygonShape} poly2 79 | * @param {box2d.b2Transform} xf2 80 | */ 81 | box2d.b2FindIncidentEdge = function(c, poly1, xf1, edge1, poly2, xf2) { 82 | var count1 = poly1.m_count; 83 | var normals1 = poly1.m_normals; 84 | 85 | var count2 = poly2.m_count; 86 | var vertices2 = poly2.m_vertices; 87 | var normals2 = poly2.m_normals; 88 | 89 | if (box2d.ENABLE_ASSERTS) { 90 | box2d.b2Assert(0 <= edge1 && edge1 < count1); 91 | } 92 | 93 | // Get the normal of the reference edge in poly2's frame. 94 | var normal1 = box2d.b2MulT_R_V2(xf2.q, box2d.b2Mul_R_V2(xf1.q, normals1[edge1], box2d.b2Vec2.s_t0), box2d.b2FindIncidentEdge.s_normal1); 95 | 96 | // Find the incident edge on poly2. 97 | var index = 0; 98 | var minDot = box2d.b2_maxFloat; 99 | for (var i = 0; i < count2; ++i) { 100 | var dot = box2d.b2Dot_V2_V2(normal1, normals2[i]); 101 | if (dot < minDot) { 102 | minDot = dot; 103 | index = i; 104 | } 105 | } 106 | 107 | // Build the clip vertices for the incident edge. 108 | var i1 = index; 109 | var i2 = (i1 + 1) % count2; 110 | 111 | var c0 = c[0]; 112 | box2d.b2Mul_X_V2(xf2, vertices2[i1], c0.v); 113 | var cf0 = c0.id.cf; 114 | cf0.indexA = edge1; 115 | cf0.indexB = i1; 116 | cf0.typeA = box2d.b2ContactFeatureType.e_face; 117 | cf0.typeB = box2d.b2ContactFeatureType.e_vertex; 118 | 119 | var c1 = c[1]; 120 | box2d.b2Mul_X_V2(xf2, vertices2[i2], c1.v); 121 | var cf1 = c1.id.cf; 122 | cf1.indexA = edge1; 123 | cf1.indexB = i2; 124 | cf1.typeA = box2d.b2ContactFeatureType.e_face; 125 | cf1.typeB = box2d.b2ContactFeatureType.e_vertex; 126 | } 127 | box2d.b2FindIncidentEdge.s_normal1 = new box2d.b2Vec2(); 128 | 129 | /** 130 | * Find edge normal of max separation on A - return if separating axis is found 131 | * Find edge normal of max separation on B - return if separation axis is found 132 | * Choose reference edge as min(minA, minB) 133 | * Find incident edge 134 | * Clip 135 | * The normal points from 1 to 2 136 | * @export 137 | * @return {void} 138 | * @param {box2d.b2Manifold} manifold 139 | * @param {box2d.b2PolygonShape} polyA 140 | * @param {box2d.b2Transform} xfA 141 | * @param {box2d.b2PolygonShape} polyB 142 | * @param {box2d.b2Transform} xfB 143 | */ 144 | box2d.b2CollidePolygons = function(manifold, polyA, xfA, polyB, xfB) { 145 | manifold.pointCount = 0; 146 | var totalRadius = polyA.m_radius + polyB.m_radius; 147 | 148 | var edgeA = box2d.b2CollidePolygons.s_edgeA; 149 | edgeA[0] = 0; 150 | var separationA = box2d.b2FindMaxSeparation(edgeA, polyA, xfA, polyB, xfB); 151 | if (separationA > totalRadius) 152 | return; 153 | 154 | var edgeB = box2d.b2CollidePolygons.s_edgeB; 155 | edgeB[0] = 0; 156 | var separationB = box2d.b2FindMaxSeparation(edgeB, polyB, xfB, polyA, xfA); 157 | if (separationB > totalRadius) 158 | return; 159 | 160 | var poly1; // reference polygon 161 | var poly2; // incident polygon 162 | var xf1, xf2; 163 | var edge1 = 0; // reference edge 164 | var flip = 0; 165 | var k_relativeTol = 0.98; 166 | var k_absoluteTol = 0.001; 167 | 168 | if (separationB > k_relativeTol * separationA + k_absoluteTol) { 169 | poly1 = polyB; 170 | poly2 = polyA; 171 | xf1 = xfB; 172 | xf2 = xfA; 173 | edge1 = edgeB[0]; 174 | manifold.type = box2d.b2ManifoldType.e_faceB; 175 | flip = 1; 176 | } else { 177 | poly1 = polyA; 178 | poly2 = polyB; 179 | xf1 = xfA; 180 | xf2 = xfB; 181 | edge1 = edgeA[0]; 182 | manifold.type = box2d.b2ManifoldType.e_faceA; 183 | flip = 0; 184 | } 185 | 186 | var incidentEdge = box2d.b2CollidePolygons.s_incidentEdge; 187 | box2d.b2FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2); 188 | 189 | var count1 = poly1.m_count; 190 | var vertices1 = poly1.m_vertices; 191 | 192 | var iv1 = edge1; 193 | var iv2 = (edge1 + 1) % count1; 194 | 195 | var local_v11 = vertices1[iv1]; 196 | var local_v12 = vertices1[iv2]; 197 | 198 | var localTangent = box2d.b2Sub_V2_V2(local_v12, local_v11, box2d.b2CollidePolygons.s_localTangent); 199 | localTangent.Normalize(); 200 | 201 | var localNormal = box2d.b2Cross_V2_S(localTangent, 1.0, box2d.b2CollidePolygons.s_localNormal); 202 | var planePoint = box2d.b2Mid_V2_V2(local_v11, local_v12, box2d.b2CollidePolygons.s_planePoint); 203 | 204 | var tangent = box2d.b2Mul_R_V2(xf1.q, localTangent, box2d.b2CollidePolygons.s_tangent); 205 | var normal = box2d.b2Cross_V2_S(tangent, 1.0, box2d.b2CollidePolygons.s_normal); 206 | 207 | var v11 = box2d.b2Mul_X_V2(xf1, local_v11, box2d.b2CollidePolygons.s_v11); 208 | var v12 = box2d.b2Mul_X_V2(xf1, local_v12, box2d.b2CollidePolygons.s_v12); 209 | 210 | // Face offset. 211 | var frontOffset = box2d.b2Dot_V2_V2(normal, v11); 212 | 213 | // Side offsets, extended by polytope skin thickness. 214 | var sideOffset1 = -box2d.b2Dot_V2_V2(tangent, v11) + totalRadius; 215 | var sideOffset2 = box2d.b2Dot_V2_V2(tangent, v12) + totalRadius; 216 | 217 | // Clip incident edge against extruded edge1 side edges. 218 | var clipPoints1 = box2d.b2CollidePolygons.s_clipPoints1; 219 | var clipPoints2 = box2d.b2CollidePolygons.s_clipPoints2; 220 | var np; 221 | 222 | // Clip to box side 1 223 | var ntangent = box2d.b2CollidePolygons.s_ntangent.Copy(tangent).SelfNeg(); 224 | np = box2d.b2ClipSegmentToLine(clipPoints1, incidentEdge, ntangent, sideOffset1, iv1); 225 | 226 | if (np < 2) 227 | return; 228 | 229 | // Clip to negative box side 1 230 | np = box2d.b2ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2); 231 | 232 | if (np < 2) { 233 | return; 234 | } 235 | 236 | // Now clipPoints2 contains the clipped points. 237 | manifold.localNormal.Copy(localNormal); 238 | manifold.localPoint.Copy(planePoint); 239 | 240 | var pointCount = 0; 241 | for (var i = 0; i < box2d.b2_maxManifoldPoints; ++i) { 242 | var cv = clipPoints2[i]; 243 | var separation = box2d.b2Dot_V2_V2(normal, cv.v) - frontOffset; 244 | 245 | if (separation <= totalRadius) { 246 | var cp = manifold.points[pointCount]; 247 | box2d.b2MulT_X_V2(xf2, cv.v, cp.localPoint); 248 | cp.id.Copy(cv.id); 249 | if (flip) { 250 | // Swap features 251 | /** @type {box2d.b2ContactFeature} */ 252 | var cf = cp.id.cf; 253 | cp.id.cf.indexA = cf.indexB; 254 | cp.id.cf.indexB = cf.indexA; 255 | cp.id.cf.typeA = cf.typeB; 256 | cp.id.cf.typeB = cf.typeA; 257 | } 258 | ++pointCount; 259 | } 260 | } 261 | 262 | manifold.pointCount = pointCount; 263 | } 264 | box2d.b2CollidePolygons.s_incidentEdge = box2d.b2ClipVertex.MakeArray(2); 265 | box2d.b2CollidePolygons.s_clipPoints1 = box2d.b2ClipVertex.MakeArray(2); 266 | box2d.b2CollidePolygons.s_clipPoints2 = box2d.b2ClipVertex.MakeArray(2); 267 | box2d.b2CollidePolygons.s_edgeA = box2d.b2MakeNumberArray(1); 268 | box2d.b2CollidePolygons.s_edgeB = box2d.b2MakeNumberArray(1); 269 | box2d.b2CollidePolygons.s_localTangent = new box2d.b2Vec2(); 270 | box2d.b2CollidePolygons.s_localNormal = new box2d.b2Vec2(); 271 | box2d.b2CollidePolygons.s_planePoint = new box2d.b2Vec2(); 272 | box2d.b2CollidePolygons.s_normal = new box2d.b2Vec2(); 273 | box2d.b2CollidePolygons.s_tangent = new box2d.b2Vec2(); 274 | box2d.b2CollidePolygons.s_ntangent = new box2d.b2Vec2(); 275 | box2d.b2CollidePolygons.s_v11 = new box2d.b2Vec2(); 276 | box2d.b2CollidePolygons.s_v12 = new box2d.b2Vec2(); 277 | -------------------------------------------------------------------------------- /Box2D/Common/b2BlockAllocator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | 20 | /** 21 | * @export 22 | * @constructor 23 | */ 24 | box2d.b2BlockAllocator = function() {} 25 | -------------------------------------------------------------------------------- /Box2D/Common/b2Draw.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | 20 | 21 | /** 22 | * Color for debug drawing. Each value has the range [0,1]. 23 | * @export 24 | * @constructor 25 | * @param {number} rr 26 | * @param {number} gg 27 | * @param {number} bb 28 | * @param {number=} aa 29 | */ 30 | box2d.b2Color = function(rr, gg, bb, aa) { 31 | this.r = rr; 32 | this.g = gg; 33 | this.b = bb; 34 | this.a = (typeof(aa) === 'number') ? (aa) : (1.0); 35 | } 36 | 37 | /** 38 | * @export 39 | * @type {number} 40 | */ 41 | box2d.b2Color.prototype.r = 0.5; 42 | /** 43 | * @export 44 | * @type {number} 45 | */ 46 | box2d.b2Color.prototype.g = 0.5; 47 | /** 48 | * @export 49 | * @type {number} 50 | */ 51 | box2d.b2Color.prototype.b = 0.5; 52 | /** 53 | * @export 54 | * @type {number} 55 | */ 56 | box2d.b2Color.prototype.a = 1.0; 57 | 58 | /** 59 | * @export 60 | * @return {box2d.b2Color} 61 | * @param {number} rr 62 | * @param {number} gg 63 | * @param {number} bb 64 | */ 65 | box2d.b2Color.prototype.SetRGB = function(rr, gg, bb) { 66 | this.r = rr; 67 | this.g = gg; 68 | this.b = bb; 69 | return this; 70 | } 71 | 72 | /** 73 | * @export 74 | * @return {string} 75 | * @param {number=} alpha 76 | */ 77 | box2d.b2Color.prototype.MakeStyleString = function(alpha) { 78 | var r = Math.round(Math.max(0, Math.min(255, this.r * 255))); 79 | var g = Math.round(Math.max(0, Math.min(255, this.g * 255))); 80 | var b = Math.round(Math.max(0, Math.min(255, this.b * 255))); 81 | var a = (typeof(alpha) === 'undefined') ? (this.a) : (Math.max(0, Math.min(1, alpha))); 82 | return box2d.b2Color.MakeStyleString(r, g, b, a); 83 | } 84 | 85 | /** 86 | * @export 87 | * @return {string} 88 | */ 89 | box2d.b2Color.MakeStyleString = function(r, g, b, a) { 90 | if (a < 1) { 91 | return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; 92 | } else { 93 | return 'rgb(' + r + ',' + g + ',' + b + ')'; 94 | } 95 | } 96 | 97 | /** 98 | * @export 99 | * @const 100 | * @type {box2d.b2Color} 101 | */ 102 | box2d.b2Color.RED = new box2d.b2Color(1, 0, 0); 103 | /** 104 | * @export 105 | * @const 106 | * @type {box2d.b2Color} 107 | */ 108 | box2d.b2Color.GREEN = new box2d.b2Color(0, 1, 0); 109 | /** 110 | * @export 111 | * @const 112 | * @type {box2d.b2Color} 113 | */ 114 | box2d.b2Color.BLUE = new box2d.b2Color(0, 0, 1); 115 | 116 | /** 117 | * @export 118 | * @enum 119 | */ 120 | box2d.b2DrawFlags = { 121 | e_none: 0, 122 | e_shapeBit: 0x0001, ///< draw shapes 123 | e_jointBit: 0x0002, ///< draw joint connections 124 | e_aabbBit: 0x0004, ///< draw axis aligned bounding boxes 125 | e_pairBit: 0x0008, ///< draw broad-phase pairs 126 | e_centerOfMassBit: 0x0010, ///< draw center of mass frame 127 | //#if B2_ENABLE_CONTROLLER 128 | e_controllerBit: 0x0020, /// @see box2d.b2Controller list 129 | //#endif 130 | //#if B2_ENABLE_PARTICLE 131 | e_particleBit: 0x0040, ///< draw particles 132 | //#endif 133 | e_all: 0xffff 134 | }; 135 | 136 | /** 137 | * Implement and register this class with a b2World to provide 138 | * debug drawing of physics entities in your game. 139 | * @export 140 | * @constructor 141 | */ 142 | box2d.b2Draw = function() {} 143 | 144 | /** 145 | * @export 146 | * @type {box2d.b2DrawFlags} 147 | */ 148 | box2d.b2Draw.prototype.m_drawFlags = box2d.b2DrawFlags.e_none; 149 | 150 | /** 151 | * Set the drawing flags. 152 | * @export 153 | * @return {void} 154 | * @param {box2d.b2DrawFlags} flags 155 | */ 156 | box2d.b2Draw.prototype.SetFlags = function(flags) { 157 | this.m_drawFlags = flags; 158 | } 159 | 160 | /** 161 | * Get the drawing flags. 162 | * @export 163 | * @return {box2d.b2DrawFlags} 164 | */ 165 | box2d.b2Draw.prototype.GetFlags = function() { 166 | return this.m_drawFlags; 167 | } 168 | 169 | /** 170 | * Append flags to the current flags. 171 | * @export 172 | * @return {void} 173 | * @param {box2d.b2DrawFlags} flags 174 | */ 175 | box2d.b2Draw.prototype.AppendFlags = function(flags) { 176 | this.m_drawFlags |= flags; 177 | } 178 | 179 | /** 180 | * Clear flags from the current flags. 181 | * @export 182 | * @return {void} 183 | * @param {box2d.b2DrawFlags} flags 184 | */ 185 | box2d.b2Draw.prototype.ClearFlags = function(flags) { 186 | this.m_drawFlags &= ~flags; 187 | } 188 | 189 | /** 190 | * @export 191 | * @return {void} 192 | * @param {box2d.b2Transform} xf 193 | */ 194 | box2d.b2Draw.prototype.PushTransform = function(xf) {} 195 | 196 | /** 197 | * @export 198 | * @return {void} 199 | * @param {box2d.b2Transform} xf 200 | */ 201 | box2d.b2Draw.prototype.PopTransform = function(xf) {} 202 | 203 | /** 204 | * Draw a closed polygon provided in CCW order. 205 | * @export 206 | * @return {void} 207 | * @param {Array.} vertices 208 | * @param {number} vertexCount 209 | * @param {box2d.b2Color} color 210 | */ 211 | box2d.b2Draw.prototype.DrawPolygon = function(vertices, vertexCount, color) {} 212 | 213 | /** 214 | * Draw a solid closed polygon provided in CCW order. 215 | * @export 216 | * @return {void} 217 | * @param {Array.} vertices 218 | * @param {number} vertexCount 219 | * @param {box2d.b2Color} color 220 | */ 221 | box2d.b2Draw.prototype.DrawSolidPolygon = function(vertices, vertexCount, color) {} 222 | 223 | /** 224 | * Draw a circle. 225 | * @export 226 | * @return {void} 227 | * @param {box2d.b2Vec2} center 228 | * @param {number} radius 229 | * @param {box2d.b2Color} color 230 | */ 231 | box2d.b2Draw.prototype.DrawCircle = function(center, radius, color) {} 232 | 233 | /** 234 | * Draw a solid circle. 235 | * @export 236 | * @return {void} 237 | * @param {box2d.b2Vec2} center 238 | * @param {number} radius 239 | * @param {box2d.b2Vec2} axis 240 | * @param {box2d.b2Color} color 241 | */ 242 | box2d.b2Draw.prototype.DrawSolidCircle = function(center, radius, axis, color) {} 243 | 244 | //#if B2_ENABLE_PARTICLE 245 | 246 | /** 247 | * Draw a particle array 248 | * @export 249 | * @return {void} 250 | * @param {Array.} centers 251 | * @param {number} radius 252 | * @param {Array.} colors 253 | * @param {number} count 254 | */ 255 | box2d.b2Draw.prototype.DrawParticles = function(centers, radius, colors, count) {} 256 | 257 | //#endif 258 | 259 | /** 260 | * Draw a line segment. 261 | * @export 262 | * @return {void} 263 | * @param {box2d.b2Vec2} p1 264 | * @param {box2d.b2Vec2} p2 265 | * @param {box2d.b2Color} color 266 | */ 267 | box2d.b2Draw.prototype.DrawSegment = function(p1, p2, color) {} 268 | 269 | /** 270 | * Draw a transform. Choose your own length scale. 271 | * @export 272 | * @return {void} 273 | * @param {box2d.b2Transform} xf a transform. 274 | */ 275 | box2d.b2Draw.prototype.DrawTransform = function(xf) {} 276 | -------------------------------------------------------------------------------- /Box2D/Common/b2GrowableStack.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | 20 | 21 | /** 22 | * This is a growable LIFO stack with an initial capacity of N. 23 | * If the stack size exceeds the initial capacity, the heap is 24 | * used to increase the size of the stack. 25 | * @export 26 | * @constructor 27 | * @param {number} N 28 | */ 29 | box2d.b2GrowableStack = function(N) { 30 | this.m_stack = new Array(N); 31 | } 32 | 33 | /** 34 | * @export 35 | * @type {Array.<*>} 36 | */ 37 | box2d.b2GrowableStack.prototype.m_stack = null; 38 | /** 39 | * @export 40 | * @type {number} 41 | */ 42 | box2d.b2GrowableStack.prototype.m_count = 0; 43 | 44 | /** 45 | * @export 46 | * @return {box2d.b2GrowableStack} 47 | */ 48 | box2d.b2GrowableStack.prototype.Reset = function() { 49 | this.m_count = 0; 50 | return this; 51 | } 52 | 53 | /** 54 | * @export 55 | * @return {void} 56 | * @param {*} element 57 | */ 58 | box2d.b2GrowableStack.prototype.Push = function(element) { 59 | this.m_stack[this.m_count] = element; 60 | ++this.m_count; 61 | } 62 | 63 | /** 64 | * @export 65 | * @return {*} 66 | */ 67 | box2d.b2GrowableStack.prototype.Pop = function() { 68 | if (box2d.ENABLE_ASSERTS) { 69 | box2d.b2Assert(this.m_count > 0); 70 | } 71 | --this.m_count; 72 | var element = this.m_stack[this.m_count]; 73 | this.m_stack[this.m_count] = null; 74 | return element; 75 | } 76 | 77 | /** 78 | * @export 79 | * @return {number} 80 | */ 81 | box2d.b2GrowableStack.prototype.GetCount = function() { 82 | return this.m_count; 83 | } 84 | -------------------------------------------------------------------------------- /Box2D/Common/b2Settings.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | 20 | //goog.require('goog.asserts'); 21 | //goog.require('goog.string.format'); 22 | let box2d = {} 23 | if (!Object.defineProperty) { 24 | Object.defineProperty = function(obj, name, options) { 25 | if (Object.__defineGetter__) { 26 | if ('get' in options) { 27 | obj.__defineGetter__(name, options.get); 28 | } else if ('value' in options) { 29 | obj.__defineGetter__(name, options.value); 30 | } 31 | } 32 | 33 | if (Object.__defineSetter__) { 34 | if ('set' in options) { 35 | obj.__defineSetter__(name, options.set); 36 | } else if ('value' in options) { 37 | obj.__defineSetter__(name, options.value); 38 | } 39 | } 40 | return obj; 41 | } 42 | } 43 | 44 | /** 45 | * @export 46 | * @define {boolean} 47 | */ 48 | box2d.DEBUG = false; 49 | 50 | /** 51 | * @export 52 | * @define {boolean} 53 | */ 54 | box2d.ENABLE_ASSERTS = box2d.DEBUG; 55 | 56 | /** 57 | * @export 58 | * @return {void} 59 | * @param {boolean} condition 60 | * @param {string=} opt_message 61 | * @param {...} var_args 62 | */ 63 | box2d.b2Assert = function(condition, opt_message, var_args) { 64 | if (box2d.DEBUG) { 65 | if (!condition) { 66 | throw new Error(); 67 | } 68 | 69 | //goog.asserts.assert(condition, opt_message, var_args); 70 | } 71 | } 72 | 73 | /** 74 | * @export 75 | * @const 76 | * @type {number} 77 | */ 78 | box2d.b2_maxFloat = 1E+37; // FLT_MAX instead of Number.MAX_VALUE; 79 | /** 80 | * @export 81 | * @const 82 | * @type {number} 83 | */ 84 | box2d.b2_epsilon = 1E-5; // FLT_EPSILON instead of Number.MIN_VALUE; 85 | /** 86 | * @export 87 | * @const 88 | * @type {number} 89 | */ 90 | box2d.b2_epsilon_sq = (box2d.b2_epsilon * box2d.b2_epsilon); 91 | /** 92 | * @export 93 | * @const 94 | * @type {number} 95 | */ 96 | box2d.b2_pi = Math.PI; 97 | 98 | /** 99 | * Global tuning constants based on meters-kilograms-seconds 100 | * (MKS) units. 101 | */ 102 | 103 | // Collision 104 | 105 | /** 106 | * The maximum number of contact points between two convex 107 | * shapes. Do not change this value. 108 | * @export 109 | * @const 110 | * @type {number} 111 | */ 112 | box2d.b2_maxManifoldPoints = 2; 113 | 114 | /** 115 | * The maximum number of vertices on a convex polygon. You 116 | * cannot increase this too much because b2BlockAllocator has a 117 | * maximum object size. 118 | * @export 119 | * @const 120 | * @type {number} 121 | */ 122 | box2d.b2_maxPolygonVertices = 8; 123 | 124 | /** 125 | * This is used to fatten AABBs in the dynamic tree. This allows 126 | * proxies to move by a small amount without triggering a tree 127 | * adjustment. 128 | * This is in meters. 129 | * @export 130 | * @const 131 | * @type {number} 132 | */ 133 | box2d.b2_aabbExtension = 0.1; 134 | 135 | /** 136 | * This is used to fatten AABBs in the dynamic tree. This is 137 | * used to predict the future position based on the current 138 | * displacement. 139 | * This is a dimensionless multiplier. 140 | * @export 141 | * @const 142 | * @type {number} 143 | */ 144 | box2d.b2_aabbMultiplier = 2; 145 | 146 | /** 147 | * A small length used as a collision and constraint tolerance. 148 | * Usually it is chosen to be numerically significant, but 149 | * visually insignificant. 150 | * @export 151 | * @const 152 | * @type {number} 153 | */ 154 | box2d.b2_linearSlop = 0.008; //0.005; 155 | 156 | /** 157 | * A small angle used as a collision and constraint tolerance. 158 | * Usually it is chosen to be numerically significant, but 159 | * visually insignificant. 160 | * @export 161 | * @const 162 | * @type {number} 163 | */ 164 | box2d.b2_angularSlop = 2 / 180 * box2d.b2_pi; 165 | 166 | /** 167 | * The radius of the polygon/edge shape skin. This should not be 168 | * modified. Making this smaller means polygons will have an 169 | * insufficient buffer for continuous collision. 170 | * Making it larger may create artifacts for vertex collision. 171 | * @export 172 | * @const 173 | * @type {number} 174 | */ 175 | box2d.b2_polygonRadius = 2 * box2d.b2_linearSlop; 176 | 177 | /** 178 | * Maximum number of sub-steps per contact in continuous physics 179 | * simulation. 180 | * @export 181 | * @const 182 | * @type {number} 183 | */ 184 | box2d.b2_maxSubSteps = 8; 185 | 186 | 187 | // Dynamics 188 | 189 | /** 190 | * Maximum number of contacts to be handled to solve a TOI 191 | * impact. 192 | * @export 193 | * @const 194 | * @type {number} 195 | */ 196 | box2d.b2_maxTOIContacts = 32; 197 | 198 | /** 199 | * A velocity threshold for elastic collisions. Any collision 200 | * with a relative linear velocity below this threshold will be 201 | * treated as inelastic. 202 | * @export 203 | * @const 204 | * @type {number} 205 | */ 206 | box2d.b2_velocityThreshold = 1; 207 | 208 | /** 209 | * The maximum linear position correction used when solving 210 | * constraints. This helps to prevent overshoot. 211 | * @export 212 | * @const 213 | * @type {number} 214 | */ 215 | box2d.b2_maxLinearCorrection = 0.2; 216 | 217 | /** 218 | * The maximum angular position correction used when solving 219 | * constraints. This helps to prevent overshoot. 220 | * @export 221 | * @const 222 | * @type {number} 223 | */ 224 | box2d.b2_maxAngularCorrection = 8 / 180 * box2d.b2_pi; 225 | 226 | /** 227 | * The maximum linear velocity of a body. This limit is very 228 | * large and is used to prevent numerical problems. You 229 | * shouldn't need to adjust this. 230 | * @export 231 | * @const 232 | * @type {number} 233 | */ 234 | box2d.b2_maxTranslation = 2; 235 | /** 236 | * @export 237 | * @const 238 | * @type {number} 239 | */ 240 | box2d.b2_maxTranslationSquared = box2d.b2_maxTranslation * box2d.b2_maxTranslation; 241 | 242 | /** 243 | * The maximum angular velocity of a body. This limit is very 244 | * large and is used to prevent numerical problems. You 245 | * shouldn't need to adjust this. 246 | * @export 247 | * @const 248 | * @type {number} 249 | */ 250 | box2d.b2_maxRotation = 0.5 * box2d.b2_pi; 251 | /** 252 | * @export 253 | * @const 254 | * @type {number} 255 | */ 256 | box2d.b2_maxRotationSquared = box2d.b2_maxRotation * box2d.b2_maxRotation; 257 | 258 | /** 259 | * This scale factor controls how fast overlap is resolved. 260 | * Ideally this would be 1 so that overlap is removed in one 261 | * time step. However using values close to 1 often lead to 262 | * overshoot. 263 | * @export 264 | * @const 265 | * @type {number} 266 | */ 267 | box2d.b2_baumgarte = 0.2; 268 | /** 269 | * @export 270 | * @const 271 | * @type {number} 272 | */ 273 | box2d.b2_toiBaumgarte = 0.75; 274 | 275 | 276 | 277 | //#if B2_ENABLE_PARTICLE 278 | 279 | // Particle 280 | 281 | /** 282 | * A symbolic constant that stands for particle allocation 283 | * error. 284 | * 285 | * @export 286 | * @const 287 | * @type {number} 288 | */ 289 | box2d.b2_invalidParticleIndex = -1; 290 | 291 | /** 292 | * @export 293 | * @const 294 | * @type {number} 295 | */ 296 | box2d.b2_maxParticleIndex = 0x7FFFFFFF; 297 | 298 | /** 299 | * The default distance between particles, multiplied by the 300 | * particle diameter. 301 | * 302 | * @export 303 | * @const 304 | * @type {number} 305 | */ 306 | box2d.b2_particleStride = 0.75; 307 | 308 | /** 309 | * The minimum particle weight that produces pressure. 310 | * 311 | * @export 312 | * @const 313 | * @type {number} 314 | */ 315 | box2d.b2_minParticleWeight = 1.0; 316 | 317 | /** 318 | * The upper limit for particle pressure. 319 | * 320 | * @export 321 | * @const 322 | * @type {number} 323 | */ 324 | box2d.b2_maxParticlePressure = 0.25; 325 | 326 | /** 327 | * The upper limit for force between particles. 328 | * 329 | * @export 330 | * @const 331 | * @type {number} 332 | */ 333 | box2d.b2_maxParticleForce = 0.5; 334 | 335 | /** 336 | * The maximum distance between particles in a triad, multiplied 337 | * by the particle diameter. 338 | * 339 | * @export 340 | * @const 341 | * @type {number} 342 | */ 343 | box2d.b2_maxTriadDistance = 2.0; 344 | 345 | /** 346 | * @export 347 | * @const 348 | * @type {number} 349 | */ 350 | box2d.b2_maxTriadDistanceSquared = (box2d.b2_maxTriadDistance * box2d.b2_maxTriadDistance); 351 | 352 | /** 353 | * The initial size of particle data buffers. 354 | * 355 | * @export 356 | * @const 357 | * @type {number} 358 | */ 359 | box2d.b2_minParticleSystemBufferCapacity = 256; 360 | 361 | /** 362 | * The time into the future that collisions against barrier 363 | * particles will be detected. 364 | * 365 | * @export 366 | * @const 367 | * @type {number} 368 | */ 369 | box2d.b2_barrierCollisionTime = 2.5; 370 | 371 | //#endif 372 | 373 | 374 | 375 | // Sleep 376 | 377 | /** 378 | * The time that a body must be still before it will go to 379 | * sleep. 380 | * @export 381 | * @const 382 | * @type {number} 383 | */ 384 | box2d.b2_timeToSleep = 0.5; 385 | 386 | /** 387 | * A body cannot sleep if its linear velocity is above this 388 | * tolerance. 389 | * @export 390 | * @const 391 | * @type {number} 392 | */ 393 | box2d.b2_linearSleepTolerance = 0.01; 394 | 395 | /** 396 | * A body cannot sleep if its angular velocity is above this 397 | * tolerance. 398 | * @export 399 | * @const 400 | * @type {number} 401 | */ 402 | box2d.b2_angularSleepTolerance = 2 / 180 * box2d.b2_pi; 403 | 404 | // Memory Allocation 405 | 406 | /** 407 | * Implement this function to use your own memory allocator. 408 | * @export 409 | * @return {*} 410 | * @param {number} size 411 | */ 412 | box2d.b2Alloc = function(size) { 413 | return null; 414 | } 415 | 416 | /** 417 | * If you implement b2Alloc, you should also implement this 418 | * function. 419 | * @export 420 | * @return {void} 421 | * @param {*} mem 422 | */ 423 | box2d.b2Free = function(mem) {} 424 | 425 | /** 426 | * Logging function. 427 | * You can modify this to use your logging facility. 428 | * @export 429 | * @return {void} 430 | * @param {...string|number|boolean} var_args 431 | */ 432 | box2d.b2Log = function(var_args) { 433 | goog.global.console.log.apply(null, arguments); 434 | } 435 | 436 | /** 437 | * Version numberinf scheme See 438 | * http://en.wikipedia.org/wiki/Software_versioning 439 | * @export 440 | * @constructor 441 | * @param {number=} major 442 | * @param {number=} minor 443 | * @param {number=} revision 444 | */ 445 | box2d.b2Version = function(major, minor, revision) { 446 | this.major = major || 0; 447 | this.minor = minor || 0; 448 | this.revision = revision || 0; 449 | }; 450 | 451 | /** 452 | * @export 453 | * @type {number} 454 | */ 455 | box2d.b2Version.prototype.major = 0; ///< significant changes 456 | /** 457 | * @export 458 | * @type {number} 459 | */ 460 | box2d.b2Version.prototype.minor = 0; ///< incremental changes 461 | /** 462 | * @export 463 | * @type {number} 464 | */ 465 | box2d.b2Version.prototype.revision = 0; ///< bug fixes 466 | 467 | /** 468 | * @export 469 | * @return {string} 470 | */ 471 | box2d.b2Version.prototype.toString = function() { 472 | return this.major + "." + this.minor + "." + this.revision; 473 | } 474 | 475 | /** 476 | * Current version. 477 | * @export 478 | * @const 479 | * @type {box2d.b2Version} 480 | */ 481 | box2d.b2_version = new box2d.b2Version(2, 3, 2); 482 | /** 483 | * @export 484 | * @const 485 | * @type {number} 486 | */ 487 | box2d.b2_changelist = 313; 488 | 489 | /** 490 | * @export 491 | * @return {number} 492 | * @param {string} v 493 | */ 494 | box2d.b2ParseInt = function(v) { 495 | return parseInt(v, 10); 496 | } 497 | 498 | /** 499 | * @export 500 | * @return {number} 501 | * @param {string} v 502 | */ 503 | box2d.b2ParseUInt = function(v) { 504 | return box2d.b2Abs(parseInt(v, 10)); 505 | } 506 | 507 | /** 508 | * @export 509 | * @return {Array.<*>} 510 | * @param {number=} length 511 | * @param {function(number): *=} init 512 | */ 513 | box2d.b2MakeArray = function(length, init) { 514 | length = (typeof(length) === 'number') ? (length) : (0); 515 | var a = []; 516 | if (typeof(init) === 'function') { 517 | for (var i = 0; i < length; ++i) { 518 | a.push(init(i)); 519 | } 520 | } else { 521 | for (var i = 0; i < length; ++i) { 522 | a.push(null); 523 | } 524 | } 525 | return a; 526 | } 527 | 528 | /** 529 | * @export 530 | * @return {Array.} 531 | * @param {number=} length 532 | */ 533 | box2d.b2MakeNumberArray = function(length) { 534 | return box2d.b2MakeArray(length, function(i) { 535 | return 0; 536 | }); 537 | } 538 | -------------------------------------------------------------------------------- /Box2D/Common/b2StackAllocator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | 20 | /** 21 | * @export 22 | * @constructor 23 | */ 24 | box2d.b2StackAllocator = function() {} 25 | -------------------------------------------------------------------------------- /Box2D/Common/b2Timer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | 20 | 21 | /** 22 | * Timer for profiling. This has platform specific code and may 23 | * not work on every platform. 24 | * @export 25 | * @constructor 26 | */ 27 | box2d.b2Timer = function() { 28 | this.m_start = new Date().getTime(); 29 | } 30 | 31 | /** 32 | * @export 33 | * @type {number} 34 | */ 35 | box2d.b2Timer.prototype.m_start = 0; 36 | 37 | /** 38 | * @export 39 | * @return {box2d.b2Timer} 40 | */ 41 | box2d.b2Timer.prototype.Reset = function() { 42 | this.m_start = new Date().getTime(); 43 | return this; 44 | } 45 | 46 | /** 47 | * @export 48 | * @return {number} 49 | */ 50 | box2d.b2Timer.prototype.GetMilliseconds = function() { 51 | return new Date().getTime() - this.m_start; 52 | } 53 | 54 | /** 55 | * @export 56 | * @constructor 57 | */ 58 | box2d.b2Counter = function() {} 59 | 60 | /** 61 | * @export 62 | * @type {number} 63 | */ 64 | box2d.b2Counter.prototype.m_count = 0; 65 | /** 66 | * @export 67 | * @type {number} 68 | */ 69 | box2d.b2Counter.prototype.m_min_count = 0; 70 | /** 71 | * @export 72 | * @type {number} 73 | */ 74 | box2d.b2Counter.prototype.m_max_count = 0; 75 | 76 | /** 77 | * @export 78 | * @return {number} 79 | */ 80 | box2d.b2Counter.prototype.GetCount = function() { 81 | return this.m_count; 82 | } 83 | 84 | /** 85 | * @export 86 | * @return {number} 87 | */ 88 | box2d.b2Counter.prototype.GetMinCount = function() { 89 | return this.m_min_count; 90 | } 91 | 92 | /** 93 | * @export 94 | * @return {number} 95 | */ 96 | box2d.b2Counter.prototype.GetMaxCount = function() { 97 | return this.m_max_count; 98 | } 99 | 100 | /** 101 | * @export 102 | * @return {number} 103 | */ 104 | box2d.b2Counter.prototype.ResetCount = function() { 105 | var count = this.m_count; 106 | this.m_count = 0; 107 | return count; 108 | } 109 | 110 | /** 111 | * @export 112 | * @return {void} 113 | */ 114 | box2d.b2Counter.prototype.ResetMinCount = function() { 115 | this.m_min_count = 0; 116 | } 117 | 118 | /** 119 | * @export 120 | * @return {void} 121 | */ 122 | box2d.b2Counter.prototype.ResetMaxCount = function() { 123 | this.m_max_count = 0; 124 | } 125 | 126 | /** 127 | * @export 128 | * @return {void} 129 | */ 130 | box2d.b2Counter.prototype.Increment = function() { 131 | this.m_count++; 132 | 133 | if (this.m_max_count < this.m_count) { 134 | this.m_max_count = this.m_count; 135 | } 136 | } 137 | 138 | /** 139 | * @export 140 | * @return {void} 141 | */ 142 | box2d.b2Counter.prototype.Decrement = function() { 143 | this.m_count--; 144 | 145 | if (this.m_min_count > this.m_count) { 146 | this.m_min_count = this.m_count; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2ChainAndCircleContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2ChainAndCircleContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | // goog.require('box2d.b2CollideEdge'); 24 | 25 | /** 26 | * @export 27 | * @constructor 28 | * @extends {box2d.b2Contact} 29 | */ 30 | box2d.b2ChainAndCircleContact = function() { 31 | box2d.b2Contact.call(this); // base class constructor 32 | }; 33 | 34 | box2d.b2ChainAndCircleContact.prototype = new box2d.b2Contact() 35 | 36 | /** 37 | * @export 38 | * @return {box2d.b2Contact} 39 | * @param allocator 40 | */ 41 | box2d.b2ChainAndCircleContact.Create = function(allocator) { 42 | return new box2d.b2ChainAndCircleContact(); 43 | } 44 | 45 | /** 46 | * @export 47 | * @return {void} 48 | * @param {box2d.b2Contact} contact 49 | * @param allocator 50 | */ 51 | box2d.b2ChainAndCircleContact.Destroy = function(contact, allocator) {} 52 | 53 | /** 54 | * @export 55 | * @return {void} 56 | * @param {box2d.b2Manifold} manifold 57 | * @param {box2d.b2Transform} xfA 58 | * @param {box2d.b2Transform} xfB 59 | */ 60 | box2d.b2ChainAndCircleContact.prototype.Evaluate = function(manifold, xfA, xfB) { 61 | var shapeA = this.m_fixtureA.GetShape(); 62 | var shapeB = this.m_fixtureB.GetShape(); 63 | if (box2d.ENABLE_ASSERTS) { 64 | box2d.b2Assert(shapeA instanceof box2d.b2ChainShape); 65 | } 66 | if (box2d.ENABLE_ASSERTS) { 67 | box2d.b2Assert(shapeB instanceof box2d.b2CircleShape); 68 | } 69 | /*box2d.b2ChainShape*/ 70 | var chain = (shapeA instanceof box2d.b2ChainShape) ? shapeA : null; 71 | /*box2d.b2EdgeShape*/ 72 | var edge = box2d.b2ChainAndCircleContact.prototype.Evaluate.s_edge; 73 | chain.GetChildEdge(edge, this.m_indexA); 74 | box2d.b2CollideEdgeAndCircle( 75 | manifold, 76 | edge, xfA, (shapeB instanceof box2d.b2CircleShape) ? shapeB : null, xfB); 77 | } 78 | box2d.b2ChainAndCircleContact.prototype.Evaluate.s_edge = new box2d.b2EdgeShape(); 79 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2ChainAndPolygonContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | // goog.require('box2d.b2CollideEdge'); 24 | // goog.require('box2d.b2ChainShape'); 25 | // goog.require('box2d.b2PolygonShape'); 26 | 27 | /** 28 | * @export 29 | * @constructor 30 | * @extends {box2d.b2Contact} 31 | */ 32 | box2d.b2ChainAndPolygonContact = function() { 33 | box2d.b2Contact.call(this); // base class constructor 34 | }; 35 | 36 | box2d.b2ChainAndPolygonContact.prototype = new box2d.b2Contact() 37 | 38 | /** 39 | * @export 40 | * @return {box2d.b2Contact} 41 | * @param allocator 42 | */ 43 | box2d.b2ChainAndPolygonContact.Create = function(allocator) { 44 | return new box2d.b2ChainAndPolygonContact(); 45 | } 46 | 47 | /** 48 | * @export 49 | * @return {void} 50 | * @param {box2d.b2Contact} contact 51 | * @param allocator 52 | */ 53 | box2d.b2ChainAndPolygonContact.Destroy = function(contact, allocator) {} 54 | 55 | /** 56 | * @export 57 | * @return {void} 58 | * @param {box2d.b2Manifold} manifold 59 | * @param {box2d.b2Transform} xfA 60 | * @param {box2d.b2Transform} xfB 61 | */ 62 | box2d.b2ChainAndPolygonContact.prototype.Evaluate = function(manifold, xfA, xfB) { 63 | var shapeA = this.m_fixtureA.GetShape(); 64 | var shapeB = this.m_fixtureB.GetShape(); 65 | if (box2d.ENABLE_ASSERTS) { 66 | box2d.b2Assert(shapeA instanceof box2d.b2ChainShape); 67 | } 68 | if (box2d.ENABLE_ASSERTS) { 69 | box2d.b2Assert(shapeB instanceof box2d.b2PolygonShape); 70 | } 71 | /*box2d.b2ChainShape*/ 72 | var chain = (shapeA instanceof box2d.b2ChainShape) ? shapeA : null; 73 | /*box2d.b2EdgeShape*/ 74 | var edge = box2d.b2ChainAndPolygonContact.prototype.Evaluate.s_edge; 75 | chain.GetChildEdge(edge, this.m_indexA); 76 | box2d.b2CollideEdgeAndPolygon( 77 | manifold, 78 | edge, xfA, (shapeB instanceof box2d.b2PolygonShape) ? shapeB : null, xfB); 79 | } 80 | box2d.b2ChainAndPolygonContact.prototype.Evaluate.s_edge = new box2d.b2EdgeShape(); 81 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2CircleContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2CircleContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | // goog.require('box2d.b2CollideCircle'); 24 | 25 | /** 26 | * @export 27 | * @constructor 28 | * @extends {box2d.b2Contact} 29 | */ 30 | box2d.b2CircleContact = function() { 31 | box2d.b2Contact.call(this); // base class constructor 32 | }; 33 | 34 | box2d.b2CircleContact.prototype = new box2d.b2Contact() 35 | 36 | /** 37 | * @export 38 | * @return {box2d.b2Contact} 39 | * @param allocator 40 | */ 41 | box2d.b2CircleContact.Create = function(allocator) { 42 | return new box2d.b2CircleContact(); 43 | } 44 | 45 | /** 46 | * @export 47 | * @return {void} 48 | * @param {box2d.b2Contact} contact 49 | * @param allocator 50 | */ 51 | box2d.b2CircleContact.Destroy = function(contact, allocator) {} 52 | 53 | /** 54 | * @export 55 | * @return {void} 56 | * @param {box2d.b2Manifold} manifold 57 | * @param {box2d.b2Transform} xfA 58 | * @param {box2d.b2Transform} xfB 59 | */ 60 | box2d.b2CircleContact.prototype.Evaluate = function(manifold, xfA, xfB) { 61 | var shapeA = this.m_fixtureA.GetShape(); 62 | var shapeB = this.m_fixtureB.GetShape(); 63 | if (box2d.ENABLE_ASSERTS) { 64 | box2d.b2Assert(shapeA instanceof box2d.b2CircleShape); 65 | } 66 | if (box2d.ENABLE_ASSERTS) { 67 | box2d.b2Assert(shapeB instanceof box2d.b2CircleShape); 68 | } 69 | box2d.b2CollideCircles( 70 | manifold, (shapeA instanceof box2d.b2CircleShape) ? shapeA : null, xfA, (shapeB instanceof box2d.b2CircleShape) ? shapeB : null, xfB); 71 | } 72 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2ContactFactory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2ContactFactory'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | 24 | /** 25 | * @export 26 | * @constructor 27 | */ 28 | box2d.b2ContactRegister = function() {}; 29 | 30 | box2d.b2ContactRegister.prototype.createFcn = null; 31 | box2d.b2ContactRegister.prototype.destroyFcn = null; 32 | box2d.b2ContactRegister.prototype.primary = false; 33 | 34 | /** 35 | * @export 36 | * @constructor 37 | * @param allocator 38 | */ 39 | box2d.b2ContactFactory = function(allocator) { 40 | this.m_allocator = allocator; 41 | this.InitializeRegisters(); 42 | } 43 | 44 | box2d.b2ContactFactory.prototype.m_allocator = null; 45 | 46 | /** 47 | * @export 48 | * @return {void} 49 | * @param createFcn 50 | * @param destroyFcn 51 | * @param {box2d.b2ShapeType} type1 52 | * @param {box2d.b2ShapeType} type2 53 | */ 54 | box2d.b2ContactFactory.prototype.AddType = function(createFcn, destroyFcn, type1, type2) { 55 | var pool = box2d.b2MakeArray(256, function(i) { 56 | return createFcn(); 57 | }); // TODO: b2Settings 58 | 59 | var poolCreateFcn = function(allocator) { 60 | if (pool.length > 0) { 61 | return pool.pop(); 62 | } 63 | 64 | return createFcn(allocator); 65 | } 66 | 67 | var poolDestroyFcn = function(contact, allocator) { 68 | pool.push(contact); 69 | } 70 | 71 | this.m_registers[type1][type2].pool = pool; 72 | this.m_registers[type1][type2].createFcn = poolCreateFcn; 73 | this.m_registers[type1][type2].destroyFcn = poolDestroyFcn; 74 | this.m_registers[type1][type2].primary = true; 75 | 76 | if (type1 !== type2) { 77 | this.m_registers[type2][type1].pool = pool; 78 | this.m_registers[type2][type1].createFcn = poolCreateFcn; 79 | this.m_registers[type2][type1].destroyFcn = poolDestroyFcn; 80 | this.m_registers[type2][type1].primary = false; 81 | } 82 | 83 | /* 84 | this.m_registers[type1][type2].createFcn = createFcn; 85 | this.m_registers[type1][type2].destroyFcn = destroyFcn; 86 | this.m_registers[type1][type2].primary = true; 87 | 88 | if (type1 !== type2) 89 | { 90 | this.m_registers[type2][type1].createFcn = createFcn; 91 | this.m_registers[type2][type1].destroyFcn = destroyFcn; 92 | this.m_registers[type2][type1].primary = false; 93 | } 94 | */ 95 | } 96 | 97 | /** 98 | * @export 99 | * @return {void} 100 | */ 101 | box2d.b2ContactFactory.prototype.InitializeRegisters = function() { 102 | this.m_registers = new Array(box2d.b2ShapeType.e_shapeTypeCount); 103 | 104 | for (var i = 0; i < box2d.b2ShapeType.e_shapeTypeCount; i++) { 105 | this.m_registers[i] = new Array(box2d.b2ShapeType.e_shapeTypeCount); 106 | 107 | for (var j = 0; j < box2d.b2ShapeType.e_shapeTypeCount; j++) { 108 | this.m_registers[i][j] = new box2d.b2ContactRegister(); 109 | } 110 | } 111 | 112 | this.AddType(box2d.b2CircleContact.Create, box2d.b2CircleContact.Destroy, box2d.b2ShapeType.e_circleShape, box2d.b2ShapeType.e_circleShape); 113 | this.AddType(box2d.b2PolygonAndCircleContact.Create, box2d.b2PolygonAndCircleContact.Destroy, box2d.b2ShapeType.e_polygonShape, box2d.b2ShapeType.e_circleShape); 114 | this.AddType(box2d.b2PolygonContact.Create, box2d.b2PolygonContact.Destroy, box2d.b2ShapeType.e_polygonShape, box2d.b2ShapeType.e_polygonShape); 115 | this.AddType(box2d.b2EdgeAndCircleContact.Create, box2d.b2EdgeAndCircleContact.Destroy, box2d.b2ShapeType.e_edgeShape, box2d.b2ShapeType.e_circleShape); 116 | this.AddType(box2d.b2EdgeAndPolygonContact.Create, box2d.b2EdgeAndPolygonContact.Destroy, box2d.b2ShapeType.e_edgeShape, box2d.b2ShapeType.e_polygonShape); 117 | this.AddType(box2d.b2ChainAndCircleContact.Create, box2d.b2ChainAndCircleContact.Destroy, box2d.b2ShapeType.e_chainShape, box2d.b2ShapeType.e_circleShape); 118 | this.AddType(box2d.b2ChainAndPolygonContact.Create, box2d.b2ChainAndPolygonContact.Destroy, box2d.b2ShapeType.e_chainShape, box2d.b2ShapeType.e_polygonShape); 119 | } 120 | 121 | /** 122 | * @export 123 | * @return {box2d.b2Contact} 124 | * @param {box2d.b2Fixture} fixtureA 125 | * @param {number} indexA 126 | * @param {box2d.b2Fixture} fixtureB 127 | * @param {number} indexB 128 | */ 129 | box2d.b2ContactFactory.prototype.Create = function(fixtureA, indexA, fixtureB, indexB) { 130 | var type1 = fixtureA.GetType(); 131 | var type2 = fixtureB.GetType(); 132 | 133 | if (box2d.ENABLE_ASSERTS) { 134 | box2d.b2Assert(0 <= type1 && type1 < box2d.b2ShapeType.e_shapeTypeCount); 135 | } 136 | if (box2d.ENABLE_ASSERTS) { 137 | box2d.b2Assert(0 <= type2 && type2 < box2d.b2ShapeType.e_shapeTypeCount); 138 | } 139 | 140 | var reg = this.m_registers[type1][type2]; 141 | 142 | var createFcn = reg.createFcn; 143 | if (createFcn !== null) { 144 | if (reg.primary) { 145 | var c = createFcn(this.m_allocator); 146 | c.Reset(fixtureA, indexA, fixtureB, indexB); 147 | return c; 148 | } else { 149 | var c = createFcn(this.m_allocator); 150 | c.Reset(fixtureB, indexB, fixtureA, indexA); 151 | return c; 152 | } 153 | } else { 154 | return null; 155 | } 156 | } 157 | 158 | /** 159 | * @export 160 | * @return {void} 161 | * @param {box2d.b2Contact} contact 162 | */ 163 | box2d.b2ContactFactory.prototype.Destroy = function(contact) { 164 | var fixtureA = contact.m_fixtureA; 165 | var fixtureB = contact.m_fixtureB; 166 | 167 | if (contact.m_manifold.pointCount > 0 && 168 | !fixtureA.IsSensor() && 169 | !fixtureB.IsSensor()) { 170 | fixtureA.GetBody().SetAwake(true); 171 | fixtureB.GetBody().SetAwake(true); 172 | } 173 | 174 | var typeA = fixtureA.GetType(); 175 | var typeB = fixtureB.GetType(); 176 | 177 | if (box2d.ENABLE_ASSERTS) { 178 | box2d.b2Assert(0 <= typeA && typeB < box2d.b2ShapeType.e_shapeTypeCount); 179 | } 180 | if (box2d.ENABLE_ASSERTS) { 181 | box2d.b2Assert(0 <= typeA && typeB < box2d.b2ShapeType.e_shapeTypeCount); 182 | } 183 | 184 | var reg = this.m_registers[typeA][typeB]; 185 | 186 | var destroyFcn = reg.destroyFcn; 187 | destroyFcn(contact, this.m_allocator); 188 | } 189 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2EdgeAndCircleContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | // goog.require('box2d.b2CollideEdge'); 24 | 25 | /** 26 | * @export 27 | * @constructor 28 | * @extends {box2d.b2Contact} 29 | */ 30 | box2d.b2EdgeAndCircleContact = function() { 31 | box2d.b2Contact.call(this); // base class constructor 32 | }; 33 | 34 | box2d.b2EdgeAndCircleContact.prototype = new box2d.b2Contact() 35 | 36 | /** 37 | * @export 38 | * @return {box2d.b2Contact} 39 | * @param allocator 40 | */ 41 | box2d.b2EdgeAndCircleContact.Create = function(allocator) { 42 | return new box2d.b2EdgeAndCircleContact(); 43 | } 44 | 45 | /** 46 | * @export 47 | * @return {void} 48 | * @param {box2d.b2Contact} contact 49 | * @param allocator 50 | */ 51 | box2d.b2EdgeAndCircleContact.Destroy = function(contact, allocator) {} 52 | 53 | /** 54 | * @export 55 | * @return {void} 56 | * @param {box2d.b2Manifold} manifold 57 | * @param {box2d.b2Transform} xfA 58 | * @param {box2d.b2Transform} xfB 59 | */ 60 | box2d.b2EdgeAndCircleContact.prototype.Evaluate = function(manifold, xfA, xfB) { 61 | var shapeA = this.m_fixtureA.GetShape(); 62 | var shapeB = this.m_fixtureB.GetShape(); 63 | if (box2d.ENABLE_ASSERTS) { 64 | box2d.b2Assert(shapeA instanceof box2d.b2EdgeShape); 65 | } 66 | if (box2d.ENABLE_ASSERTS) { 67 | box2d.b2Assert(shapeB instanceof box2d.b2CircleShape); 68 | } 69 | box2d.b2CollideEdgeAndCircle( 70 | manifold, (shapeA instanceof box2d.b2EdgeShape) ? shapeA : null, xfA, (shapeB instanceof box2d.b2CircleShape) ? shapeB : null, xfB); 71 | } 72 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2EdgeAndPolygonContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | 24 | /** 25 | * @export 26 | * @constructor 27 | * @extends {box2d.b2Contact} 28 | */ 29 | box2d.b2EdgeAndPolygonContact = function() { 30 | box2d.b2Contact.call(this); // base class constructor 31 | }; 32 | 33 | box2d.b2EdgeAndPolygonContact.prototype = new box2d.b2Contact() 34 | 35 | /** 36 | * @export 37 | * @return {box2d.b2Contact} 38 | * @param allocator 39 | */ 40 | box2d.b2EdgeAndPolygonContact.Create = function(allocator) { 41 | return new box2d.b2EdgeAndPolygonContact(); 42 | } 43 | 44 | /** 45 | * @export 46 | * @return {void} 47 | * @param {box2d.b2Contact} contact 48 | * @param allocator 49 | */ 50 | box2d.b2EdgeAndPolygonContact.Destroy = function(contact, allocator) {} 51 | 52 | /** 53 | * @export 54 | * @return {void} 55 | * @param {box2d.b2Manifold} manifold 56 | * @param {box2d.b2Transform} xfA 57 | * @param {box2d.b2Transform} xfB 58 | */ 59 | box2d.b2EdgeAndPolygonContact.prototype.Evaluate = function(manifold, xfA, xfB) { 60 | var shapeA = this.m_fixtureA.GetShape(); 61 | var shapeB = this.m_fixtureB.GetShape(); 62 | if (box2d.ENABLE_ASSERTS) { 63 | box2d.b2Assert(shapeA instanceof box2d.b2EdgeShape); 64 | } 65 | if (box2d.ENABLE_ASSERTS) { 66 | box2d.b2Assert(shapeB instanceof box2d.b2PolygonShape); 67 | } 68 | box2d.b2CollideEdgeAndPolygon( 69 | manifold, (shapeA instanceof box2d.b2EdgeShape) ? shapeA : null, xfA, (shapeB instanceof box2d.b2PolygonShape) ? shapeB : null, xfB); 70 | } 71 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2PolygonAndCircleContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | 24 | /** 25 | * @export 26 | * @constructor 27 | * @extends {box2d.b2Contact} 28 | */ 29 | box2d.b2PolygonAndCircleContact = function() { 30 | box2d.b2Contact.call(this); // base class constructor 31 | }; 32 | 33 | box2d.b2PolygonAndCircleContact.prototype = new box2d.b2Contact() 34 | 35 | /** 36 | * @export 37 | * @return {box2d.b2Contact} 38 | * @param allocator 39 | */ 40 | box2d.b2PolygonAndCircleContact.Create = function(allocator) { 41 | return new box2d.b2PolygonAndCircleContact(); 42 | } 43 | 44 | /** 45 | * @export 46 | * @return {void} 47 | * @param {box2d.b2Contact} contact 48 | * @param allocator 49 | */ 50 | box2d.b2PolygonAndCircleContact.Destroy = function(contact, allocator) {} 51 | 52 | /** 53 | * @export 54 | * @return {void} 55 | * @param {box2d.b2Manifold} manifold 56 | * @param {box2d.b2Transform} xfA 57 | * @param {box2d.b2Transform} xfB 58 | */ 59 | box2d.b2PolygonAndCircleContact.prototype.Evaluate = function(manifold, xfA, xfB) { 60 | var shapeA = this.m_fixtureA.GetShape(); 61 | var shapeB = this.m_fixtureB.GetShape(); 62 | if (box2d.ENABLE_ASSERTS) { 63 | box2d.b2Assert(shapeA instanceof box2d.b2PolygonShape); 64 | } 65 | if (box2d.ENABLE_ASSERTS) { 66 | box2d.b2Assert(shapeB instanceof box2d.b2CircleShape); 67 | } 68 | box2d.b2CollidePolygonAndCircle( 69 | manifold, (shapeA instanceof box2d.b2PolygonShape) ? shapeA : null, xfA, (shapeB instanceof box2d.b2CircleShape) ? shapeB : null, xfB); 70 | } 71 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Contacts/b2PolygonContact.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2PolygonContact'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Contact'); 23 | // goog.require('box2d.b2CollidePolygon'); 24 | 25 | /** 26 | * @export 27 | * @constructor 28 | * @extends {box2d.b2Contact} 29 | */ 30 | box2d.b2PolygonContact = function() { 31 | box2d.b2Contact.call(this); // base class constructor 32 | }; 33 | 34 | box2d.b2PolygonContact.prototype = new box2d.b2Contact() 35 | 36 | /** 37 | * @export 38 | * @return {box2d.b2Contact} 39 | * @param allocator 40 | */ 41 | box2d.b2PolygonContact.Create = function(allocator) { 42 | return new box2d.b2PolygonContact(); 43 | } 44 | 45 | /** 46 | * @export 47 | * @return {void} 48 | * @param {box2d.b2Contact} contact 49 | * @param allocator 50 | */ 51 | box2d.b2PolygonContact.Destroy = function(contact, allocator) {} 52 | 53 | /** 54 | * @export 55 | * @return {void} 56 | * @param {box2d.b2Manifold} manifold 57 | * @param {box2d.b2Transform} xfA 58 | * @param {box2d.b2Transform} xfB 59 | */ 60 | box2d.b2PolygonContact.prototype.Evaluate = function(manifold, xfA, xfB) { 61 | var shapeA = this.m_fixtureA.GetShape(); 62 | var shapeB = this.m_fixtureB.GetShape(); 63 | if (box2d.ENABLE_ASSERTS) { 64 | box2d.b2Assert(shapeA instanceof box2d.b2PolygonShape); 65 | } 66 | if (box2d.ENABLE_ASSERTS) { 67 | box2d.b2Assert(shapeB instanceof box2d.b2PolygonShape); 68 | } 69 | box2d.b2CollidePolygons( 70 | manifold, (shapeA instanceof box2d.b2PolygonShape) ? shapeA : null, xfA, (shapeB instanceof box2d.b2PolygonShape) ? shapeB : null, xfB); 71 | } 72 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Joints/b2AreaJoint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2AreaJoint'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Joint'); 23 | // goog.require('box2d.b2Math'); 24 | 25 | /** 26 | * Definition for a {@link box2d.b2AreaJoint}, which connects a 27 | * group a bodies together so they maintain a constant area 28 | * within them. 29 | * @export 30 | * @constructor 31 | * @extends {box2d.b2JointDef} 32 | */ 33 | box2d.b2AreaJointDef = function() { 34 | box2d.b2JointDef.call(this, box2d.b2JointType.e_areaJoint); // base class constructor 35 | 36 | this.bodies = new Array(); 37 | } 38 | 39 | setInherit(box2d.b2AreaJointDef, box2d.b2JointDef) 40 | 41 | /** 42 | * @export 43 | * @type {box2d.b2World} 44 | */ 45 | box2d.b2AreaJointDef.prototype.world = null; 46 | 47 | /** 48 | * @export 49 | * @type {Array.} 50 | */ 51 | box2d.b2AreaJointDef.prototype.bodies = null; 52 | 53 | /** 54 | * The mass-spring-damper frequency in Hertz. A value of 0 55 | * disables softness. 56 | * @export 57 | * @type {number} 58 | */ 59 | box2d.b2AreaJointDef.prototype.frequencyHz = 0; 60 | 61 | /** 62 | * The damping ratio. 0 = no damping, 1 = critical damping. 63 | * @export 64 | * @type {number} 65 | */ 66 | box2d.b2AreaJointDef.prototype.dampingRatio = 0; 67 | 68 | /** 69 | * @export 70 | * @return {void} 71 | * @param {box2d.b2Body} body 72 | */ 73 | box2d.b2AreaJointDef.prototype.AddBody = function(body) { 74 | this.bodies.push(body); 75 | 76 | if (this.bodies.length === 1) { 77 | this.bodyA = body; 78 | } else if (this.bodies.length === 2) { 79 | this.bodyB = body; 80 | } 81 | } 82 | 83 | /** 84 | * A distance joint constrains two points on two bodies to 85 | * remain at a fixed distance from each other. You can view this 86 | * as a massless, rigid rod. 87 | * @export 88 | * @constructor 89 | * @extends {box2d.b2Joint} 90 | * @param {box2d.b2AreaJointDef} def 91 | */ 92 | box2d.b2AreaJoint = function(def) { 93 | box2d.b2Joint.call(this, def); // base class constructor 94 | 95 | if (box2d.ENABLE_ASSERTS) { 96 | box2d.b2Assert(def.bodies.length >= 3, "You cannot create an area joint with less than three bodies."); 97 | } 98 | 99 | this.m_bodies = def.bodies; 100 | this.m_frequencyHz = def.frequencyHz; 101 | this.m_dampingRatio = def.dampingRatio; 102 | 103 | this.m_targetLengths = box2d.b2MakeNumberArray(def.bodies.length); 104 | this.m_normals = box2d.b2Vec2.MakeArray(def.bodies.length); 105 | this.m_joints = new Array(def.bodies.length); 106 | this.m_deltas = box2d.b2Vec2.MakeArray(def.bodies.length); 107 | this.m_delta = new box2d.b2Vec2(); 108 | 109 | var djd = new box2d.b2DistanceJointDef(); 110 | djd.frequencyHz = def.frequencyHz; 111 | djd.dampingRatio = def.dampingRatio; 112 | 113 | this.m_targetArea = 0; 114 | 115 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 116 | var body = this.m_bodies[i]; 117 | var next = this.m_bodies[(i + 1) % ict]; 118 | 119 | var body_c = body.GetWorldCenter(); 120 | var next_c = next.GetWorldCenter(); 121 | 122 | this.m_targetLengths[i] = box2d.b2Distance(body_c, next_c); 123 | 124 | this.m_targetArea += box2d.b2Cross_V2_V2(body_c, next_c); 125 | 126 | djd.Initialize(body, next, body_c, next_c); 127 | this.m_joints[i] = def.world.CreateJoint(djd); 128 | } 129 | 130 | this.m_targetArea *= 0.5; 131 | } 132 | 133 | setInherit(box2d.b2AreaJoint, box2d.b2Joint) 134 | 135 | /** 136 | * @export 137 | * @type {Array.} 138 | */ 139 | box2d.b2AreaJoint.prototype.m_bodies = null; 140 | /** 141 | * @export 142 | * @type {number} 143 | */ 144 | box2d.b2AreaJoint.prototype.m_frequencyHz = 0; 145 | /** 146 | * @export 147 | * @type {number} 148 | */ 149 | box2d.b2AreaJoint.prototype.m_dampingRatio = 0; 150 | 151 | // Solver shared 152 | /** 153 | * @export 154 | * @type {number} 155 | */ 156 | box2d.b2AreaJoint.prototype.m_impulse = 0; 157 | 158 | // Solver temp 159 | box2d.b2AreaJoint.prototype.m_targetLengths = null; 160 | box2d.b2AreaJoint.prototype.m_targetArea = 0; 161 | box2d.b2AreaJoint.prototype.m_normals = null; 162 | box2d.b2AreaJoint.prototype.m_joints = null; 163 | box2d.b2AreaJoint.prototype.m_deltas = null; 164 | box2d.b2AreaJoint.prototype.m_delta = null; 165 | 166 | /** 167 | * @export 168 | * @return {box2d.b2Vec2} 169 | * @param {box2d.b2Vec2} out 170 | */ 171 | box2d.b2AreaJoint.prototype.GetAnchorA = function(out) { 172 | return out.SetZero(); 173 | } 174 | 175 | /** 176 | * @export 177 | * @return {box2d.b2Vec2} 178 | * @param {box2d.b2Vec2} out 179 | */ 180 | box2d.b2AreaJoint.prototype.GetAnchorB = function(out) { 181 | return out.SetZero(); 182 | } 183 | 184 | /** 185 | * Get the reaction force given the inverse time step. 186 | * Unit is N. 187 | * @export 188 | * @return {box2d.b2Vec2} 189 | * @param {number} inv_dt 190 | * @param {box2d.b2Vec2} out 191 | */ 192 | box2d.b2AreaJoint.prototype.GetReactionForce = function(inv_dt, out) { 193 | return out.SetZero(); 194 | } 195 | 196 | /** 197 | * Get the reaction torque given the inverse time step. 198 | * Unit is N*m. This is always zero for a distance joint. 199 | * @export 200 | * @return {number} 201 | * @param {number} inv_dt 202 | */ 203 | box2d.b2AreaJoint.prototype.GetReactionTorque = function(inv_dt) { 204 | return 0; 205 | } 206 | 207 | /** 208 | * Set/get frequency in Hz. 209 | * @export 210 | * @return {void} 211 | * @param {number} hz 212 | */ 213 | box2d.b2AreaJoint.prototype.SetFrequency = function(hz) { 214 | this.m_frequencyHz = hz; 215 | 216 | for (var i = 0, ict = this.m_joints.length; i < ict; ++i) { 217 | this.m_joints[i].SetFrequency(hz); 218 | } 219 | } 220 | 221 | /** 222 | * @export 223 | * @return {number} 224 | */ 225 | box2d.b2AreaJoint.prototype.GetFrequency = function() { 226 | return this.m_frequencyHz; 227 | } 228 | 229 | /** 230 | * Set/get damping ratio. 231 | * @export 232 | * @return {void} 233 | * @param {number} ratio 234 | */ 235 | box2d.b2AreaJoint.prototype.SetDampingRatio = function(ratio) { 236 | this.m_dampingRatio = ratio; 237 | 238 | for (var i = 0, ict = this.m_joints.length; i < ict; ++i) { 239 | this.m_joints[i].SetDampingRatio(ratio); 240 | } 241 | } 242 | 243 | /** 244 | * @export 245 | * @return {number} 246 | */ 247 | box2d.b2AreaJoint.prototype.GetDampingRatio = function() { 248 | return this.m_dampingRatio; 249 | } 250 | 251 | /** 252 | * Dump joint to dmLog 253 | * @export 254 | * @return {void} 255 | */ 256 | box2d.b2AreaJoint.prototype.Dump = function() { 257 | if (box2d.DEBUG) { 258 | box2d.b2Log("Area joint dumping is not supported.\n"); 259 | } 260 | } 261 | 262 | /** 263 | * @export 264 | * @return {void} 265 | * @param {box2d.b2SolverData} data 266 | */ 267 | box2d.b2AreaJoint.prototype.InitVelocityConstraints = function(data) { 268 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 269 | var prev = this.m_bodies[(i + ict - 1) % ict]; 270 | var next = this.m_bodies[(i + 1) % ict]; 271 | var prev_c = data.positions[prev.m_islandIndex].c; 272 | var next_c = data.positions[next.m_islandIndex].c; 273 | var delta = this.m_deltas[i]; 274 | 275 | box2d.b2Sub_V2_V2(next_c, prev_c, delta); 276 | } 277 | 278 | if (data.step.warmStarting) { 279 | this.m_impulse *= data.step.dtRatio; 280 | 281 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 282 | var body = this.m_bodies[i]; 283 | var body_v = data.velocities[body.m_islandIndex].v; 284 | var delta = this.m_deltas[i]; 285 | 286 | body_v.x += body.m_invMass * delta.y * 0.5 * this.m_impulse; 287 | body_v.y += body.m_invMass * -delta.x * 0.5 * this.m_impulse; 288 | } 289 | } else { 290 | this.m_impulse = 0; 291 | } 292 | } 293 | 294 | /** 295 | * @export 296 | * @return {void} 297 | * @param {box2d.b2SolverData} data 298 | */ 299 | box2d.b2AreaJoint.prototype.SolveVelocityConstraints = function(data) { 300 | var dotMassSum = 0; 301 | var crossMassSum = 0; 302 | 303 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 304 | var body = this.m_bodies[i]; 305 | var body_v = data.velocities[body.m_islandIndex].v; 306 | var delta = this.m_deltas[i]; 307 | 308 | dotMassSum += delta.LengthSquared() / body.GetMass(); 309 | crossMassSum += box2d.b2Cross_V2_V2(body_v, delta); 310 | } 311 | 312 | var lambda = -2 * crossMassSum / dotMassSum; 313 | //lambda = box2d.b2Clamp(lambda, -box2d.b2_maxLinearCorrection, box2d.b2_maxLinearCorrection); 314 | 315 | this.m_impulse += lambda; 316 | 317 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 318 | var body = this.m_bodies[i]; 319 | var body_v = data.velocities[body.m_islandIndex].v; 320 | var delta = this.m_deltas[i]; 321 | 322 | body_v.x += body.m_invMass * delta.y * 0.5 * lambda; 323 | body_v.y += body.m_invMass * -delta.x * 0.5 * lambda; 324 | } 325 | } 326 | 327 | /** 328 | * @export 329 | * @return {boolean} 330 | * @param {box2d.b2SolverData} data 331 | */ 332 | box2d.b2AreaJoint.prototype.SolvePositionConstraints = function(data) { 333 | var perimeter = 0; 334 | var area = 0; 335 | 336 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 337 | var body = this.m_bodies[i]; 338 | var next = this.m_bodies[(i + 1) % ict]; 339 | var body_c = data.positions[body.m_islandIndex].c; 340 | var next_c = data.positions[next.m_islandIndex].c; 341 | 342 | var delta = box2d.b2Sub_V2_V2(next_c, body_c, this.m_delta); 343 | 344 | var dist = delta.Length(); 345 | if (dist < box2d.b2_epsilon) { 346 | dist = 1; 347 | } 348 | 349 | this.m_normals[i].x = delta.y / dist; 350 | this.m_normals[i].y = -delta.x / dist; 351 | 352 | perimeter += dist; 353 | 354 | area += box2d.b2Cross_V2_V2(body_c, next_c); 355 | } 356 | 357 | area *= 0.5; 358 | 359 | var deltaArea = this.m_targetArea - area; 360 | var toExtrude = 0.5 * deltaArea / perimeter; 361 | var done = true; 362 | 363 | for (var i = 0, ict = this.m_bodies.length; i < ict; ++i) { 364 | var body = this.m_bodies[i]; 365 | var body_c = data.positions[body.m_islandIndex].c; 366 | var next_i = (i + 1) % ict; 367 | 368 | var delta = box2d.b2Add_V2_V2(this.m_normals[i], this.m_normals[next_i], this.m_delta); 369 | delta.SelfMul(toExtrude); 370 | 371 | var norm_sq = delta.LengthSquared(); 372 | if (norm_sq > box2d.b2Sq(box2d.b2_maxLinearCorrection)) { 373 | delta.SelfMul(box2d.b2_maxLinearCorrection / box2d.b2Sqrt(norm_sq)); 374 | } 375 | if (norm_sq > box2d.b2Sq(box2d.b2_linearSlop)) { 376 | done = false; 377 | } 378 | 379 | body_c.x += delta.x; 380 | body_c.y += delta.y; 381 | } 382 | 383 | return done; 384 | } 385 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Joints/b2Joint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2Joint'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Math'); 23 | 24 | /** 25 | * @export 26 | * @enum 27 | */ 28 | box2d.b2JointType = { 29 | e_unknownJoint: 0, 30 | e_revoluteJoint: 1, 31 | e_prismaticJoint: 2, 32 | e_distanceJoint: 3, 33 | e_pulleyJoint: 4, 34 | e_mouseJoint: 5, 35 | e_gearJoint: 6, 36 | e_wheelJoint: 7, 37 | e_weldJoint: 8, 38 | e_frictionJoint: 9, 39 | e_ropeJoint: 10, 40 | e_motorJoint: 11, 41 | e_areaJoint: 12 42 | }; 43 | // goog.exportProperty(box2d.b2JointType, 'e_unknownJoint', box2d.b2JointType.e_unknownJoint); 44 | // goog.exportProperty(box2d.b2JointType, 'e_revoluteJoint', box2d.b2JointType.e_revoluteJoint); 45 | // goog.exportProperty(box2d.b2JointType, 'e_prismaticJoint', box2d.b2JointType.e_prismaticJoint); 46 | // goog.exportProperty(box2d.b2JointType, 'e_distanceJoint', box2d.b2JointType.e_distanceJoint); 47 | // goog.exportProperty(box2d.b2JointType, 'e_pulleyJoint', box2d.b2JointType.e_pulleyJoint); 48 | // goog.exportProperty(box2d.b2JointType, 'e_mouseJoint', box2d.b2JointType.e_mouseJoint); 49 | // goog.exportProperty(box2d.b2JointType, 'e_gearJoint', box2d.b2JointType.e_gearJoint); 50 | // goog.exportProperty(box2d.b2JointType, 'e_wheelJoint', box2d.b2JointType.e_wheelJoint); 51 | // goog.exportProperty(box2d.b2JointType, 'e_weldJoint', box2d.b2JointType.e_weldJoint); 52 | // goog.exportProperty(box2d.b2JointType, 'e_frictionJoint', box2d.b2JointType.e_frictionJoint); 53 | // goog.exportProperty(box2d.b2JointType, 'e_ropeJoint', box2d.b2JointType.e_ropeJoint); 54 | // goog.exportProperty(box2d.b2JointType, 'e_motorJoint', box2d.b2JointType.e_motorJoint); 55 | // goog.exportProperty(box2d.b2JointType, 'e_areaJoint', box2d.b2JointType.e_areaJoint); 56 | 57 | /** 58 | * @export 59 | * @enum 60 | */ 61 | box2d.b2LimitState = { 62 | e_inactiveLimit: 0, 63 | e_atLowerLimit: 1, 64 | e_atUpperLimit: 2, 65 | e_equalLimits: 3 66 | }; 67 | // goog.exportProperty(box2d.b2LimitState, 'e_inactiveLimit', box2d.b2LimitState.e_inactiveLimit); 68 | // goog.exportProperty(box2d.b2LimitState, 'e_atLowerLimit', box2d.b2LimitState.e_atLowerLimit); 69 | // goog.exportProperty(box2d.b2LimitState, 'e_atUpperLimit', box2d.b2LimitState.e_atUpperLimit); 70 | // goog.exportProperty(box2d.b2LimitState, 'e_equalLimits', box2d.b2LimitState.e_equalLimits); 71 | 72 | /** 73 | * @export 74 | * @constructor 75 | */ 76 | box2d.b2Jacobian = function() { 77 | this.linear = new box2d.b2Vec2(); 78 | }; 79 | 80 | /** 81 | * @export 82 | * @type {box2d.b2Vec2} 83 | */ 84 | box2d.b2Jacobian.prototype.linear = null; 85 | /** 86 | * @export 87 | * @type {number} 88 | */ 89 | box2d.b2Jacobian.prototype.angularA = 0; 90 | /** 91 | * @export 92 | * @type {number} 93 | */ 94 | box2d.b2Jacobian.prototype.angularB = 0; 95 | 96 | /** 97 | * @export 98 | * @return {box2d.b2Jacobian} 99 | */ 100 | box2d.b2Jacobian.prototype.SetZero = function() { 101 | this.linear.SetZero(); 102 | this.angularA = 0; 103 | this.angularB = 0; 104 | return this; 105 | } 106 | 107 | /** 108 | * @export 109 | * @return {box2d.b2Jacobian} 110 | * @param {box2d.b2Vec2} x 111 | * @param {number} a1 112 | * @param {number} a2 113 | */ 114 | box2d.b2Jacobian.prototype.Set = function(x, a1, a2) { 115 | this.linear.Copy(x); 116 | this.angularA = a1; 117 | this.angularB = a2; 118 | return this; 119 | } 120 | 121 | /** 122 | * A joint edge is used to connect bodies and joints together in 123 | * a joint graph where each body is a node and each joint is an 124 | * edge. A joint edge belongs to a doubly linked list maintained 125 | * in each attached body. Each joint has two joint nodes, one 126 | * for each attached body. 127 | * @export 128 | * @constructor 129 | */ 130 | box2d.b2JointEdge = function() {}; 131 | 132 | /** 133 | * @export 134 | * @type {box2d.b2Body} 135 | */ 136 | box2d.b2JointEdge.prototype.other = null; ///< provides quick access to the other body attached. 137 | /** 138 | * @export 139 | * @type {box2d.b2Joint} 140 | */ 141 | box2d.b2JointEdge.prototype.joint = null; ///< the joint 142 | /** 143 | * @export 144 | * @type {box2d.b2JointEdge} 145 | */ 146 | box2d.b2JointEdge.prototype.prev = null; ///< the previous joint edge in the body's joint list 147 | /** 148 | * @export 149 | * @type {box2d.b2JointEdge} 150 | */ 151 | box2d.b2JointEdge.prototype.next = null; ///< the next joint edge in the body's joint list 152 | 153 | /** 154 | * Joint definitions are used to construct joints. 155 | * @export 156 | * @constructor 157 | * @param {box2d.b2JointType} type 158 | */ 159 | box2d.b2JointDef = function(type) { 160 | this.type = type; 161 | } 162 | 163 | /** 164 | * The joint type is set automatically for concrete joint types. 165 | * @export 166 | * @type {box2d.b2JointType} 167 | */ 168 | box2d.b2JointDef.prototype.type = box2d.b2JointType.e_unknownJoint; 169 | 170 | /** 171 | * Use this to attach application specific data to your joints. 172 | * @export 173 | * @type {*} 174 | */ 175 | box2d.b2JointDef.prototype.userData = null; 176 | 177 | /** 178 | * The first attached body. 179 | * @export 180 | * @type {box2d.b2Body} 181 | */ 182 | box2d.b2JointDef.prototype.bodyA = null; 183 | 184 | /** 185 | * The second attached body. 186 | * @export 187 | * @type {box2d.b2Body} 188 | */ 189 | box2d.b2JointDef.prototype.bodyB = null; 190 | 191 | /** 192 | * Set this flag to true if the attached bodies should collide. 193 | * @export 194 | * @type {boolean} 195 | */ 196 | box2d.b2JointDef.prototype.collideConnected = false; 197 | 198 | /** 199 | * The base joint class. Joints are used to constraint two 200 | * bodies together in various fashions. Some joints also feature 201 | * limits and motors. 202 | * @export 203 | * @constructor 204 | */ 205 | box2d.b2Joint = function(def) { 206 | if (box2d.ENABLE_ASSERTS) { 207 | box2d.b2Assert(def.bodyA !== def.bodyB); 208 | } 209 | 210 | this.m_type = def.type; 211 | this.m_edgeA = new box2d.b2JointEdge(); 212 | this.m_edgeB = new box2d.b2JointEdge(); 213 | this.m_bodyA = def.bodyA; 214 | this.m_bodyB = def.bodyB; 215 | 216 | this.m_collideConnected = def.collideConnected; 217 | 218 | this.m_userData = def.userData; 219 | } 220 | 221 | /** 222 | * @export 223 | * @type {box2d.b2JointType} 224 | */ 225 | box2d.b2Joint.prototype.m_type = box2d.b2JointType.e_unknownJoint; 226 | /** 227 | * @export 228 | * @type {box2d.b2Joint} 229 | */ 230 | box2d.b2Joint.prototype.m_prev = null; 231 | /** 232 | * @export 233 | * @type {box2d.b2Joint} 234 | */ 235 | box2d.b2Joint.prototype.m_next = null; 236 | /** 237 | * @export 238 | * @type {box2d.b2JointEdge} 239 | */ 240 | box2d.b2Joint.prototype.m_edgeA = null; 241 | /** 242 | * @export 243 | * @type {box2d.b2JointEdge} 244 | */ 245 | box2d.b2Joint.prototype.m_edgeB = null; 246 | /** 247 | * @export 248 | * @type {box2d.b2Body} 249 | */ 250 | box2d.b2Joint.prototype.m_bodyA = null; 251 | /** 252 | * @export 253 | * @type {box2d.b2Body} 254 | */ 255 | box2d.b2Joint.prototype.m_bodyB = null; 256 | 257 | /** 258 | * @export 259 | * @type {number} 260 | */ 261 | box2d.b2Joint.prototype.m_index = 0; 262 | 263 | /** 264 | * @export 265 | * @type {boolean} 266 | */ 267 | box2d.b2Joint.prototype.m_islandFlag = false; 268 | /** 269 | * @export 270 | * @type {boolean} 271 | */ 272 | box2d.b2Joint.prototype.m_collideConnected = false; 273 | 274 | /** 275 | * @export 276 | * @type {*} 277 | */ 278 | box2d.b2Joint.prototype.m_userData = null; 279 | 280 | /** 281 | * Get the anchor point on bodyA in world coordinates. 282 | * @export 283 | * @return {box2d.b2Vec2} 284 | * @param {box2d.b2Vec2} out 285 | */ 286 | box2d.b2Joint.prototype.GetAnchorA = function(out) { 287 | return out.SetZero(); 288 | } 289 | 290 | /** 291 | * Get the anchor point on bodyB in world coordinates. 292 | * @export 293 | * @return {box2d.b2Vec2} 294 | * @param {box2d.b2Vec2} out 295 | */ 296 | box2d.b2Joint.prototype.GetAnchorB = function(out) { 297 | return out.SetZero(); 298 | } 299 | 300 | /** 301 | * Get the reaction force on bodyB at the joint anchor in 302 | * Newtons. 303 | * @export 304 | * @return {box2d.b2Vec2} 305 | * @param {number} inv_dt 306 | * @param {box2d.b2Vec2} out 307 | */ 308 | box2d.b2Joint.prototype.GetReactionForce = function(inv_dt, out) { 309 | return out.SetZero(); 310 | } 311 | 312 | /** 313 | * Get the reaction torque on bodyB in N*m. 314 | * @export 315 | * @return {number} 316 | * @param {number} inv_dt 317 | */ 318 | box2d.b2Joint.prototype.GetReactionTorque = function(inv_dt) { 319 | return 0; 320 | } 321 | 322 | /** 323 | * @export 324 | * @return {void} 325 | * @param {box2d.b2SolverData} data 326 | */ 327 | box2d.b2Joint.prototype.InitVelocityConstraints = function(data) {} 328 | 329 | /** 330 | * @export 331 | * @return {void} 332 | * @param {box2d.b2SolverData} data 333 | */ 334 | box2d.b2Joint.prototype.SolveVelocityConstraints = function(data) {} 335 | 336 | /** 337 | * This returns true if the position errors are within 338 | * tolerance. 339 | * @export 340 | * @return {boolean} 341 | * @param {box2d.b2SolverData} data 342 | */ 343 | box2d.b2Joint.prototype.SolvePositionConstraints = function(data) { 344 | return false; 345 | } 346 | 347 | /** 348 | * Get the type of the concrete joint. 349 | * @export 350 | * @return {box2d.b2JointType} 351 | */ 352 | box2d.b2Joint.prototype.GetType = function() { 353 | return this.m_type; 354 | } 355 | 356 | /** 357 | * Get the first body attached to this joint. 358 | * @export 359 | * @return {box2d.b2Body} 360 | */ 361 | box2d.b2Joint.prototype.GetBodyA = function() { 362 | return this.m_bodyA; 363 | } 364 | 365 | /** 366 | * Get the second body attached to this joint. 367 | * @export 368 | * @return {box2d.b2Body} 369 | */ 370 | box2d.b2Joint.prototype.GetBodyB = function() { 371 | return this.m_bodyB; 372 | } 373 | 374 | /** 375 | * Get the next joint the world joint list. 376 | * @export 377 | * @return {box2d.b2Joint} 378 | */ 379 | box2d.b2Joint.prototype.GetNext = function() { 380 | return this.m_next; 381 | } 382 | 383 | /** 384 | * Get the user data pointer. 385 | * @export 386 | * @return {*} 387 | */ 388 | box2d.b2Joint.prototype.GetUserData = function() { 389 | return this.m_userData; 390 | } 391 | 392 | /** 393 | * Set the user data pointer. 394 | * @export 395 | * @return {void} 396 | * @param {*} data 397 | */ 398 | box2d.b2Joint.prototype.SetUserData = function(data) { 399 | this.m_userData = data; 400 | } 401 | 402 | /** 403 | * Get collide connected. 404 | * Note: modifying the collide connect flag won't work correctly 405 | * because the flag is only checked when fixture AABBs begin to 406 | * overlap. 407 | * @export 408 | * @return {boolean} 409 | */ 410 | box2d.b2Joint.prototype.GetCollideConnected = function() { 411 | return this.m_collideConnected; 412 | } 413 | 414 | /** 415 | * Dump this joint to the log file. 416 | * @export 417 | * @return {void} 418 | */ 419 | box2d.b2Joint.prototype.Dump = function() { 420 | if (box2d.DEBUG) { 421 | box2d.b2Log("// Dump is not supported for this joint type.\n"); 422 | } 423 | } 424 | 425 | /** 426 | * Short-cut function to determine if either body is inactive. 427 | * @export 428 | * @return {boolean} 429 | */ 430 | box2d.b2Joint.prototype.IsActive = function() { 431 | return this.m_bodyA.IsActive() && this.m_bodyB.IsActive(); 432 | } 433 | 434 | /** 435 | * Shift the origin for any points stored in world coordinates. 436 | * @export 437 | * @return {void} 438 | * @param {box2d.b2Vec2} newOrigin 439 | */ 440 | box2d.b2Joint.prototype.ShiftOrigin = function(newOrigin) {} 441 | -------------------------------------------------------------------------------- /Box2D/Dynamics/Joints/b2JointFactory.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2JointFactory'); 20 | 21 | // // goog.require('box2d.b2Settings'); 22 | // // goog.require('box2d.b2Math'); 23 | // // goog.require('box2d.b2Joint'); 24 | 25 | 26 | box2d.b2JointFactory = {} 27 | /** 28 | * @export 29 | * @return {box2d.b2Joint} 30 | * @param {box2d.b2JointDef} def 31 | * @param allocator 32 | */ 33 | box2d.b2JointFactory.Create = function(def, allocator) { 34 | var joint = null; 35 | 36 | switch (def.type) { 37 | case box2d.b2JointType.e_distanceJoint: 38 | { 39 | joint = new box2d.b2DistanceJoint((def instanceof box2d.b2DistanceJointDef ? def : null)); 40 | } 41 | break; 42 | 43 | case box2d.b2JointType.e_mouseJoint: 44 | { 45 | joint = new box2d.b2MouseJoint((def instanceof box2d.b2MouseJointDef ? def : null)); 46 | } 47 | break; 48 | 49 | case box2d.b2JointType.e_prismaticJoint: 50 | { 51 | joint = new box2d.b2PrismaticJoint((def instanceof box2d.b2PrismaticJointDef ? def : null)); 52 | } 53 | break; 54 | 55 | case box2d.b2JointType.e_revoluteJoint: 56 | { 57 | joint = new box2d.b2RevoluteJoint((def instanceof box2d.b2RevoluteJointDef ? def : null)); 58 | } 59 | break; 60 | 61 | case box2d.b2JointType.e_pulleyJoint: 62 | { 63 | joint = new box2d.b2PulleyJoint((def instanceof box2d.b2PulleyJointDef ? def : null)); 64 | } 65 | break; 66 | 67 | case box2d.b2JointType.e_gearJoint: 68 | { 69 | joint = new box2d.b2GearJoint((def instanceof box2d.b2GearJointDef ? def : null)); 70 | } 71 | break; 72 | 73 | case box2d.b2JointType.e_wheelJoint: 74 | { 75 | joint = new box2d.b2WheelJoint((def instanceof box2d.b2WheelJointDef ? def : null)); 76 | } 77 | break; 78 | 79 | case box2d.b2JointType.e_weldJoint: 80 | { 81 | joint = new box2d.b2WeldJoint((def instanceof box2d.b2WeldJointDef ? def : null)); 82 | } 83 | break; 84 | 85 | case box2d.b2JointType.e_frictionJoint: 86 | { 87 | joint = new box2d.b2FrictionJoint((def instanceof box2d.b2FrictionJointDef ? def : null)); 88 | } 89 | break; 90 | 91 | case box2d.b2JointType.e_ropeJoint: 92 | { 93 | joint = new box2d.b2RopeJoint((def instanceof box2d.b2RopeJointDef ? def : null)); 94 | } 95 | break; 96 | 97 | case box2d.b2JointType.e_motorJoint: 98 | { 99 | joint = new box2d.b2MotorJoint((def instanceof box2d.b2MotorJointDef ? def : null)); 100 | } 101 | break; 102 | 103 | case box2d.b2JointType.e_areaJoint: 104 | { 105 | joint = new box2d.b2AreaJoint((def instanceof box2d.b2AreaJointDef ? def : null)); 106 | } 107 | break; 108 | 109 | default: 110 | if (box2d.ENABLE_ASSERTS) { 111 | box2d.b2Assert(false); 112 | } 113 | break; 114 | } 115 | 116 | return joint; 117 | } 118 | 119 | /** 120 | * @export 121 | * @return {void} 122 | * @param {box2d.b2Joint} joint 123 | * @param allocator 124 | */ 125 | box2d.b2JointFactory.Destroy = function(joint, allocator) {} 126 | -------------------------------------------------------------------------------- /Box2D/Dynamics/b2ContactManager.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2ContactManager'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | // goog.require('box2d.b2Math'); 23 | // goog.require('box2d.b2Collision'); 24 | // goog.require('box2d.b2BroadPhase'); 25 | // goog.require('box2d.b2ContactFactory'); 26 | 27 | /** 28 | * Delegate of box2d.b2World. 29 | * @constructor 30 | */ 31 | box2d.b2ContactManager = function() { 32 | this.m_broadPhase = new box2d.b2BroadPhase(); 33 | 34 | this.m_contactFactory = new box2d.b2ContactFactory(this.m_allocator); 35 | } 36 | 37 | /** 38 | * @export 39 | * @type {box2d.b2BroadPhase} 40 | */ 41 | box2d.b2ContactManager.prototype.m_broadPhase = null; 42 | /** 43 | * @export 44 | * @type {box2d.b2Contact} 45 | */ 46 | box2d.b2ContactManager.prototype.m_contactList = null; 47 | /** 48 | * @export 49 | * @type {number} 50 | */ 51 | box2d.b2ContactManager.prototype.m_contactCount = 0; 52 | /** 53 | * @export 54 | * @type {box2d.b2ContactFilter} 55 | */ 56 | box2d.b2ContactManager.prototype.m_contactFilter = box2d.b2ContactFilter.b2_defaultFilter; 57 | /** 58 | * @export 59 | * @type {box2d.b2ContactListener} 60 | */ 61 | box2d.b2ContactManager.prototype.m_contactListener = box2d.b2ContactListener.b2_defaultListener; 62 | /** 63 | * @export 64 | * @type {*} 65 | */ 66 | box2d.b2ContactManager.prototype.m_allocator = null; 67 | 68 | /** 69 | * @export 70 | * @type {box2d.b2ContactFactory} 71 | */ 72 | box2d.b2ContactManager.prototype.m_contactFactory = null; 73 | 74 | /** 75 | * @export 76 | * @return {void} 77 | * @param {box2d.b2Contact} c 78 | */ 79 | box2d.b2ContactManager.prototype.Destroy = function(c) { 80 | var fixtureA = c.GetFixtureA(); 81 | var fixtureB = c.GetFixtureB(); 82 | var bodyA = fixtureA.GetBody(); 83 | var bodyB = fixtureB.GetBody(); 84 | 85 | if (this.m_contactListener && c.IsTouching()) { 86 | this.m_contactListener.EndContact(c); 87 | } 88 | 89 | // Remove from the world. 90 | if (c.m_prev) { 91 | c.m_prev.m_next = c.m_next; 92 | } 93 | 94 | if (c.m_next) { 95 | c.m_next.m_prev = c.m_prev; 96 | } 97 | 98 | if (c === this.m_contactList) { 99 | this.m_contactList = c.m_next; 100 | } 101 | 102 | // Remove from body 1 103 | if (c.m_nodeA.prev) { 104 | c.m_nodeA.prev.next = c.m_nodeA.next; 105 | } 106 | 107 | if (c.m_nodeA.next) { 108 | c.m_nodeA.next.prev = c.m_nodeA.prev; 109 | } 110 | 111 | if (c.m_nodeA === bodyA.m_contactList) { 112 | bodyA.m_contactList = c.m_nodeA.next; 113 | } 114 | 115 | // Remove from body 2 116 | if (c.m_nodeB.prev) { 117 | c.m_nodeB.prev.next = c.m_nodeB.next; 118 | } 119 | 120 | if (c.m_nodeB.next) { 121 | c.m_nodeB.next.prev = c.m_nodeB.prev; 122 | } 123 | 124 | if (c.m_nodeB === bodyB.m_contactList) { 125 | bodyB.m_contactList = c.m_nodeB.next; 126 | } 127 | 128 | // Call the factory. 129 | this.m_contactFactory.Destroy(c); 130 | --this.m_contactCount; 131 | } 132 | 133 | /** 134 | * This is the top level collision call for the time step. Here 135 | * all the narrow phase collision is processed for the world 136 | * contact list. 137 | * @export 138 | * @return {void} 139 | */ 140 | box2d.b2ContactManager.prototype.Collide = function() { 141 | // Update awake contacts. 142 | var c = this.m_contactList; 143 | while (c) { 144 | var fixtureA = c.GetFixtureA(); 145 | var fixtureB = c.GetFixtureB(); 146 | var indexA = c.GetChildIndexA(); 147 | var indexB = c.GetChildIndexB(); 148 | var bodyA = fixtureA.GetBody(); 149 | var bodyB = fixtureB.GetBody(); 150 | 151 | // Is this contact flagged for filtering? 152 | if (c.m_flag_filterFlag) { 153 | // Check user filtering. 154 | if (this.m_contactFilter && !this.m_contactFilter.ShouldCollide(fixtureA, fixtureB)) { 155 | cNuke = c; 156 | c = cNuke.m_next; 157 | this.Destroy(cNuke); 158 | continue; 159 | } 160 | 161 | // Clear the filtering flag. 162 | c.m_flag_filterFlag = false; 163 | } 164 | 165 | var activeA = bodyA.IsAwake() && bodyA.m_type !== box2d.b2BodyType.b2_staticBody; 166 | var activeB = bodyB.IsAwake() && bodyB.m_type !== box2d.b2BodyType.b2_staticBody; 167 | 168 | // At least one body must be awake and it must be dynamic or kinematic. 169 | if (!activeA && !activeB) { 170 | c = c.m_next; 171 | continue; 172 | } 173 | 174 | var proxyA = fixtureA.m_proxies[indexA].proxy; 175 | var proxyB = fixtureB.m_proxies[indexB].proxy; 176 | var overlap = this.m_broadPhase.TestOverlap(proxyA, proxyB); 177 | 178 | // Here we destroy contacts that cease to overlap in the broad-phase. 179 | if (!overlap) { 180 | cNuke = c; 181 | c = cNuke.m_next; 182 | this.Destroy(cNuke); 183 | continue; 184 | } 185 | 186 | // The contact persists. 187 | c.Update(this.m_contactListener); 188 | c = c.m_next; 189 | } 190 | } 191 | 192 | /** 193 | * @export 194 | * @return {void} 195 | */ 196 | box2d.b2ContactManager.prototype.FindNewContacts = function() { 197 | this.m_broadPhase.UpdatePairs(this); 198 | } 199 | 200 | /** 201 | * Broad-phase callback. 202 | * @export 203 | * @return {void} 204 | * @param {box2d.b2FixtureProxy} proxyUserDataA 205 | * @param {box2d.b2FixtureProxy} proxyUserDataB 206 | */ 207 | box2d.b2ContactManager.prototype.AddPair = function(proxyUserDataA, proxyUserDataB) { 208 | if (box2d.ENABLE_ASSERTS) { 209 | box2d.b2Assert(proxyUserDataA instanceof box2d.b2FixtureProxy); 210 | } 211 | if (box2d.ENABLE_ASSERTS) { 212 | box2d.b2Assert(proxyUserDataB instanceof box2d.b2FixtureProxy); 213 | } 214 | var proxyA = proxyUserDataA; //(proxyUserDataA instanceof box2d.b2FixtureProxy ? proxyUserDataA : null); 215 | var proxyB = proxyUserDataB; //(proxyUserDataB instanceof box2d.b2FixtureProxy ? proxyUserDataB : null); 216 | 217 | var fixtureA = proxyA.fixture; 218 | var fixtureB = proxyB.fixture; 219 | 220 | var indexA = proxyA.childIndex; 221 | var indexB = proxyB.childIndex; 222 | 223 | var bodyA = fixtureA.GetBody(); 224 | var bodyB = fixtureB.GetBody(); 225 | 226 | // Are the fixtures on the same body? 227 | if (bodyA === bodyB) { 228 | return; 229 | } 230 | 231 | // TODO_ERIN use a hash table to remove a potential bottleneck when both 232 | // bodies have a lot of contacts. 233 | // Does a contact already exist? 234 | var edge = bodyB.GetContactList(); 235 | while (edge) { 236 | if (edge.other === bodyA) { 237 | var fA = edge.contact.GetFixtureA(); 238 | var fB = edge.contact.GetFixtureB(); 239 | var iA = edge.contact.GetChildIndexA(); 240 | var iB = edge.contact.GetChildIndexB(); 241 | 242 | if (fA === fixtureA && fB === fixtureB && iA === indexA && iB === indexB) { 243 | // A contact already exists. 244 | return; 245 | } 246 | 247 | if (fA === fixtureB && fB === fixtureA && iA === indexB && iB === indexA) { 248 | // A contact already exists. 249 | return; 250 | } 251 | } 252 | 253 | edge = edge.next; 254 | } 255 | 256 | // Check user filtering. 257 | if (this.m_contactFilter && !this.m_contactFilter.ShouldCollide(fixtureA, fixtureB)) { 258 | return; 259 | } 260 | 261 | // Call the factory. 262 | var c = this.m_contactFactory.Create(fixtureA, indexA, fixtureB, indexB); 263 | if (c === null) { 264 | return; 265 | } 266 | 267 | // Contact creation may swap fixtures. 268 | fixtureA = c.GetFixtureA(); 269 | fixtureB = c.GetFixtureB(); 270 | //indexA = c.GetChildIndexA(); 271 | //indexB = c.GetChildIndexB(); 272 | bodyA = fixtureA.m_body; 273 | bodyB = fixtureB.m_body; 274 | 275 | // Insert into the world. 276 | c.m_prev = null; 277 | c.m_next = this.m_contactList; 278 | if (this.m_contactList !== null) { 279 | this.m_contactList.m_prev = c; 280 | } 281 | this.m_contactList = c; 282 | 283 | // Connect to island graph. 284 | 285 | // Connect to body A 286 | c.m_nodeA.contact = c; 287 | c.m_nodeA.other = bodyB; 288 | 289 | c.m_nodeA.prev = null; 290 | c.m_nodeA.next = bodyA.m_contactList; 291 | if (bodyA.m_contactList !== null) { 292 | bodyA.m_contactList.prev = c.m_nodeA; 293 | } 294 | bodyA.m_contactList = c.m_nodeA; 295 | 296 | // Connect to body B 297 | c.m_nodeB.contact = c; 298 | c.m_nodeB.other = bodyA; 299 | 300 | c.m_nodeB.prev = null; 301 | c.m_nodeB.next = bodyB.m_contactList; 302 | if (bodyB.m_contactList !== null) { 303 | bodyB.m_contactList.prev = c.m_nodeB; 304 | } 305 | bodyB.m_contactList = c.m_nodeB; 306 | 307 | // Wake up the bodies 308 | if (!fixtureA.IsSensor() && !fixtureB.IsSensor()) { 309 | bodyA.SetAwake(true); 310 | bodyB.SetAwake(true); 311 | } 312 | 313 | ++this.m_contactCount; 314 | } 315 | -------------------------------------------------------------------------------- /Box2D/Dynamics/b2TimeStep.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.b2TimeStep'); 20 | 21 | // goog.require('box2d.b2Settings'); 22 | 23 | /** 24 | * Profiling data. Times are in milliseconds. 25 | * @export 26 | * @constructor 27 | */ 28 | box2d.b2Profile = function() {}; 29 | 30 | /** 31 | * @export 32 | * @type {number} 33 | */ 34 | box2d.b2Profile.prototype.step = 0; 35 | /** 36 | * @export 37 | * @type {number} 38 | */ 39 | box2d.b2Profile.prototype.collide = 0; 40 | /** 41 | * @export 42 | * @type {number} 43 | */ 44 | box2d.b2Profile.prototype.solve = 0; 45 | /** 46 | * @export 47 | * @type {number} 48 | */ 49 | box2d.b2Profile.prototype.solveInit = 0; 50 | /** 51 | * @export 52 | * @type {number} 53 | */ 54 | box2d.b2Profile.prototype.solveVelocity = 0; 55 | /** 56 | * @export 57 | * @type {number} 58 | */ 59 | box2d.b2Profile.prototype.solvePosition = 0; 60 | /** 61 | * @export 62 | * @type {number} 63 | */ 64 | box2d.b2Profile.prototype.broadphase = 0; 65 | /** 66 | * @export 67 | * @type {number} 68 | */ 69 | box2d.b2Profile.prototype.solveTOI = 0; 70 | 71 | /** 72 | * @export 73 | * @return {box2d.b2Profile} 74 | */ 75 | box2d.b2Profile.prototype.Reset = function() { 76 | this.step = 0; 77 | this.collide = 0; 78 | this.solve = 0; 79 | this.solveInit = 0; 80 | this.solveVelocity = 0; 81 | this.solvePosition = 0; 82 | this.broadphase = 0; 83 | this.solveTOI = 0; 84 | return this; 85 | } 86 | 87 | /** 88 | * This is an internal structure. 89 | * @export 90 | * @constructor 91 | */ 92 | box2d.b2TimeStep = function() {}; 93 | 94 | /** 95 | * @export 96 | * @type {number} 97 | */ 98 | box2d.b2TimeStep.prototype.dt = 0; // time step 99 | /** 100 | * @export 101 | * @type {number} 102 | */ 103 | box2d.b2TimeStep.prototype.inv_dt = 0; // inverse time step (0 if dt === 0). 104 | /** 105 | * @export 106 | * @type {number} 107 | */ 108 | box2d.b2TimeStep.prototype.dtRatio = 0; // dt * inv_dt0 109 | /** 110 | * @export 111 | * @type {number} 112 | */ 113 | box2d.b2TimeStep.prototype.velocityIterations = 0; 114 | /** 115 | * @export 116 | * @type {number} 117 | */ 118 | box2d.b2TimeStep.prototype.positionIterations = 0; 119 | //#if B2_ENABLE_PARTICLE 120 | /** 121 | * @export 122 | * @type {number} 123 | */ 124 | box2d.b2TimeStep.prototype.particleIterations = 0; 125 | //#endif 126 | /** 127 | * @export 128 | * @type {boolean} 129 | */ 130 | box2d.b2TimeStep.prototype.warmStarting = false; 131 | 132 | /** 133 | * @export 134 | * @return {box2d.b2TimeStep} 135 | * @param {box2d.b2TimeStep} step 136 | */ 137 | box2d.b2TimeStep.prototype.Copy = function(step) { 138 | this.dt = step.dt; // time step 139 | this.inv_dt = step.inv_dt; // inverse time step (0 if dt === 0). 140 | this.dtRatio = step.dtRatio; // dt * inv_dt0 141 | this.positionIterations = step.positionIterations; 142 | this.velocityIterations = step.velocityIterations; 143 | //#if B2_ENABLE_PARTICLE 144 | this.particleIterations = step.particleIterations; 145 | //#endif 146 | this.warmStarting = step.warmStarting; 147 | return this; 148 | } 149 | 150 | /** 151 | * This is an internal structure. 152 | * @export 153 | * @constructor 154 | */ 155 | box2d.b2Position = function() { 156 | this.c = new box2d.b2Vec2(); 157 | }; 158 | 159 | /** 160 | * @export 161 | * @type {box2d.b2Vec2} 162 | */ 163 | box2d.b2Position.prototype.c = null; 164 | /** 165 | * @export 166 | * @type {number} 167 | */ 168 | box2d.b2Position.prototype.a = 0; 169 | 170 | /** 171 | * @export 172 | * @return {Array.} 173 | * @param {number} length 174 | */ 175 | box2d.b2Position.MakeArray = function(length) { 176 | return box2d.b2MakeArray(length, function(i) { 177 | return new box2d.b2Position(); 178 | }); 179 | } 180 | 181 | /** 182 | * This is an internal structure. 183 | * @export 184 | * @constructor 185 | */ 186 | box2d.b2Velocity = function() { 187 | this.v = new box2d.b2Vec2(); 188 | }; 189 | 190 | /** 191 | * @export 192 | * @type {box2d.b2Vec2} 193 | */ 194 | box2d.b2Velocity.prototype.v = null; 195 | /** 196 | * @export 197 | * @type {number} 198 | */ 199 | box2d.b2Velocity.prototype.w = 0; 200 | 201 | /** 202 | * @export 203 | * @return {Array.} 204 | * @param {number} length 205 | */ 206 | box2d.b2Velocity.MakeArray = function(length) { 207 | return box2d.b2MakeArray(length, function(i) { 208 | return new box2d.b2Velocity(); 209 | }); 210 | } 211 | 212 | /** 213 | * Solver Data 214 | * @export 215 | * @constructor 216 | */ 217 | box2d.b2SolverData = function() { 218 | this.step = new box2d.b2TimeStep(); 219 | }; 220 | 221 | /** 222 | * @export 223 | * @type {box2d.b2TimeStep} 224 | */ 225 | box2d.b2SolverData.prototype.step = null; 226 | /** 227 | * @export 228 | * @type {Array.} 229 | */ 230 | box2d.b2SolverData.prototype.positions = null; 231 | /** 232 | * @export 233 | * @type {Array.} 234 | */ 235 | box2d.b2SolverData.prototype.velocities = null; 236 | -------------------------------------------------------------------------------- /Box2D/Particle/b2StackQueue.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Google, Inc. 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_PARTICLE 20 | 21 | // goog.provide('box2d.b2StackQueue'); 22 | 23 | /** 24 | * @constructor 25 | * @param {number} capacity 26 | */ 27 | box2d.b2StackQueue = function(capacity) { 28 | this.m_buffer = box2d.b2MakeArray(capacity); 29 | this.m_end = capacity; 30 | } 31 | 32 | /** 33 | * @type {Array.<*>} 34 | */ 35 | box2d.b2StackQueue.prototype.m_buffer = null; 36 | 37 | /** 38 | * @type {number} 39 | */ 40 | box2d.b2StackQueue.prototype.m_front = 0; 41 | 42 | /** 43 | * @type {number} 44 | */ 45 | box2d.b2StackQueue.prototype.m_back = 0; 46 | 47 | /** 48 | * @type {number} 49 | */ 50 | box2d.b2StackQueue.prototype.m_capacity = 0; 51 | 52 | /** 53 | * @return {void} 54 | * @param {*} item 55 | */ 56 | box2d.b2StackQueue.prototype.Push = function(item) { 57 | if (this.m_back >= this.m_capacity) { 58 | for (var i = this.m_front; i < this.m_back; i++) { 59 | this.m_buffer[i - this.m_front] = this.m_buffer[i]; 60 | } 61 | this.m_back -= this.m_front; 62 | this.m_front = 0; 63 | if (this.m_back >= this.m_capacity) { 64 | if (this.m_capacity > 0) { 65 | this.m_buffer.concat(box2d.b2MakeArray(this.m_capacity)); 66 | this.m_capacity *= 2; 67 | } else { 68 | this.m_buffer.concat(box2d.b2MakeArray(1)); 69 | this.m_capacity = 1; 70 | } 71 | ///m_buffer = (T*) m_allocator->Reallocate(m_buffer, sizeof(T) * m_capacity); 72 | } 73 | } 74 | this.m_buffer[this.m_back] = item; 75 | this.m_back++; 76 | } 77 | 78 | /** 79 | * @return {void} 80 | */ 81 | box2d.b2StackQueue.prototype.Pop = function() { 82 | box2d.b2Assert(this.m_front < this.m_back); 83 | this.m_buffer[this.m_front] = null; 84 | this.m_front++; 85 | } 86 | 87 | /** 88 | * @return {boolean} 89 | */ 90 | box2d.b2StackQueue.prototype.Empty = function() { 91 | box2d.b2Assert(this.m_front <= this.m_back); 92 | return this.m_front === this.m_back; 93 | } 94 | 95 | /** 96 | * @return {*} 97 | */ 98 | box2d.b2StackQueue.prototype.Front = function() { 99 | return this.m_buffer[this.m_front]; 100 | } 101 | 102 | //#endif 103 | -------------------------------------------------------------------------------- /Box2D/Particle/b2VoronoiDiagram.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Google, Inc. 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_PARTICLE 20 | 21 | // goog.provide('box2d.b2VoronoiDiagram'); 22 | 23 | // goog.require('box2d.b2StackQueue'); 24 | // goog.require('box2d.b2Collision'); 25 | 26 | /** 27 | * A field representing the nearest generator from each point. 28 | * 29 | * @export 30 | * @constructor 31 | */ 32 | box2d.b2VoronoiDiagram = function(generatorCapacity) { 33 | this.m_generatorBuffer = box2d.b2MakeArray(generatorCapacity, function(index) { 34 | return new box2d.b2VoronoiDiagram.Generator(); 35 | }) 36 | this.m_generatorCapacity = generatorCapacity; 37 | } 38 | 39 | /** 40 | * @export 41 | * @type {Array.} 42 | */ 43 | box2d.b2VoronoiDiagram.prototype.m_generatorBuffer = null; 44 | 45 | /** 46 | * @type {number} 47 | */ 48 | box2d.b2VoronoiDiagram.prototype.m_generatorCapacity = 0; 49 | 50 | /** 51 | * @type {number} 52 | */ 53 | box2d.b2VoronoiDiagram.prototype.m_generatorCount = 0; 54 | 55 | /** 56 | * @type {number} 57 | */ 58 | box2d.b2VoronoiDiagram.prototype.m_countX = 0; 59 | 60 | /** 61 | * @type {number} 62 | */ 63 | box2d.b2VoronoiDiagram.prototype.m_countY = 0; 64 | 65 | /** 66 | * @type {Array.} 67 | */ 68 | box2d.b2VoronoiDiagram.prototype.m_diagram = null; 69 | 70 | /** 71 | * Callback used by GetNodes(). 72 | * 73 | * Receive tags for generators associated with a node. 74 | * 75 | * @typedef {function(number,number,number):void} 76 | */ 77 | box2d.b2VoronoiDiagram.NodeCallback; 78 | 79 | /** 80 | * @constructor 81 | */ 82 | box2d.b2VoronoiDiagram.Generator = function() { 83 | this.center = new box2d.b2Vec2(); 84 | }; 85 | 86 | /** 87 | * @type {box2d.b2Vec2} 88 | */ 89 | box2d.b2VoronoiDiagram.Generator.prototype.center = null; 90 | 91 | /** 92 | * @type {number} 93 | */ 94 | box2d.b2VoronoiDiagram.Generator.prototype.tag = 0; 95 | 96 | /** 97 | * @constructor 98 | * @param {number} x 99 | * @param {number} y 100 | * @param {number} i 101 | * @param {box2d.b2VoronoiDiagram.Generator} g 102 | */ 103 | box2d.b2VoronoiDiagram.b2VoronoiDiagramTask = function(x, y, i, g) { 104 | this.m_x = x; 105 | this.m_y = y; 106 | this.m_i = i; 107 | this.m_generator = g; 108 | }; 109 | 110 | /** 111 | * @type {number} 112 | */ 113 | box2d.b2VoronoiDiagram.b2VoronoiDiagramTask.prototype.m_x = 0; 114 | 115 | /** 116 | * @type {number} 117 | */ 118 | box2d.b2VoronoiDiagram.b2VoronoiDiagramTask.prototype.m_y = 0; 119 | 120 | /** 121 | * @type {number} 122 | */ 123 | box2d.b2VoronoiDiagram.b2VoronoiDiagramTask.prototype.m_i = 0; 124 | 125 | /** 126 | * @type {box2d.b2VoronoiDiagram.Generator} 127 | */ 128 | box2d.b2VoronoiDiagram.b2VoronoiDiagramTask.prototype.m_generator = null; 129 | 130 | /** 131 | * Add a generator. 132 | * 133 | * @export 134 | * @return {void} 135 | * @param {box2d.b2Vec2} center the position of the generator. 136 | * @param {number} tag a tag used to identify the generator in 137 | * callback functions. 138 | * @param {boolean} necessary whether to callback for nodes 139 | * associated with the generator. 140 | */ 141 | box2d.b2VoronoiDiagram.prototype.AddGenerator = function(center, tag, necessary) { 142 | box2d.b2Assert(this.m_generatorCount < this.m_generatorCapacity); 143 | var g = this.m_generatorBuffer[this.m_generatorCount++]; 144 | g.center.Copy(center); 145 | g.tag = tag; 146 | g.necessary = necessary; 147 | } 148 | 149 | /** 150 | * Generate the Voronoi diagram. It is rasterized with a given 151 | * interval in the same range as the necessary generators exist. 152 | * 153 | * @export 154 | * @return {void} 155 | * @param {number} radius the interval of the diagram. 156 | * @param {number} margin margin for which the range of the 157 | * diagram is extended. 158 | */ 159 | box2d.b2VoronoiDiagram.prototype.Generate = function(radius, margin) { 160 | box2d.b2Assert(this.m_diagram === null); 161 | var inverseRadius = 1 / radius; 162 | var lower = new box2d.b2Vec2(+box2d.b2_maxFloat, +box2d.b2_maxFloat); 163 | var upper = new box2d.b2Vec2(-box2d.b2_maxFloat, -box2d.b2_maxFloat); 164 | var necessary_count = 0; 165 | for (var k = 0; k < this.m_generatorCount; k++) { 166 | var g = this.m_generatorBuffer[k]; 167 | if (g.necessary) { 168 | box2d.b2Min_V2_V2(lower, g.center, lower); 169 | box2d.b2Max_V2_V2(upper, g.center, upper); 170 | ++necessary_count; 171 | } 172 | } 173 | if (necessary_count === 0) { 174 | //debugger; 175 | this.m_countX = 0; 176 | this.m_countY = 0; 177 | return; 178 | } 179 | lower.x -= margin; 180 | lower.y -= margin; 181 | upper.x += margin; 182 | upper.y += margin; 183 | this.m_countX = 1 + Math.floor(inverseRadius * (upper.x - lower.x)); 184 | this.m_countY = 1 + Math.floor(inverseRadius * (upper.y - lower.y)); 185 | /// m_diagram = (Generator**) m_allocator->Allocate(sizeof(Generator*) * m_countX * m_countY); 186 | /// for (int32 i = 0; i < m_countX * m_countY; i++) 187 | /// { 188 | /// m_diagram[i] = NULL; 189 | /// } 190 | this.m_diagram = /** @type {Array.} */ (box2d.b2MakeArray(this.m_countX * this.m_countY)); 191 | 192 | // (4 * m_countX * m_countY) is the queue capacity that is experimentally 193 | // known to be necessary and sufficient for general particle distributions. 194 | var queue = new box2d.b2StackQueue(4 * this.m_countX * this.m_countY); 195 | for (var k = 0; k < this.m_generatorCount; k++) { 196 | var g = this.m_generatorBuffer[k]; 197 | /// g.center = inverseRadius * (g.center - lower); 198 | g.center.SelfSub(lower).SelfMul(inverseRadius); 199 | var x = Math.floor(g.center.x); 200 | var y = Math.floor(g.center.y); 201 | if (x >= 0 && y >= 0 && x < this.m_countX && y < this.m_countY) { 202 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y, x + y * this.m_countX, g)); 203 | } 204 | } 205 | while (!queue.Empty()) { 206 | var task = queue.Front(); 207 | var x = task.m_x; 208 | var y = task.m_y; 209 | var i = task.m_i; 210 | var g = task.m_generator; 211 | queue.Pop(); 212 | if (!this.m_diagram[i]) { 213 | this.m_diagram[i] = g; 214 | if (x > 0) { 215 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x - 1, y, i - 1, g)); 216 | } 217 | if (y > 0) { 218 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y - 1, i - this.m_countX, g)); 219 | } 220 | if (x < this.m_countX - 1) { 221 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x + 1, y, i + 1, g)); 222 | } 223 | if (y < this.m_countY - 1) { 224 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y + 1, i + this.m_countX, g)); 225 | } 226 | } 227 | } 228 | for (var y = 0; y < this.m_countY; y++) { 229 | for (var x = 0; x < this.m_countX - 1; x++) { 230 | var i = x + y * this.m_countX; 231 | var a = this.m_diagram[i]; 232 | var b = this.m_diagram[i + 1]; 233 | if (a !== b) { 234 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y, i, b)); 235 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x + 1, y, i + 1, a)); 236 | } 237 | } 238 | } 239 | for (var y = 0; y < this.m_countY - 1; y++) { 240 | for (var x = 0; x < this.m_countX; x++) { 241 | var i = x + y * this.m_countX; 242 | var a = this.m_diagram[i]; 243 | var b = this.m_diagram[i + this.m_countX]; 244 | if (a !== b) { 245 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y, i, b)); 246 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y + 1, i + this.m_countX, a)); 247 | } 248 | } 249 | } 250 | while (!queue.Empty()) { 251 | var task = queue.Front(); 252 | var x = task.m_x; 253 | var y = task.m_y; 254 | var i = task.m_i; 255 | var k = task.m_generator; 256 | queue.Pop(); 257 | var a = this.m_diagram[i]; 258 | var b = k; 259 | if (a !== b) { 260 | var ax = a.center.x - x; 261 | var ay = a.center.y - y; 262 | var bx = b.center.x - x; 263 | var by = b.center.y - y; 264 | var a2 = ax * ax + ay * ay; 265 | var b2 = bx * bx + by * by; 266 | if (a2 > b2) { 267 | this.m_diagram[i] = b; 268 | if (x > 0) { 269 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x - 1, y, i - 1, b)); 270 | } 271 | if (y > 0) { 272 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y - 1, i - this.m_countX, b)); 273 | } 274 | if (x < this.m_countX - 1) { 275 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x + 1, y, i + 1, b)); 276 | } 277 | if (y < this.m_countY - 1) { 278 | queue.Push(new box2d.b2VoronoiDiagram.b2VoronoiDiagramTask(x, y + 1, i + this.m_countX, b)); 279 | } 280 | } 281 | } 282 | } 283 | } 284 | 285 | /** 286 | * Enumerate all nodes that contain at least one necessary 287 | * generator. 288 | * 289 | * @export 290 | * @return {void} 291 | * @param {function(number,number,number):void} callback 292 | */ 293 | box2d.b2VoronoiDiagram.prototype.GetNodes = function(callback) { 294 | for (var y = 0; y < this.m_countY - 1; y++) { 295 | for (var x = 0; x < this.m_countX - 1; x++) { 296 | var i = x + y * this.m_countX; 297 | var a = this.m_diagram[i]; 298 | var b = this.m_diagram[i + 1]; 299 | var c = this.m_diagram[i + this.m_countX]; 300 | var d = this.m_diagram[i + 1 + this.m_countX]; 301 | if (b !== c) { 302 | if (a !== b && a !== c && 303 | (a.necessary || b.necessary || c.necessary)) { 304 | callback(a.tag, b.tag, c.tag); 305 | } 306 | if (d !== b && d !== c && 307 | (a.necessary || b.necessary || c.necessary)) { 308 | callback(b.tag, d.tag, c.tag); 309 | } 310 | } 311 | } 312 | } 313 | } 314 | 315 | //#endif 316 | -------------------------------------------------------------------------------- /Box2D/Rope/b2Rope.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_ROPE 20 | 21 | // goog.provide('box2d.b2Rope'); 22 | 23 | // goog.require('box2d.b2Math'); 24 | // goog.require('box2d.b2Draw'); 25 | 26 | /** 27 | * @export 28 | * @constructor 29 | */ 30 | box2d.b2RopeDef = function() { 31 | this.vertices = new Array(); 32 | this.masses = new Array(); 33 | this.gravity = new box2d.b2Vec2(); 34 | }; 35 | 36 | /*box2d.b2Vec2[]*/ 37 | box2d.b2RopeDef.prototype.vertices = null; 38 | 39 | /*int32*/ 40 | box2d.b2RopeDef.prototype.count = 0; 41 | 42 | /*float32[]*/ 43 | box2d.b2RopeDef.prototype.masses = null; 44 | 45 | /*box2d.b2Vec2*/ 46 | box2d.b2RopeDef.prototype.gravity = null; 47 | 48 | /*float32*/ 49 | box2d.b2RopeDef.prototype.damping = 0.1; 50 | 51 | /** 52 | * Stretching stiffness 53 | */ 54 | /*float32*/ 55 | box2d.b2RopeDef.prototype.k2 = 0.9; 56 | 57 | /** 58 | * Bending stiffness. Values above 0.5 can make the simulation 59 | * blow up. 60 | */ 61 | /*float32*/ 62 | box2d.b2RopeDef.prototype.k3 = 0.1; 63 | 64 | /** 65 | * @export 66 | * @constructor 67 | */ 68 | box2d.b2Rope = function() { 69 | this.m_gravity = new box2d.b2Vec2(); 70 | }; 71 | 72 | /*int32*/ 73 | box2d.b2Rope.prototype.m_count = 0; 74 | /*box2d.b2Vec2[]*/ 75 | box2d.b2Rope.prototype.m_ps = null; 76 | /*box2d.b2Vec2[]*/ 77 | box2d.b2Rope.prototype.m_p0s = null; 78 | /*box2d.b2Vec2[]*/ 79 | box2d.b2Rope.prototype.m_vs = null; 80 | 81 | /*float32[]*/ 82 | box2d.b2Rope.prototype.m_ims = null; 83 | 84 | /*float32[]*/ 85 | box2d.b2Rope.prototype.m_Ls = null; 86 | /*float32[]*/ 87 | box2d.b2Rope.prototype.m_as = null; 88 | 89 | /*box2d.b2Vec2*/ 90 | box2d.b2Rope.prototype.m_gravity = null; 91 | /*float32*/ 92 | box2d.b2Rope.prototype.m_damping = 0; 93 | 94 | /*float32*/ 95 | box2d.b2Rope.prototype.m_k2 = 1; 96 | /*float32*/ 97 | box2d.b2Rope.prototype.m_k3 = 0.1; 98 | 99 | /** 100 | * @export 101 | * @return {number} 102 | */ 103 | box2d.b2Rope.prototype.GetVertexCount = function() { 104 | return this.m_count; 105 | } 106 | 107 | /** 108 | * @export 109 | * @return {Array.} 110 | */ 111 | box2d.b2Rope.prototype.GetVertices = function() { 112 | return this.m_ps; 113 | } 114 | 115 | /** 116 | * @export 117 | * @return {void} 118 | * @param {box2d.b2RopeDef} def 119 | */ 120 | box2d.b2Rope.prototype.Initialize = function(def) { 121 | if (box2d.ENABLE_ASSERTS) { 122 | box2d.b2Assert(def.count >= 3); 123 | } 124 | this.m_count = def.count; 125 | // this.m_ps = (box2d.b2Vec2*)b2Alloc(this.m_count * sizeof(box2d.b2Vec2)); 126 | this.m_ps = box2d.b2Vec2.MakeArray(this.m_count); 127 | // this.m_p0s = (box2d.b2Vec2*)b2Alloc(this.m_count * sizeof(box2d.b2Vec2)); 128 | this.m_p0s = box2d.b2Vec2.MakeArray(this.m_count); 129 | // this.m_vs = (box2d.b2Vec2*)b2Alloc(this.m_count * sizeof(box2d.b2Vec2)); 130 | this.m_vs = box2d.b2Vec2.MakeArray(this.m_count); 131 | // this.m_ims = (float32*)b2Alloc(this.m_count * sizeof(float32)); 132 | this.m_ims = box2d.b2MakeNumberArray(this.m_count); 133 | 134 | for ( /*int32*/ var i = 0; i < this.m_count; ++i) { 135 | this.m_ps[i].Copy(def.vertices[i]); 136 | this.m_p0s[i].Copy(def.vertices[i]); 137 | this.m_vs[i].SetZero(); 138 | 139 | /*float32*/ 140 | var m = def.masses[i]; 141 | if (m > 0) { 142 | this.m_ims[i] = 1 / m; 143 | } else { 144 | this.m_ims[i] = 0; 145 | } 146 | } 147 | 148 | /*int32*/ 149 | var count2 = this.m_count - 1; 150 | /*int32*/ 151 | var count3 = this.m_count - 2; 152 | // this.m_Ls = (float32*)be2Alloc(count2 * sizeof(float32)); 153 | this.m_Ls = box2d.b2MakeNumberArray(count2); 154 | // this.m_as = (float32*)b2Alloc(count3 * sizeof(float32)); 155 | this.m_as = box2d.b2MakeNumberArray(count3); 156 | 157 | for ( /*int32*/ var i = 0; i < count2; ++i) { 158 | /*box2d.b2Vec2&*/ 159 | var p1 = this.m_ps[i]; 160 | /*box2d.b2Vec2&*/ 161 | var p2 = this.m_ps[i + 1]; 162 | this.m_Ls[i] = box2d.b2Distance(p1, p2); 163 | } 164 | 165 | for ( /*int32*/ var i = 0; i < count3; ++i) { 166 | /*box2d.b2Vec2&*/ 167 | var p1 = this.m_ps[i]; 168 | /*box2d.b2Vec2&*/ 169 | var p2 = this.m_ps[i + 1]; 170 | /*box2d.b2Vec2&*/ 171 | var p3 = this.m_ps[i + 2]; 172 | 173 | /*box2d.b2Vec2*/ 174 | var d1 = box2d.b2Sub_V2_V2(p2, p1, box2d.b2Vec2.s_t0); 175 | /*box2d.b2Vec2*/ 176 | var d2 = box2d.b2Sub_V2_V2(p3, p2, box2d.b2Vec2.s_t1); 177 | 178 | /*float32*/ 179 | var a = box2d.b2Cross_V2_V2(d1, d2); 180 | /*float32*/ 181 | var b = box2d.b2Dot_V2_V2(d1, d2); 182 | 183 | this.m_as[i] = box2d.b2Atan2(a, b); 184 | } 185 | 186 | this.m_gravity.Copy(def.gravity); 187 | this.m_damping = def.damping; 188 | this.m_k2 = def.k2; 189 | this.m_k3 = def.k3; 190 | } 191 | 192 | /** 193 | * @export 194 | * @return {void} 195 | * @param {number} h 196 | * @param {number} iterations 197 | */ 198 | box2d.b2Rope.prototype.Step = function( /*float32*/ h, /*int32*/ iterations) { 199 | if (h === 0) { 200 | return; 201 | } 202 | 203 | /*float32*/ 204 | var d = Math.exp(-h * this.m_damping); 205 | 206 | for ( /*int32*/ var i = 0; i < this.m_count; ++i) { 207 | this.m_p0s[i].Copy(this.m_ps[i]); 208 | if (this.m_ims[i] > 0) { 209 | this.m_vs[i].SelfMulAdd(h, this.m_gravity); 210 | } 211 | this.m_vs[i].SelfMul(d); 212 | this.m_ps[i].SelfMulAdd(h, this.m_vs[i]); 213 | 214 | } 215 | 216 | for ( /*int32*/ var i = 0; i < iterations; ++i) { 217 | this.SolveC2(); 218 | this.SolveC3(); 219 | this.SolveC2(); 220 | } 221 | 222 | /*float32*/ 223 | var inv_h = 1 / h; 224 | for ( /*int32*/ var i = 0; i < this.m_count; ++i) { 225 | box2d.b2Mul_S_V2(inv_h, box2d.b2Sub_V2_V2(this.m_ps[i], this.m_p0s[i], box2d.b2Vec2.s_t0), this.m_vs[i]); 226 | } 227 | } 228 | 229 | /** 230 | * @export 231 | * @return {void} 232 | */ 233 | box2d.b2Rope.prototype.SolveC2 = function() { 234 | /*int32*/ 235 | var count2 = this.m_count - 1; 236 | 237 | for ( /*int32*/ var i = 0; i < count2; ++i) { 238 | /*box2d.b2Vec2&*/ 239 | var p1 = this.m_ps[i]; 240 | /*box2d.b2Vec2&*/ 241 | var p2 = this.m_ps[i + 1]; 242 | 243 | /*box2d.b2Vec2*/ 244 | var d = box2d.b2Sub_V2_V2(p2, p1, box2d.b2Rope.s_d); 245 | /*float32*/ 246 | var L = d.Normalize(); 247 | 248 | /*float32*/ 249 | var im1 = this.m_ims[i]; 250 | /*float32*/ 251 | var im2 = this.m_ims[i + 1]; 252 | 253 | if (im1 + im2 === 0) { 254 | continue; 255 | } 256 | 257 | /*float32*/ 258 | var s1 = im1 / (im1 + im2); 259 | /*float32*/ 260 | var s2 = im2 / (im1 + im2); 261 | 262 | p1.SelfMulSub(this.m_k2 * s1 * (this.m_Ls[i] - L), d); 263 | p2.SelfMulAdd(this.m_k2 * s2 * (this.m_Ls[i] - L), d); 264 | 265 | // this.m_ps[i] = p1; 266 | // this.m_ps[i + 1] = p2; 267 | } 268 | } 269 | box2d.b2Rope.s_d = new box2d.b2Vec2(); 270 | 271 | /** 272 | * @export 273 | * @return {void} 274 | * @param {number} angle 275 | */ 276 | box2d.b2Rope.prototype.SetAngle = function(angle) { 277 | /*int32*/ 278 | var count3 = this.m_count - 2; 279 | for ( /*int32*/ var i = 0; i < count3; ++i) { 280 | this.m_as[i] = angle; 281 | } 282 | } 283 | 284 | /** 285 | * @export 286 | * @return {void} 287 | */ 288 | box2d.b2Rope.prototype.SolveC3 = function() { 289 | /*int32*/ 290 | var count3 = this.m_count - 2; 291 | 292 | for ( /*int32*/ var i = 0; i < count3; ++i) { 293 | /*box2d.b2Vec2&*/ 294 | var p1 = this.m_ps[i]; 295 | /*box2d.b2Vec2&*/ 296 | var p2 = this.m_ps[i + 1]; 297 | /*box2d.b2Vec2&*/ 298 | var p3 = this.m_ps[i + 2]; 299 | 300 | /*float32*/ 301 | var m1 = this.m_ims[i]; 302 | /*float32*/ 303 | var m2 = this.m_ims[i + 1]; 304 | /*float32*/ 305 | var m3 = this.m_ims[i + 2]; 306 | 307 | /*box2d.b2Vec2*/ 308 | var d1 = box2d.b2Sub_V2_V2(p2, p1, box2d.b2Rope.s_d1); 309 | /*box2d.b2Vec2*/ 310 | var d2 = box2d.b2Sub_V2_V2(p3, p2, box2d.b2Rope.s_d2); 311 | 312 | /*float32*/ 313 | var L1sqr = d1.LengthSquared(); 314 | /*float32*/ 315 | var L2sqr = d2.LengthSquared(); 316 | 317 | if (L1sqr * L2sqr === 0) { 318 | continue; 319 | } 320 | 321 | /*float32*/ 322 | var a = box2d.b2Cross_V2_V2(d1, d2); 323 | /*float32*/ 324 | var b = box2d.b2Dot_V2_V2(d1, d2); 325 | 326 | /*float32*/ 327 | var angle = box2d.b2Atan2(a, b); 328 | 329 | /*box2d.b2Vec2*/ 330 | var Jd1 = box2d.b2Mul_S_V2((-1 / L1sqr), d1.SelfSkew(), box2d.b2Rope.s_Jd1); 331 | /*box2d.b2Vec2*/ 332 | var Jd2 = box2d.b2Mul_S_V2((1 / L2sqr), d2.SelfSkew(), box2d.b2Rope.s_Jd2); 333 | 334 | /*box2d.b2Vec2*/ 335 | var J1 = box2d.b2Rope.s_J1.Copy(Jd1).SelfNeg(); 336 | /*box2d.b2Vec2*/ 337 | var J2 = box2d.b2Sub_V2_V2(Jd1, Jd2, box2d.b2Rope.s_J2); 338 | /*box2d.b2Vec2*/ 339 | var J3 = Jd2; 340 | 341 | /*float32*/ 342 | var mass = m1 * box2d.b2Dot_V2_V2(J1, J1) + m2 * box2d.b2Dot_V2_V2(J2, J2) + m3 * box2d.b2Dot_V2_V2(J3, J3); 343 | if (mass === 0) { 344 | continue; 345 | } 346 | 347 | mass = 1 / mass; 348 | 349 | /*float32*/ 350 | var C = angle - this.m_as[i]; 351 | 352 | while (C > box2d.b2_pi) { 353 | angle -= 2 * box2d.b2_pi; 354 | C = angle - this.m_as[i]; 355 | } 356 | 357 | while (C < -box2d.b2_pi) { 358 | angle += 2 * box2d.b2_pi; 359 | C = angle - this.m_as[i]; 360 | } 361 | 362 | /*float32*/ 363 | var impulse = -this.m_k3 * mass * C; 364 | 365 | p1.SelfMulAdd((m1 * impulse), J1); 366 | p2.SelfMulAdd((m2 * impulse), J2); 367 | p3.SelfMulAdd((m3 * impulse), J3); 368 | 369 | // this.m_ps[i] = p1; 370 | // this.m_ps[i + 1] = p2; 371 | // this.m_ps[i + 2] = p3; 372 | } 373 | } 374 | box2d.b2Rope.s_d1 = new box2d.b2Vec2(); 375 | box2d.b2Rope.s_d2 = new box2d.b2Vec2(); 376 | box2d.b2Rope.s_Jd1 = new box2d.b2Vec2(); 377 | box2d.b2Rope.s_Jd2 = new box2d.b2Vec2(); 378 | box2d.b2Rope.s_J1 = new box2d.b2Vec2(); 379 | box2d.b2Rope.s_J2 = new box2d.b2Vec2(); 380 | 381 | /** 382 | * @export 383 | * @return {void} 384 | * @param {box2d.b2Draw} draw 385 | */ 386 | box2d.b2Rope.prototype.Draw = function(draw) { 387 | /*box2d.b2Color*/ 388 | var c = new box2d.b2Color(0.4, 0.5, 0.7); 389 | 390 | for ( /*int32*/ var i = 0; i < this.m_count - 1; ++i) { 391 | draw.DrawSegment(this.m_ps[i], this.m_ps[i + 1], c); 392 | } 393 | } 394 | 395 | //#endif 396 | -------------------------------------------------------------------------------- /Contributions/Enhancements/Controllers/b2BuoyancyController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_CONTROLLER 20 | 21 | goog.provide('box2d.b2BuoyancyController'); 22 | 23 | goog.require('box2d.b2Settings'); 24 | goog.require('box2d.b2Controller'); 25 | goog.require('box2d.b2Math'); 26 | goog.require('box2d.b2WorldCallbacks'); 27 | 28 | /** 29 | * Calculates buoyancy forces for fluids in the form of a half 30 | * plane. 31 | * @export 32 | * @constructor 33 | * @extends {box2d.b2Controller} 34 | */ 35 | box2d.b2BuoyancyController = function() { 36 | goog.base(this); // base class constructor 37 | 38 | this.normal = new box2d.b2Vec2(0, 1); 39 | this.velocity = new box2d.b2Vec2(0, 0); 40 | this.gravity = new box2d.b2Vec2(0, 0); 41 | }; 42 | 43 | goog.inherits(box2d.b2BuoyancyController, box2d.b2Controller); 44 | 45 | /** 46 | * The outer surface normal 47 | * @export 48 | * @type {box2d.b2Vec2} 49 | */ 50 | box2d.b2BuoyancyController.prototype.normal = null; 51 | /** 52 | * The height of the fluid surface along the normal 53 | * @export 54 | * @type {number} 55 | */ 56 | box2d.b2BuoyancyController.prototype.offset = 0; 57 | /** 58 | * The fluid density 59 | * @export 60 | * @type {number} 61 | */ 62 | box2d.b2BuoyancyController.prototype.density = 0; 63 | /** 64 | * Fluid velocity, for drag calculations 65 | * @export 66 | * @type {box2d.b2Vec2} 67 | */ 68 | box2d.b2BuoyancyController.prototype.velocity = null; 69 | /** 70 | * Linear drag co-efficient 71 | * @export 72 | * @type {number} 73 | */ 74 | box2d.b2BuoyancyController.prototype.linearDrag = 0; 75 | /** 76 | * Linear drag co-efficient 77 | * @export 78 | * @type {number} 79 | */ 80 | box2d.b2BuoyancyController.prototype.angularDrag = 0; 81 | /** 82 | * If false, bodies are assumed to be uniformly dense, otherwise 83 | * use the shapes densities 84 | * @export 85 | * @type {boolean} 86 | */ 87 | box2d.b2BuoyancyController.prototype.useDensity = false; //False by default to prevent a gotcha 88 | /** 89 | * If true, gravity is taken from the world instead of the 90 | * @export 91 | * @type {boolean} 92 | */ 93 | box2d.b2BuoyancyController.prototype.useWorldGravity = true; 94 | /** 95 | * Gravity vector, if the world's gravity is not used 96 | * @export 97 | * @type {box2d.b2Vec2} 98 | */ 99 | box2d.b2BuoyancyController.prototype.gravity = null; 100 | 101 | /** 102 | * @see box2d.b2Controller::Step 103 | * @export 104 | * @return {void} 105 | * @param {box2d.b2TimeStep} step 106 | */ 107 | box2d.b2BuoyancyController.prototype.Step = function(step) { 108 | if (!this.m_bodyList) 109 | return; 110 | if (this.useWorldGravity) { 111 | this.gravity.Copy(this.GetWorld().GetGravity()); 112 | } 113 | for (var i = this.m_bodyList; i; i = i.nextBody) { 114 | var body = i.body; 115 | if (!body.IsAwake()) { 116 | //Buoyancy force is just a function of position, 117 | //so unlike most forces, it is safe to ignore sleeping bodes 118 | continue; 119 | } 120 | var areac = new box2d.b2Vec2(); 121 | var massc = new box2d.b2Vec2(); 122 | var area = 0; 123 | var mass = 0; 124 | for (var fixture = body.GetFixtureList(); fixture; fixture = fixture.m_next) { 125 | var sc = new box2d.b2Vec2(); 126 | var sarea = fixture.GetShape().ComputeSubmergedArea(this.normal, this.offset, body.GetTransform(), sc); 127 | area += sarea; 128 | areac.x += sarea * sc.x; 129 | areac.y += sarea * sc.y; 130 | var shapeDensity = 0; 131 | if (this.useDensity) { 132 | //TODO: Expose density publicly 133 | shapeDensity = fixture.GetDensity(); 134 | } else { 135 | shapeDensity = 1; 136 | } 137 | mass += sarea * shapeDensity; 138 | massc.x += sarea * sc.x * shapeDensity; 139 | massc.y += sarea * sc.y * shapeDensity; 140 | } 141 | areac.x /= area; 142 | areac.y /= area; 143 | // b2Vec2 localCentroid = b2MulT(body->GetXForm(),areac); 144 | massc.x /= mass; 145 | massc.y /= mass; 146 | if (area < box2d.b2_epsilon) 147 | continue; 148 | //Buoyancy 149 | var buoyancyForce = this.gravity.Clone().SelfNeg(); 150 | buoyancyForce.SelfMul(this.density * area); 151 | body.ApplyForce(buoyancyForce, massc); 152 | //Linear drag 153 | var dragForce = body.GetLinearVelocityFromWorldPoint(areac, new box2d.b2Vec2()); 154 | dragForce.SelfSub(this.velocity); 155 | dragForce.SelfMul((-this.linearDrag * area)); 156 | body.ApplyForce(dragForce, areac); 157 | //Angular drag 158 | //TODO: Something that makes more physical sense? 159 | body.ApplyTorque((-body.GetInertia() / body.GetMass() * area * body.GetAngularVelocity() * this.angularDrag)); 160 | } 161 | } 162 | 163 | /** 164 | * @see b2Controller::Draw 165 | * @export 166 | * @return {void} 167 | * @param {box2d.b2Draw} debugDraw 168 | */ 169 | box2d.b2BuoyancyController.prototype.Draw = function(debugDraw) { 170 | var r = 100; 171 | var p1 = new box2d.b2Vec2(); 172 | var p2 = new box2d.b2Vec2(); 173 | p1.x = this.normal.x * this.offset + this.normal.y * r; 174 | p1.y = this.normal.y * this.offset - this.normal.x * r; 175 | p2.x = this.normal.x * this.offset - this.normal.y * r; 176 | p2.y = this.normal.y * this.offset + this.normal.x * r; 177 | 178 | var color = new box2d.b2Color(0, 0, 0.8); 179 | 180 | debugDraw.DrawSegment(p1, p2, color); 181 | } 182 | 183 | //#endif 184 | -------------------------------------------------------------------------------- /Contributions/Enhancements/Controllers/b2ConstantAccelController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_CONTROLLER 20 | 21 | goog.provide('box2d.b2ConstantAccelController'); 22 | 23 | goog.require('box2d.b2Settings'); 24 | goog.require('box2d.b2Controller'); 25 | goog.require('box2d.b2Math'); 26 | 27 | /** 28 | * Applies a force every frame 29 | * @export 30 | * @constructor 31 | * @extends {box2d.b2Controller} 32 | */ 33 | box2d.b2ConstantAccelController = function() { 34 | goog.base(this); // base class constructor 35 | 36 | this.A = new box2d.b2Vec2(0, 0); 37 | }; 38 | 39 | goog.inherits(box2d.b2ConstantAccelController, box2d.b2Controller); 40 | 41 | /** 42 | * The acceleration to apply 43 | * @export 44 | * @type {box2d.b2Vec2} 45 | */ 46 | box2d.b2ConstantAccelController.prototype.A = null; 47 | 48 | /** 49 | * @see box2d.b2Controller::Step 50 | * @export 51 | * @return {void} 52 | * @param {box2d.b2TimeStep} step 53 | */ 54 | box2d.b2ConstantAccelController.prototype.Step = function(step) { 55 | var dtA = box2d.b2Mul_S_V2(step.dt, this.A, box2d.b2ConstantAccelController.prototype.Step.s_dtA); 56 | for (var i = this.m_bodyList; i; i = i.nextBody) { 57 | var body = i.body; 58 | if (!body.IsAwake()) 59 | continue; 60 | body.SetLinearVelocity(box2d.b2Add_V2_V2(body.GetLinearVelocity(), dtA, box2d.b2Vec2.s_t0)); 61 | } 62 | } 63 | box2d.b2ConstantAccelController.prototype.Step.s_dtA = new box2d.b2Vec2(); 64 | 65 | //#endif 66 | -------------------------------------------------------------------------------- /Contributions/Enhancements/Controllers/b2ConstantForceController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_CONTROLLER 20 | 21 | goog.provide('box2d.b2ConstantForceController'); 22 | 23 | goog.require('box2d.b2Settings'); 24 | goog.require('box2d.b2Controller'); 25 | goog.require('box2d.b2Math'); 26 | 27 | /** 28 | * Applies a force every frame 29 | * @export 30 | * @constructor 31 | * @extends {box2d.b2Controller} 32 | */ 33 | box2d.b2ConstantForceController = function() { 34 | goog.base(this); // base class constructor 35 | 36 | this.F = new box2d.b2Vec2(0, 0); 37 | }; 38 | 39 | goog.inherits(box2d.b2ConstantForceController, box2d.b2Controller); 40 | 41 | /** 42 | * The force to apply 43 | * @export 44 | * @type {box2d.b2Vec2} 45 | */ 46 | box2d.b2ConstantAccelController.prototype.F = null; 47 | 48 | /** 49 | * @see box2d.b2Controller::Step 50 | * @export 51 | * @return {void} 52 | * @param {box2d.b2TimeStep} step 53 | */ 54 | box2d.b2ConstantForceController.prototype.Step = function(step) { 55 | for (var i = this.m_bodyList; i; i = i.nextBody) { 56 | var body = i.body; 57 | if (!body.IsAwake()) 58 | continue; 59 | body.ApplyForce(this.F, body.GetWorldCenter()); 60 | } 61 | } 62 | 63 | //#endif 64 | -------------------------------------------------------------------------------- /Contributions/Enhancements/Controllers/b2Controller.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_CONTROLLER 20 | 21 | goog.provide('box2d.b2Controller'); 22 | 23 | goog.require('box2d.b2Settings'); 24 | 25 | /** 26 | * A controller edge is used to connect bodies and controllers 27 | * together in a bipartite graph. 28 | * @export 29 | * @constructor 30 | */ 31 | box2d.b2ControllerEdge = function() {}; 32 | 33 | /** 34 | * @export 35 | * @type {box2d.b2Controller} 36 | */ 37 | box2d.b2ControllerEdge.prototype.controller = null; ///< provides quick access to other end of this edge. 38 | /** 39 | * @export 40 | * @type {box2d.b2Body} 41 | */ 42 | box2d.b2ControllerEdge.prototype.body = null; ///< the body 43 | /** 44 | * @export 45 | * @type {box2d.b2ControllerEdge} 46 | */ 47 | box2d.b2ControllerEdge.prototype.prevBody = null; ///< the previous controller edge in the controllers's joint list 48 | /** 49 | * @export 50 | * @type {box2d.b2ControllerEdge} 51 | */ 52 | box2d.b2ControllerEdge.prototype.nextBody = null; ///< the next controller edge in the controllers's joint list 53 | /** 54 | * @export 55 | * @type {box2d.b2ControllerEdge} 56 | */ 57 | box2d.b2ControllerEdge.prototype.prevController = null; ///< the previous controller edge in the body's joint list 58 | /** 59 | * @export 60 | * @type {box2d.b2ControllerEdge} 61 | */ 62 | box2d.b2ControllerEdge.prototype.nextController = null; ///< the next controller edge in the body's joint list 63 | 64 | /** 65 | * Base class for controllers. Controllers are a convience for 66 | * encapsulating common per-step functionality. 67 | * @export 68 | * @constructor 69 | */ 70 | box2d.b2Controller = function() {}; 71 | 72 | /** 73 | * @export 74 | * @type {box2d.b2World} 75 | */ 76 | box2d.b2Controller.prototype.m_world = null; 77 | /** 78 | * @export 79 | * @type {box2d.b2ControllerEdge} 80 | */ 81 | box2d.b2Controller.prototype.m_bodyList = null; 82 | /** 83 | * @export 84 | * @type {number} 85 | */ 86 | box2d.b2Controller.prototype.m_bodyCount = 0; 87 | /** 88 | * @export 89 | * @type {box2d.b2Controller} 90 | */ 91 | box2d.b2Controller.prototype.m_prev = null; 92 | /** 93 | * @export 94 | * @type {box2d.b2Controller} 95 | */ 96 | box2d.b2Controller.prototype.m_next = null; 97 | 98 | /** 99 | * Controllers override this to implement per-step 100 | * functionality. 101 | * @export 102 | * @return {void} 103 | * @param {box2d.b2TimeStep} step 104 | */ 105 | box2d.b2Controller.prototype.Step = function(step) {} 106 | 107 | /** 108 | * Controllers override this to provide debug drawing. 109 | * @export 110 | * @return {void} 111 | * @param {box2d.b2Draw} debugDraw 112 | */ 113 | box2d.b2Controller.prototype.Draw = function(debugDraw) {} 114 | 115 | /** 116 | * Get the next controller in the world's body list. 117 | * @export 118 | * @return {box2d.b2Controller} 119 | */ 120 | box2d.b2Controller.prototype.GetNext = function() { 121 | return this.m_next; 122 | } 123 | 124 | /** 125 | * Get the previous controller in the world's body list. 126 | * @export 127 | * @return {box2d.b2Controller} 128 | */ 129 | box2d.b2Controller.prototype.GetPrev = function() { 130 | return this.m_prev; 131 | } 132 | 133 | /** 134 | * Get the parent world of this body. 135 | * @export 136 | * @return {box2d.b2World} 137 | */ 138 | box2d.b2Controller.prototype.GetWorld = function() { 139 | return this.m_world; 140 | } 141 | 142 | /** 143 | * Get the attached body list 144 | * @export 145 | * @return {box2d.b2ControllerEdge} 146 | */ 147 | box2d.b2Controller.prototype.GetBodyList = function() { 148 | return this.m_bodyList; 149 | } 150 | 151 | /** 152 | * Adds a body to the controller list. 153 | * @export 154 | * @return {void} 155 | * @param {box2d.b2Body} body 156 | */ 157 | box2d.b2Controller.prototype.AddBody = function(body) { 158 | var edge = new box2d.b2ControllerEdge(); 159 | 160 | edge.body = body; 161 | edge.controller = this; 162 | 163 | //Add edge to controller list 164 | edge.nextBody = this.m_bodyList; 165 | edge.prevBody = null; 166 | if (this.m_bodyList) 167 | this.m_bodyList.prevBody = edge; 168 | this.m_bodyList = edge; 169 | ++this.m_bodyCount; 170 | 171 | //Add edge to body list 172 | edge.nextController = body.m_controllerList; 173 | edge.prevController = null; 174 | if (body.m_controllerList) 175 | body.m_controllerList.prevController = edge; 176 | body.m_controllerList = edge; 177 | ++body.m_controllerCount; 178 | } 179 | 180 | /** 181 | * Removes a body from the controller list. 182 | * @export 183 | * @return {void} 184 | * @param {box2d.b2Body} body 185 | */ 186 | box2d.b2Controller.prototype.RemoveBody = function(body) { 187 | //Assert that the controller is not empty 188 | if (box2d.ENABLE_ASSERTS) { 189 | box2d.b2Assert(this.m_bodyCount > 0); 190 | } 191 | 192 | //Find the corresponding edge 193 | /*b2ControllerEdge*/ 194 | var edge = this.m_bodyList; 195 | while (edge && edge.body !== body) 196 | edge = edge.nextBody; 197 | 198 | //Assert that we are removing a body that is currently attached to the controller 199 | if (box2d.ENABLE_ASSERTS) { 200 | box2d.b2Assert(edge !== null); 201 | } 202 | 203 | //Remove edge from controller list 204 | if (edge.prevBody) 205 | edge.prevBody.nextBody = edge.nextBody; 206 | if (edge.nextBody) 207 | edge.nextBody.prevBody = edge.prevBody; 208 | if (this.m_bodyList === edge) 209 | this.m_bodyList = edge.nextBody; 210 | --this.m_bodyCount; 211 | 212 | //Remove edge from body list 213 | if (edge.nextController) 214 | edge.nextController.prevController = edge.prevController; 215 | if (edge.prevController) 216 | edge.prevController.nextController = edge.nextController; 217 | if (body.m_controllerList === edge) 218 | body.m_controllerList = edge.nextController; 219 | --body.m_controllerCount; 220 | } 221 | 222 | /** 223 | * Removes all bodies from the controller list. 224 | * @export 225 | * @return {void} 226 | */ 227 | box2d.b2Controller.prototype.Clear = function() { 228 | while (this.m_bodyList) { 229 | this.RemoveBody(this.m_bodyList.body); 230 | } 231 | 232 | this.m_bodyCount = 0; 233 | } 234 | 235 | //#endif 236 | -------------------------------------------------------------------------------- /Contributions/Enhancements/Controllers/b2GravityController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_CONTROLLER 20 | 21 | goog.provide('box2d.b2GravityController'); 22 | 23 | goog.require('box2d.b2Settings'); 24 | goog.require('box2d.b2Controller'); 25 | goog.require('box2d.b2Math'); 26 | 27 | /** 28 | * Applies simplified gravity between every pair of bodies 29 | * @export 30 | * @constructor 31 | * @extends {box2d.b2Controller} 32 | */ 33 | box2d.b2GravityController = function() { 34 | goog.base(this); // base class constructor 35 | }; 36 | 37 | goog.inherits(box2d.b2GravityController, box2d.b2Controller); 38 | 39 | /** 40 | * Specifies the strength of the gravitiation force 41 | * @export 42 | * @type {number} 43 | */ 44 | box2d.b2GravityController.prototype.G = 1; 45 | /** 46 | * If true, gravity is proportional to r^-2, otherwise r^-1 47 | * @export 48 | * @type {boolean} 49 | */ 50 | box2d.b2GravityController.prototype.invSqr = true; 51 | 52 | /** 53 | * @see b2Controller::Step 54 | * @export 55 | * @return {void} 56 | * @param {box2d.b2TimeStep} step 57 | */ 58 | box2d.b2GravityController.prototype.Step = function(step) { 59 | if (this.invSqr) { 60 | for (var i = this.m_bodyList; i; i = i.nextBody) { 61 | var body1 = i.body; 62 | var p1 = body1.GetWorldCenter(); 63 | var mass1 = body1.GetMass(); 64 | for (var j = this.m_bodyList; j !== i; j = j.nextBody) { 65 | var body2 = j.body; 66 | var p2 = body2.GetWorldCenter(); 67 | var mass2 = body2.GetMass(); 68 | var dx = p2.x - p1.x; 69 | var dy = p2.y - p1.y; 70 | var r2 = dx * dx + dy * dy; 71 | if (r2 < box2d.b2_epsilon) 72 | continue; 73 | var f = box2d.b2GravityController.prototype.Step.s_f.Set(dx, dy); 74 | f.SelfMul(this.G / r2 / box2d.b2Sqrt(r2) * mass1 * mass2); 75 | if (body1.IsAwake()) 76 | body1.ApplyForce(f, p1); 77 | if (body2.IsAwake()) 78 | body2.ApplyForce(f.SelfMul(-1), p2); 79 | } 80 | } 81 | } else { 82 | for (var i = this.m_bodyList; i; i = i.nextBody) { 83 | var body1 = i.body; 84 | var p1 = body1.GetWorldCenter(); 85 | var mass1 = body1.GetMass(); 86 | for (var j = this.m_bodyList; j !== i; j = j.nextBody) { 87 | var body2 = j.body; 88 | var p2 = body2.GetWorldCenter(); 89 | var mass2 = body2.GetMass(); 90 | var dx = p2.x - p1.x; 91 | var dy = p2.y - p1.y; 92 | var r2 = dx * dx + dy * dy; 93 | if (r2 < box2d.b2_epsilon) 94 | continue; 95 | var f = box2d.b2GravityController.prototype.Step.s_f.Set(dx, dy); 96 | f.SelfMul(this.G / r2 * mass1 * mass2); 97 | if (body1.IsAwake()) 98 | body1.ApplyForce(f, p1); 99 | if (body2.IsAwake()) 100 | body2.ApplyForce(f.SelfMul(-1), p2); 101 | } 102 | } 103 | } 104 | } 105 | box2d.b2GravityController.prototype.Step.s_f = new box2d.b2Vec2(); 106 | 107 | //#endif 108 | -------------------------------------------------------------------------------- /Contributions/Enhancements/Controllers/b2TensorDampingController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | //#if B2_ENABLE_CONTROLLER 20 | 21 | goog.provide('box2d.b2TensorDampingController'); 22 | 23 | goog.require('box2d.b2Settings'); 24 | goog.require('box2d.b2Controller'); 25 | goog.require('box2d.b2Math'); 26 | 27 | /** 28 | * Applies top down linear damping to the controlled bodies 29 | * The damping is calculated by multiplying velocity by a matrix 30 | * in local co-ordinates. 31 | * @export 32 | * @constructor 33 | * @extends {box2d.b2Controller} 34 | */ 35 | box2d.b2TensorDampingController = function() { 36 | goog.base(this); // base class constructor 37 | 38 | /// Tensor to use in damping model 39 | /** @type {box2d.b2Mat22} */ 40 | this.T = new box2d.b2Mat22(); 41 | /*Some examples (matrixes in format (row1; row2)) 42 | (-a 0; 0 -a) Standard isotropic damping with strength a 43 | ( 0 a; -a 0) Electron in fixed field - a force at right angles to velocity with proportional magnitude 44 | (-a 0; 0 -b) Differing x and y damping. Useful e.g. for top-down wheels. 45 | */ 46 | //By the way, tensor in this case just means matrix, don't let the terminology get you down. 47 | 48 | /// Set this to a positive number to clamp the maximum amount of damping done. 49 | /** @type {number} */ 50 | this.maxTimestep = 0; 51 | // Typically one wants maxTimestep to be 1/(max eigenvalue of T), so that damping will never cause something to reverse direction 52 | }; 53 | 54 | goog.inherits(box2d.b2TensorDampingController, box2d.b2Controller); 55 | 56 | /** 57 | * Tensor to use in damping model 58 | * @export 59 | * @type {box2d.b2Mat22} 60 | */ 61 | box2d.b2TensorDampingController.prototype.T = new box2d.b2Mat22(); 62 | /*Some examples (matrixes in format (row1; row2)) 63 | (-a 0; 0 -a) Standard isotropic damping with strength a 64 | ( 0 a; -a 0) Electron in fixed field - a force at right angles to velocity with proportional magnitude 65 | (-a 0; 0 -b) Differing x and y damping. Useful e.g. for top-down wheels. 66 | */ 67 | //By the way, tensor in this case just means matrix, don't let the terminology get you down. 68 | 69 | /** 70 | * Set this to a positive number to clamp the maximum amount of 71 | * damping done. 72 | * @export 73 | * @type {number} 74 | */ 75 | box2d.b2TensorDampingController.prototype.maxTimestep = 0; 76 | // Typically one wants maxTimestep to be 1/(max eigenvalue of T), so that damping will never cause something to reverse direction 77 | 78 | /** 79 | * @see b2Controller::Step 80 | * @return {void} 81 | * @param {box2d.b2TimeStep} step 82 | */ 83 | box2d.b2TensorDampingController.prototype.Step = function(step) { 84 | var timestep = step.dt; 85 | if (timestep <= box2d.b2_epsilon) 86 | return; 87 | if (timestep > this.maxTimestep && this.maxTimestep > 0) 88 | timestep = this.maxTimestep; 89 | for (var i = this.m_bodyList; i; i = i.nextBody) { 90 | var body = i.body; 91 | if (!body.IsAwake()) 92 | continue; 93 | var damping = body.GetWorldVector( 94 | box2d.b2Mul_M22_V2( 95 | this.T, 96 | body.GetLocalVector( 97 | body.GetLinearVelocity(), 98 | box2d.b2Vec2.s_t0), 99 | box2d.b2Vec2.s_t1), 100 | box2d.b2TensorDampingController.prototype.Step.s_damping); 101 | // body->SetLinearVelocity(body->GetLinearVelocity() + timestep * damping); 102 | body.SetLinearVelocity(box2d.b2Add_V2_V2(body.GetLinearVelocity(), box2d.b2Mul_S_V2(timestep, damping, box2d.b2Vec2.s_t0), box2d.b2Vec2.s_t1)); 103 | } 104 | } 105 | box2d.b2TensorDampingController.prototype.Step.s_damping = new box2d.b2Vec2(); 106 | 107 | /** 108 | * Sets damping independantly along the x and y axes 109 | * @return {void} 110 | * @param {number} xDamping 111 | * @param {number} yDamping 112 | */ 113 | box2d.b2TensorDampingController.prototype.SetAxisAligned = function(xDamping, yDamping) { 114 | this.T.ex.x = (-xDamping); 115 | this.T.ex.y = 0; 116 | this.T.ey.x = 0; 117 | this.T.ey.y = (-yDamping); 118 | if (xDamping > 0 || yDamping > 0) { 119 | this.maxTimestep = 1 / box2d.b2Max(xDamping, yDamping); 120 | } else { 121 | this.maxTimestep = 0; 122 | } 123 | } 124 | 125 | //#endif 126 | -------------------------------------------------------------------------------- /Contributions/Readme.txt: -------------------------------------------------------------------------------- 1 | This folder contains user contributions. Contributions are _not_ supported by the Box2D project. 2 | 3 | Contributions may not compile or function correctly. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | liquidfun-pure-javascript 3 | ======== 4 | I just wanted to play with liquidfun and javascript as quickly as possible. 5 | 6 | **To get it going: just open up the `index.html` and you'll get a simple bouncing blob that will jump with any keypress.** 7 | 8 | None of it is minified, which makes debugging a breeze. It's just so you can get up and running as quickly as possible. I'll leave the minifying up to the reader. 9 | 10 | Background 11 | ======== 12 | I looked *everywhere* for a simple box2d port that had readable javascript so debugging was easy, but couldn't find anything. Finally, I found [flyover's port of box2d](https://github.com/flyover/box2d.js), which also conveniently included liquidfun. 13 | 14 | The only downside of that was that it used google's closure compiler, which I didn't want to mess with. I therefore manually went through each file, and removed all of the closure compiler references, replacing them with non-closure equivalent javascript. 15 | 16 | I've also included simple drawing functions onto a canvas so you can see what is happening. 17 | 18 | 19 | **Note:** 20 | This *also* has support for `b2ParticleSystem.GetBodyContacts`, which for some reason some ports of liquidfun don't support. -------------------------------------------------------------------------------- /Renderer.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function Renderer(world,ctx) { 4 | var canvas=document.getElementById("ballCanvas"); 5 | var ctx=canvas.getContext("2d"); 6 | const SCALE = canvas.width/10 7 | 8 | this.render = function() { 9 | ctx.clearRect(0,0,canvas.width,canvas.height); 10 | for (body = world.GetBodyList(); body; body = body.GetNext()){ 11 | var transform = body.GetTransform(); 12 | 13 | for (f = body.GetFixtureList(); f; f = f.GetNext()) { 14 | this.draw(f,transform); 15 | } 16 | } 17 | this.drawParticleSystem() 18 | ctx.stroke(); 19 | } 20 | 21 | 22 | this.draw = function(fixture, transform){ 23 | if (fixture.userData.type == "circle") return this.drawCircle(fixture.GetShape().m_radius, transform.p, fixture.color || "black") 24 | if (fixture.userData.type == "square") return this.drawPolygon(fixture, transform) 25 | } 26 | 27 | this.drawCircle = function(radius, pos, color, index = " "){ 28 | const newRadius = radius*SCALE 29 | const x = pos.x*SCALE 30 | const y = pos.y*SCALE 31 | ctx.moveTo(x + newRadius, y) 32 | //ctx.fillStyle = "white" 33 | ctx.strokeStyle= color 34 | ctx.beginPath() 35 | 36 | ctx.arc(x,y,newRadius, 0,2*Math.PI); 37 | 38 | // ctx.fill() 39 | ctx.strokeStyle= "grey" 40 | ctx.stroke(); 41 | 42 | 43 | ctx.font = '12px serif'; 44 | ctx.strokeText(index, x, y); 45 | 46 | 47 | ctx.closePath() 48 | } 49 | 50 | this.drawPolygon = function(fixture, transform){ 51 | 52 | const pos = fixture.GetBody().GetPosition() 53 | ctx.beginPath(); 54 | 55 | //create a line 56 | //cct.lineWidth = .08; 57 | let truePoints = [] 58 | var shape = fixture.GetShape() 59 | for (var i=0;i -1){ 83 | color = "green" 84 | //console.log("i is touching") 85 | } 86 | this.drawCircle(system.m_particleDiameter/2,particles[i],color,i ) 87 | 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | b 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Box2D Hello World 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /inherit.js: -------------------------------------------------------------------------------- 1 | // A crappy manual copy of googles inheritance so we don't have to rely on closure 2 | 3 | function setInherit (childCtor, parentCtor) { 4 | /** @constructor */ 5 | function tempCtor() {} 6 | tempCtor.prototype = parentCtor.prototype; 7 | childCtor.superClass_ = parentCtor.prototype; 8 | childCtor.prototype = new tempCtor(); 9 | /** @override */ 10 | childCtor.prototype.constructor = childCtor; 11 | 12 | /** 13 | * Calls superclass constructor/method. 14 | * 15 | * This function is only available if you use goog.inherits to 16 | * express inheritance relationships between classes. 17 | * 18 | * NOTE: This is a replacement for goog.base and for superClass_ 19 | * property defined in childCtor. 20 | * 21 | * @param {!Object} me Should always be "this". 22 | * @param {string} methodName The method name to call. Calling 23 | * superclass constructor can be done with the special string 24 | * 'constructor'. 25 | * @param {...*} var_args The arguments to pass to superclass 26 | * method/constructor. 27 | * @return {*} The return value of the superclass method/constructor. 28 | */ 29 | childCtor.base = function(me, methodName, var_args) { 30 | // Copying using loop to avoid deop due to passing arguments object to 31 | // function. This is faster in many JS engines as of late 2014. 32 | var args = new Array(arguments.length - 2); 33 | for (var i = 2; i < arguments.length; i++) { 34 | args[i - 2] = arguments[i]; 35 | } 36 | return parentCtor.prototype[methodName].apply(me, args); 37 | }; 38 | }; -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org 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 as such, and must not be 15 | * misrepresented as being the original software. 16 | * 3. This notice may not be removed or altered from any source distribution. 17 | */ 18 | 19 | // goog.provide('box2d.HelloWorld'); 20 | 21 | // goog.require('box2d'); 22 | 23 | /** 24 | * This is a simple example of building and running a simulation 25 | * using Box2D. Here we create a large ground box and a small 26 | * dynamic box. 27 | * There are no graphics for this example. Box2D is meant to be 28 | * used with your rendering engine in your game engine. 29 | */ 30 | 31 | /** 32 | * @export 33 | * @return {number} 34 | * @param {Array.<*>=} args 35 | */ 36 | 37 | let world 38 | let jumping = false; 39 | let touchingParticles = [] 40 | let particleNormals = {} 41 | function mainApp(args) { 42 | 43 | function onload() { 44 | 45 | var gravity = new box2d.b2Vec2(0, 10); 46 | world = new box2d.b2World(gravity); 47 | var particleSystemDef = new box2d.b2ParticleSystemDef(); 48 | world.CreateParticleSystem(particleSystemDef); 49 | Renderer = new Renderer(world) 50 | // createCircleBody(4.9,.8) 51 | // createCircleBody(5,2) 52 | 53 | createBoxBody(0,5,.1,10) // leftwall 54 | createBoxBody(5,0,10,.1) // to 55 | createBoxBody(10,5,.1,10) // right wall 56 | createBoxBody(5,10,10,.1) 57 | createBoxBody(5,5,1,1) 58 | 59 | createBoxBody(2,7,.2,7,100) 60 | createBoxBody(8,7,.2,7,-100) 61 | circle = new box2d.b2CircleShape(.7) 62 | pgd = new box2d.b2ParticleGroupDef(); 63 | pgd.position=new box2d.b2Vec2(5,1) 64 | pgd.flags = box2d.b2ParticleFlag.b2_elasticParticle; 65 | pgd.groupFlags = box2d.b2ParticleGroupFlag.b2_solidParticleGroup 66 | pgd.shape = circle; 67 | pgd.strength=.2 68 | 69 | pgd.color.Set(0, 255, 0, 255) 70 | world.GetParticleSystemList().SetRadius(.15) 71 | partgroup = world.GetParticleSystemList().CreateParticleGroup(pgd); 72 | 73 | requestAnimationFrame(gameLoop); 74 | 75 | 76 | document.addEventListener('keyup', (event) => { 77 | jumping = false 78 | }) 79 | 80 | 81 | document.addEventListener('keydown', (event) => { 82 | if (jumping) return 83 | jumping = true; 84 | const lastIndex = partgroup.m_lastIndex - 1 85 | const firstIndex = partgroup.m_firstIndex 86 | const length = lastIndex-firstIndex 87 | const particleSystem = world.GetParticleSystemList() 88 | //const vecFirst = world.GetParticleSystem().GetParticlePositionBuffer()[firstIndex] 89 | //const vecLast= world.GetParticleSystem().GetParticlePositionBuffer()[lastIndex] 90 | //const newVec = new box2d.b2Vec2(vecFirst.x-vecLast.x, vecFirst.y-vecLast.y).Multiply(5) 91 | newVec = new box2d.b2Vec2(0,-10) 92 | 93 | // get contacting bodies 94 | oppositeBodyPoints = touchingParticles.map(particle => { 95 | return particleSystem.GetPositionBuffer()[28-particle] 96 | 97 | }) 98 | 99 | touchingParticlePoints = touchingParticles.map(index=>{ 100 | return particleSystem.GetPositionBuffer()[index] 101 | }) 102 | 103 | 104 | 105 | let distancePoints = [] 106 | for (var i=0;i 1/15) { dt = 1/15; } 187 | update(dt); 188 | lastFrame = tm; 189 | }; 190 | 191 | function update(){ 192 | touchingParticles.length = 0 193 | world.GetParticleSystemList().m_bodyContactBuffer = new box2d.b2GrowableBuffer(function() { 194 | return new box2d.b2ParticleBodyContact(); 195 | }); 196 | 197 | world.Step(1/40,10,10) 198 | getTouchingParticles() 199 | 200 | Renderer.render() 201 | 202 | 203 | 204 | 205 | } 206 | 207 | function getTouchingParticles(){ 208 | particleNormals = {} 209 | const system = world.GetParticleSystemList() 210 | bodyContacts = system.GetBodyContacts() 211 | const contacts = bodyContacts.filter(particle => { 212 | return particle.body 213 | }) 214 | 215 | 216 | bodyContacts.forEach(contact => { 217 | particleNormals[contact.index] = contact.normal 218 | }) 219 | 220 | 221 | 222 | contacts.forEach(contact => { 223 | touchingParticles.push(contact.index) 224 | }); 225 | } 226 | 227 | 228 | 229 | onload(); 230 | } 231 | --------------------------------------------------------------------------------