1 /******************************************************************************* 2 * Copyright (c) 2013, Daniel Murphy 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 17 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 21 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 22 * POSSIBILITY OF SUCH DAMAGE. 23 ******************************************************************************/ 24 package org.jbox2d.dynamics.joints; 25 26 import org.jbox2d.common.Vec2; 27 import org.jbox2d.dynamics.Body; 28 import org.jbox2d.dynamics.SolverData; 29 import org.jbox2d.dynamics.World; 30 import org.jbox2d.pooling.IWorldPool; 31 32 // updated to rev 100 33 /** 34 * The base joint class. Joints are used to constrain two bodies together in various fashions. Some 35 * joints also feature limits and motors. 36 * 37 * @author Daniel Murphy 38 */ 39 public abstract class Joint { 40 41 public static Joint create(World world, JointDef def) { 42 // Joint joint = null; 43 switch (def.type) { 44 case MOUSE: 45 return new MouseJoint(world.getPool(), (MouseJointDef) def); 46 case DISTANCE: 47 return new DistanceJoint(world.getPool(), (DistanceJointDef) def); 48 case PRISMATIC: 49 return new PrismaticJoint(world.getPool(), (PrismaticJointDef) def); 50 case REVOLUTE: 51 return new RevoluteJoint(world.getPool(), (RevoluteJointDef) def); 52 case WELD: 53 return new WeldJoint(world.getPool(), (WeldJointDef) def); 54 case FRICTION: 55 return new FrictionJoint(world.getPool(), (FrictionJointDef) def); 56 case WHEEL: 57 return new WheelJoint(world.getPool(), (WheelJointDef) def); 58 case GEAR: 59 return new GearJoint(world.getPool(), (GearJointDef) def); 60 case PULLEY: 61 return new PulleyJoint(world.getPool(), (PulleyJointDef) def); 62 case CONSTANT_VOLUME: 63 return new ConstantVolumeJoint(world, (ConstantVolumeJointDef) def); 64 case ROPE: 65 return new RopeJoint(world.getPool(), (RopeJointDef) def); 66 case MOTOR: 67 return new MotorJoint(world.getPool(), (MotorJointDef) def); 68 case UNKNOWN: 69 default: 70 return null; 71 } 72 } 73 74 public static void destroy(Joint joint) { 75 joint.destructor(); 76 } 77 78 private final JointType m_type; 79 public Joint m_prev; 80 public Joint m_next; 81 public JointEdge m_edgeA; 82 public JointEdge m_edgeB; 83 protected Body m_bodyA; 84 protected Body m_bodyB; 85 86 public boolean m_islandFlag; 87 private boolean m_collideConnected; 88 89 public Object m_userData; 90 91 protected IWorldPool pool; 92 93 // Cache here per time step to reduce cache misses. 94 // final Vec2 m_localCenterA, m_localCenterB; 95 // float m_invMassA, m_invIA; 96 // float m_invMassB, m_invIB; 97 98 protected Joint(IWorldPool worldPool, JointDef def) { 99 assert (def.bodyA != def.bodyB); 100 101 pool = worldPool; 102 m_type = def.type; 103 m_prev = null; 104 m_next = null; 105 m_bodyA = def.bodyA; 106 m_bodyB = def.bodyB; 107 m_collideConnected = def.collideConnected; 108 m_islandFlag = false; 109 m_userData = def.userData; 110 111 m_edgeA = new JointEdge(); 112 m_edgeA.joint = null; 113 m_edgeA.other = null; 114 m_edgeA.prev = null; 115 m_edgeA.next = null; 116 117 m_edgeB = new JointEdge(); 118 m_edgeB.joint = null; 119 m_edgeB.other = null; 120 m_edgeB.prev = null; 121 m_edgeB.next = null; 122 123 // m_localCenterA = new Vec2(); 124 // m_localCenterB = new Vec2(); 125 } 126 127 /** 128 * get the type of the concrete joint. 129 * 130 * @return 131 */ 132 public JointType getType() { 133 return m_type; 134 } 135 136 /** 137 * get the first body attached to this joint. 138 */ 139 public final Body getBodyA() { 140 return m_bodyA; 141 } 142 143 /** 144 * get the second body attached to this joint. 145 * 146 * @return 147 */ 148 public final Body getBodyB() { 149 return m_bodyB; 150 } 151 152 /** 153 * get the anchor point on bodyA in world coordinates. 154 * 155 * @return 156 */ 157 public abstract void getAnchorA(Vec2 out); 158 159 /** 160 * get the anchor point on bodyB in world coordinates. 161 * 162 * @return 163 */ 164 public abstract void getAnchorB(Vec2 out); 165 166 /** 167 * get the reaction force on body2 at the joint anchor in Newtons. 168 * 169 * @param inv_dt 170 * @return 171 */ 172 public abstract void getReactionForce(float inv_dt, Vec2 out); 173 174 /** 175 * get the reaction torque on body2 in N*m. 176 * 177 * @param inv_dt 178 * @return 179 */ 180 public abstract float getReactionTorque(float inv_dt); 181 182 /** 183 * get the next joint the world joint list. 184 */ 185 public Joint getNext() { 186 return m_next; 187 } 188 189 /** 190 * get the user data pointer. 191 */ 192 public Object getUserData() { 193 return m_userData; 194 } 195 196 /** 197 * Set the user data pointer. 198 */ 199 public void setUserData(Object data) { 200 m_userData = data; 201 } 202 203 /** 204 * Get collide connected. Note: modifying the collide connect flag won't work correctly because 205 * the flag is only checked when fixture AABBs begin to overlap. 206 */ 207 public final boolean getCollideConnected() { 208 return m_collideConnected; 209 } 210 211 /** 212 * Short-cut function to determine if either body is inactive. 213 * 214 * @return 215 */ 216 public boolean isActive() { 217 return m_bodyA.isActive() && m_bodyB.isActive(); 218 } 219 220 /** Internal */ 221 public abstract void initVelocityConstraints(SolverData data); 222 223 /** Internal */ 224 public abstract void solveVelocityConstraints(SolverData data); 225 226 /** 227 * This returns true if the position errors are within tolerance. Internal. 228 */ 229 public abstract boolean solvePositionConstraints(SolverData data); 230 231 /** 232 * Override to handle destruction of joint 233 */ 234 public void destructor() {} 235 } 236