From 3f5e6877e92472ed7fb87cadfabef2c2a693e65a Mon Sep 17 00:00:00 2001 From: "Carl A. Fahlstrom" Date: Mon, 14 Jul 2014 10:55:38 -0600 Subject: [PATCH 1/2] Simple typo fix. --- forces/Repulsion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forces/Repulsion.js b/forces/Repulsion.js index efd7365..834ba3f 100644 --- a/forces/Repulsion.js +++ b/forces/Repulsion.js @@ -78,7 +78,7 @@ define(function(require, exports, module) { /** * An inverse squared distance decay function - * @attribute INVERSE + * @attribute GRAVITY * @type Function * @param {Number} r distance from the source body * @param {Number} cutoff a distance shift to avoid singularities From 3251c7e134a9dff95afa79eeed5bb47735d677ca Mon Sep 17 00:00:00 2001 From: "Carl A. Fahlstrom" Date: Tue, 15 Jul 2014 09:13:05 -0600 Subject: [PATCH 2/2] Added prototype for Square which inherits from Rectangle. Added file to create prototype for an Elliptical body. Added conditionals to the collision detection methed for different body shapes. Added collision detection and setting of normal vector for limited case of collision of two squares of normal orientaion. Added a variable to get the orientation of bodies of rectangle type for more general collisions. Added the start of simple method for adding torque for off center collisions of squares. Work in progress. --- bodies/Ellipse.js | 61 +++++++++++++++++++++++++++++++ bodies/Square.js | 44 +++++++++++++++++++++++ constraints/Collision.js | 77 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 bodies/Ellipse.js create mode 100644 bodies/Square.js diff --git a/bodies/Ellipse.js b/bodies/Ellipse.js new file mode 100644 index 0000000..652a3b2 --- /dev/null +++ b/bodies/Ellipse.js @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Owner: david@famo.us + * @license MPL 2.0 + * @copyright Famous Industries, Inc. 2014 + */ + +define(function(require, exports, module) { + var Body = require('./Body'); + var Matrix = require('famous/math/Matrix'); + + /** + * Implements a circle, or spherical, geometry for an Body with + * radius. + * + * @class Circle + * @extends Body + * @constructor + */ + function Circle(options) { + options = options || {}; + this.setRadius(options.radius || 0); + Body.call(this, options); + } + + Circle.prototype = Object.create(Body.prototype); + Circle.prototype.constructor = Circle; + + /** + * Basic setter for radius. + * @method setRadius + * @param r {Number} radius + */ + Circle.prototype.setRadius = function setRadius(r) { + this.radius = r; + this.size = [2*this.radius, 2*this.radius]; + this.setMomentsOfInertia(); + }; + + Circle.prototype.setMomentsOfInertia = function setMomentsOfInertia() { + var m = this.mass; + var r = this.radius; + + this.inertia = new Matrix([ + [0.25 * m * r * r, 0, 0], + [0, 0.25 * m * r * r, 0], + [0, 0, 0.5 * m * r * r] + ]); + + this.inverseInertia = new Matrix([ + [4 / (m * r * r), 0, 0], + [0, 4 / (m * r * r), 0], + [0, 0, 2 / (m * r * r)] + ]); + }; + + module.exports = Circle; + +}); diff --git a/bodies/Square.js b/bodies/Square.js new file mode 100644 index 0000000..f4b3067 --- /dev/null +++ b/bodies/Square.js @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Owner: david@famo.us + * @license MPL 2.0 + * @copyright Famous Industries, Inc. 2014 + */ + +define(function(require, exports, module) { + var Body = require('./Rectangle'); + var Matrix = require('famous/math/Matrix'); + + /** + * Implements a square geometry for an Body with + * size = length. + * + * @class Square + * @extends Rectangle + * @constructor + */ + function Square(options) { + options = options || {}; + this.size = options.size || [0,0]; + Rectangle.call(this, options); + } + + Square.prototype = Object.create(Rectangle.prototype); + Square.prototype.constructor = Square; + + /** + * Basic setter for size. + * @method setSize + * @param length + */ + Square.prototype.setSize = function setSize(length) { + var size = [length, length]; + this.size = size; + this.setMomentsOfInertia(); + }; + + module.exports = Square; + +}); diff --git a/constraints/Collision.js b/constraints/Collision.js index 7026936..0bca52b 100644 --- a/constraints/Collision.js +++ b/constraints/Collision.js @@ -33,6 +33,8 @@ define(function(require, exports, module) { this.vDiff = new Vector(); this.impulse1 = new Vector(); this.impulse2 = new Vector(); + this.torque1 = new Vector(); + this.torque2 = new Vector(); Constraint.call(this); } @@ -74,7 +76,15 @@ define(function(require, exports, module) { var v1 = source.velocity; var p1 = source.position; var w1 = source.inverseMass; - var r1 = source.radius; + + if (source instanceof Circle) { + var r1 = source.radius; + } + else if (source instanceof Ellipse) { + } + else if (source instanceof Rectangle) { + var o1 = source.orientation; + } var options = this.options; var drift = options.drift; @@ -86,6 +96,8 @@ define(function(require, exports, module) { var vDiff = this.vDiff; var impulse1 = this.impulse1; var impulse2 = this.impulse2; + var torque1 = this.torque1; + var torque2 = this.torque2; for (var i = 0; i < targets.length; i++) { var target = targets[i]; @@ -95,19 +107,48 @@ define(function(require, exports, module) { var v2 = target.velocity; var p2 = target.position; var w2 = target.inverseMass; - var r2 = target.radius; + + if (target instanceof Rectangle) { + var o2 = target.orientation; + } pDiff.set(p2.sub(p1)); vDiff.set(v2.sub(v1)); var dist = pDiff.norm(); - var overlap = dist - (r1 + r2); var effMass = 1/(w1 + w2); var gamma = 0; + if (target instanceof Circle) { + var r1 = target.radius; + } + else if (target instanceof Ellispe) { + } + else if (target instanceof Square) { + var theta = Math.atan(pDiff.y/pDiff.x); + if (source instanceof Square) { + var r1 = source.size[0]/2 * Math.cos(theta); + } + var r2 = target.size[0]/2 * Math.cos(theta); + } + else if (target instanceof Rectangle) { + } + + var overlap = dist - (r1 + r2); + if (overlap < 0) { - n.set(pDiff.normalize()); + if ((source instanceof Circle) && (target instanceof Circle)) { + n.set(pDiff.normalize()); + } + if ((source instanceof Square) && (target instanceof Square)) { + if ((theta < Math.PI/4) && theta > -1*Math.PI/4) { + n.set(1); + } + if ((theta > Math.PI/4) && theta < -1*Math.PI/4) { + n.set([0,1,0]); + } + } if (this._eventOutput) { var collisionData = { @@ -121,9 +162,17 @@ define(function(require, exports, module) { this._eventOutput.emit('collision', collisionData); } - var lambda = (overlap <= slop) - ? ((1 + restitution) * n.dot(vDiff) + drift/dt * (overlap - slop)) / (gamma + dt/effMass) - : ((1 + restitution) * n.dot(vDiff)) / (gamma + dt/effMass); + //if ((source instanceof Circle) && (target instanceof Circle)) { + var lambda = (overlap <= slop) + ? ((1 + restitution) * n.dot(vDiff) + drift/dt * (overlap - slop)) / (gamma + dt/effMass) + : ((1 + restitution) * n.dot(vDiff)) / (gamma + dt/effMass); + //} + //if ((source instanceof Square) && (target instanceof Square)) { + // var vtheta = Math.atan(vDiff.y/vDiff.x); + // var lambda = (overlap <= slop) + // ? ((1 + restitution) * n.dot(vDiff) + drift/dt * (overlap - slop)) / (gamma + dt/effMass) + // : ((1 + restitution) * n.dot(vDiff)) / (gamma + dt/effMass); + //} n.mult(dt*lambda).put(impulse1); impulse1.mult(-1).put(impulse2); @@ -131,6 +180,20 @@ define(function(require, exports, module) { source.applyImpulse(impulse1); target.applyImpulse(impulse2); + // Calculate the torque for off center collisions of Rectangular bodies. + // Normal orientation and same size of source and target. + else if (target instanceof Rectangle) { + var fdist = pDiff.y.mult(0.5); + var torque1 = (overlap <= slop) + ? (vDiff.cross(fdist).mult(1 + restitution) + drift/dt * (overlap - slop)) / (gamma + dt/effMass) + : vDiff.cross(fdist).mult((1 + restitution)/(gamma + dt/effMass)); + //vDiff.cross(fdist).put(torque1); + torque1.mult(-1).put(torque2); + source.applyTorque(torque1); + target.applyTorque(torque2); + } + + //source.setPosition(p1.add(n.mult(overlap/2))); //target.setPosition(p2.sub(n.mult(overlap/2)));