1 /**
  2  * The Render Engine
  3  * RevoluteJointComponent
  4  *
  5  * @fileoverview A revolute 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.RevoluteJoint",
 37     "requires":[
 38         "R.components.physics.BaseMotorJoint",
 39         "R.physics.Simulation",
 40         "R.math.Point2D",
 41         "R.math.Math2D",
 42         "R.math.Vector2D"
 43     ]
 44 });
 45 
 46 /**
 47  * @class A revolute joint which allows two bodies to revolve around a common
 48  *        anchor point in a {@link R.physics.Simulation}.
 49  *
 50  * @param name {String} Name of the component
 51  * @param body1 {R.components.physics.BaseBody} The first body for the joint
 52  * @param body2 {R.components.physics.BaseBody} The second body for the joint
 53  * @param anchor {R.math.Point2D} A point, in world coordinates relative to the two
 54  *    bodies, to use as the joint's anchor point
 55  *
 56  * @extends R.components.physics.BaseMotorJoint
 57  * @constructor
 58  * @description Creates a revolute joint between two physical bodies.
 59  */
 60 R.components.physics.RevoluteJoint = function () {
 61     return R.components.physics.BaseMotorJoint.extend(/** @scope R.components.physics.RevoluteJoint.prototype */{
 62 
 63         anchor:null,
 64         limits:null,
 65 
 66         /**
 67          * @private
 68          */
 69         constructor:function (name, body1, body2, anchor) {
 70             var jointDef = new Box2D.Dynamics.Joints.b2RevoluteJointDef();
 71 
 72             this.limits = [];
 73             this.anchor = R.math.Point2D.create(anchor).div(R.physics.Simulation.WORLD_SIZE);
 74             this.base(name || "RevoluteJoint", body1, body2, jointDef);
 75         },
 76 
 77         /**
 78          * When simulation starts offset the anchor point by the position of rigid body 1 (the "from" body).
 79          * @private
 80          */
 81         startSimulation:function () {
 82             if (!this.getSimulation()) {
 83                 var anchor = new Box2D.Common.Math.b2Vec2();
 84                 anchor.Set(this.anchor.x, this.anchor.y);
 85 
 86                 this.getJointDef().Initialize(this.getBody1().getBody(), this.getBody2().getBody(), anchor);
 87 
 88                 if (this.limits.length != 0) {
 89                     this.getJointDef().upperAngle = R.math.Math2D.degToRad(Math.max(this.limits[1], this.limits[0]));
 90                     this.getJointDef().lowerAngle = R.math.Math2D.degToRad(Math.min(this.limits[0], this.limits[1]));
 91                     this.getJointDef().enableLimit = true;
 92                 }
 93             }
 94 
 95             this.base();
 96         },
 97 
 98         /**
 99          * Offset the joint's anchors by the given point
100          * @param pt {R.math.Point2D} The offset amount
101          */
102         offset:function (pt) {
103             var ofs = R.clone(pt).div(R.physics.Simulation.WORLD_SIZE);
104             this.anchor.add(ofs);
105             ofs.destroy();
106         },
107 
108         /**
109          * Clear the rotational limits.
110          */
111         clearLimits:function () {
112             this.limits = [];
113         },
114 
115         /**
116          * Get the upper limiting angle, in degrees, through which the joint can rotate.
117          * @return {Number} The angle, or <code>undefined</code>
118          */
119         getUpperLimitAngle:function () {
120             return this.limits.length != 0 ? R.math.Math2D.radToDeg(this.limits[1]) : undefined;
121         },
122 
123         /**
124          * Set the upper limiting angle through which the joint can rotate.  Zero is the
125          * "top" of the rotation, with rotation moving positively in a counter-clockwise
126          * rotation.  Negative numbers will move the rotation clockwise.
127          *
128          * @param angle {Number} An angle in degrees
129          */
130         setUpperLimitAngle:function (angle) {
131             this.limits[1] = R.math.Math2D.degToRad(angle);
132         },
133 
134         /**
135          * Get the lower limiting angle, in degrees, through which the joint can rotate.
136          * @return {Number} The angle, or <code>undefined</code>
137          */
138         getLowerLimitAngle:function () {
139             return this.limits.length != 0 ? R.math.Math2D.radToDeg(this.limits[0]) : undefined;
140         },
141 
142         /**
143          * Set the upper limiting angle through which the joint can rotate.  Zero is the
144          * "top" of the rotation, with rotation moving positively in a counter-clockwise
145          * rotation.  Negative numbers will move the rotation clockwise.
146          *
147          * @param angle {Number} An angle in degrees
148          */
149         setLowerLimitAngle:function (angle) {
150             this.limits[0] = R.math.Math2D.degToRad(angle);
151         },
152 
153         /**
154          * During simulation, this returns the current angle of the joint
155          * in degrees.  Outside of simulation it will always return zero.
156          * @return {Number}
157          */
158         getJointAngle:function () {
159             if (this.simulation) {
160                 return R.math.Math2D.radToDeg(this.getJoint().GetJointAngle());
161             } else {
162                 return 0;
163             }
164         }
165 
166     }, { /** @scope R.components.physics.RevoluteJoint.prototype */
167 
168         /**
169          * Get the class name of this object
170          *
171          * @return {String} "R.components.physics.RevoluteJoint"
172          */
173         getClassName:function () {
174             return "R.components.physics.RevoluteJoint";
175         }
176     });
177 };