1 /**
  2  * The Render Engine
  3  * DistanceJointComponent
  4  *
  5  * @fileoverview A distance joint which can be used in a {@link Simulation}.
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  *
  9  * @author: $Author: bfattori $
 10  * @version: $Revision: 1555 $
 11  *
 12  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 13  *
 14  * Permission is hereby granted, free of charge, to any person obtaining a copy
 15  * of this software and associated documentation files (the "Software"), to deal
 16  * in the Software without restriction, including without limitation the rights
 17  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 18  * copies of the Software, and to permit persons to whom the Software is
 19  * furnished to do so, subject to the following conditions:
 20  *
 21  * The above copyright notice and this permission notice shall be included in
 22  * all copies or substantial portions of the Software.
 23  *
 24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 29  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 30  * THE SOFTWARE.
 31  *
 32  */
 33 
 34 // The class this file defines and its required classes
 35 R.Engine.define({
 36     "class":"R.components.physics.DistanceJoint",
 37     "requires":[
 38         "R.components.physics.BaseJoint",
 39         "R.physics.Simulation",
 40         "R.math.Math2D"
 41     ]
 42 });
 43 
 44 /**
 45  * @class A distance joint which maintains constant distance between two bodies
 46  *        in a {@link R.physics.Simulation}.  You can picture this as a massless
 47  *        rigid rod anchored at the two anchor points.
 48  *
 49  * @param name {String} Name of the component
 50  * @param body1 {R.components.physics.BaseBody} The first body for the joint
 51  * @param body2 {R.components.physics.BaseBody} The second body for the joint
 52  * @param anchor1 {R.math.Vector2D} The anchor on body 1, or <code>null</code>
 53  * @param anchor2 {R.math.Vector2D} The anchor on body 2, or <code>null</code>
 54  *
 55  * @extends R.components.physics.BaseJoint
 56  * @constructor
 57  * @description Creates a distance joint between two physical bodies.  The distance can
 58  *              be softened by adjusting the frequency and the damping ratio of the joint.
 59  *              Rotation is not limited by this joint.  If you do not specify anchor 1 or
 60  *              anchor 2, the joint will use the position of each body offset by its physical
 61  *              origin.
 62  */
 63 R.components.physics.DistanceJoint = function () {
 64     return R.components.physics.BaseJoint.extend(/** @scope R.components.physics.DistanceJoint.prototype */{
 65 
 66         anchor1:null,
 67         anchor2:null,
 68 
 69         /**
 70          * @private
 71          */
 72         constructor:function (name, body1, body2, anchor1, anchor2) {
 73             var jointDef = new Box2D.Dynamics.Joints.b2DistanceJointDef();
 74 
 75             if (anchor1) {
 76                 this.anchor1 = R.math.Point2D.create(anchor1).div(R.physics.Simulation.WORLD_SIZE);
 77             }
 78 
 79             if (anchor2) {
 80                 this.anchor2 = R.math.Point2D.create(anchor2).div(R.physics.Simulation.WORLD_SIZE);
 81             }
 82 
 83             this.base(name || "DistanceJoint", body1, body2, jointDef);
 84         },
 85 
 86         /**
 87          * Offset the joint's anchors by the given point
 88          * @param pt {R.math.Point2D} The offset amount
 89          */
 90         offset:function (pt) {
 91             var ofs = R.clone(pt).div(R.physics.Simulation.WORLD_SIZE);
 92 
 93             if (this.anchor1) {
 94                 this.anchor1.add(ofs);
 95             }
 96 
 97             if (this.anchor2) {
 98                 this.anchor2.add(ofs);
 99             }
100 
101             ofs.destroy();
102         },
103 
104         /**
105          * When simulation starts set the anchor points to the position of each rigid body.
106          * @private
107          */
108         startSimulation:function () {
109             if (!this.getSimulation()) {
110 
111                 var anchor1 = new Box2D.Common.Math.b2Vec2(), anchor2 = new Box2D.Common.Math.b2Vec2(),
112                     a1 = this.anchor1, a2 = this.anchor2;
113 
114                 // If a1 or a2 were not specified, use the position of each body
115                 if (!a1) {
116                     a1 = R.math.Point2D.create(this.getBody1().getPosition());
117                     a1.add(this.getBody1().getLocalOrigin()).div(R.physics.Simulation.WORLD_SIZE);
118                 }
119 
120                 if (!a2) {
121                     a2 = R.math.Point2D.create(this.getBody2().getPosition());
122                     a2.add(this.getBody2().getLocalOrigin()).div(R.physics.Simulation.WORLD_SIZE);
123                 }
124 
125                 // Translate the anchor positions into B2 vectors
126                 anchor1.Set(a1.x, a1.y);
127                 anchor2.Set(a2.x, a2.y);
128 
129                 // Initialize the joint
130                 this.getJointDef().Initialize(this.getBody1().getBody(), this.getBody2().getBody(),
131                     anchor1, anchor2);
132             }
133 
134             this.base();
135         },
136 
137         /**
138          * Set the frequency which is used to determine joint softness.  According to
139          * Box2d documentation the frequency should be less than half of the time step
140          * used for the simulation.  In the engine, the frequency of the time step is
141          * the frame rate.
142          *
143          * @param hz {Number} The frequency in Hertz.
144          */
145         setFrequency:function (hz) {
146             this.getJointDef().frequencyHz = hz;
147         },
148 
149         /**
150          * Get the frequency from the joint definition.
151          * @return {Number}
152          */
153         getFrequency:function () {
154             return this.getJointDef().frequencyHz;
155         },
156 
157         /**
158          * Set the damping ratio which is used to determine joint softness.  The value
159          * should be between 0.0 and 1.0, with 1.0 being extremely rigid.
160          *
161          * @param dampingRatio {Number} A value between 0.0 and 1.0
162          */
163         setDampingRatio:function (dampingRatio) {
164             this.getJointDef().dampingRatio = dampingRatio;
165         },
166 
167         /**
168          * Get the damping ratio from the joint definition.
169          * @return {Number}
170          */
171         getDampingRatio:function () {
172             return this.getJointDef().dampingRatio;
173         }
174 
175     }, { /** @scope R.components.physics.DistanceJoint.prototype */
176 
177         /**
178          * Get the class name of this object
179          *
180          * @return {String} "R.components.physics.DistanceJoint"
181          */
182         getClassName:function () {
183             return "R.components.physics.DistanceJoint";
184         }
185     });
186 }