@Override public final void computeAABB(final AABB aabb, final Transform xf, int childIndex) { final Vec2 v = pool1; final Vec2 lower = aabb.lowerBound; final Vec2 upper = aabb.upperBound; final Vec2 v1 = m_vertices[0]; lower.x = (xf.q.c * v1.x - xf.q.s * v1.y) + xf.p.x; lower.y = (xf.q.s * v1.x + xf.q.c * v1.y) + xf.p.y; upper.set(lower); for (int i = 1; i < m_count; ++i) { Vec2 v2 = m_vertices[i]; v.x = (xf.q.c * v2.x - xf.q.s * v2.y) + xf.p.x; v.y = (xf.q.s * v2.x + xf.q.c * v2.y) + xf.p.y; // Vec2 v = Mul(xf, m_vertices[i]); Vec2.minToOut(lower, v, lower); Vec2.maxToOut(upper, v, upper); } // Vec2 r(m_radius, m_radius); // aabb.lowerBound = lower - r; // aabb.upperBound = upper + r; aabb.lowerBound.x -= m_radius; aabb.lowerBound.y -= m_radius; aabb.upperBound.x += m_radius; aabb.upperBound.y += m_radius; }
void playerControl(LudumDare26Game.ControlsState controlsState) { boolean doStop = !(controlsState.leftPressed || controlsState.rightPressed); final Body body = getBody(); float linearDamping = 0; if (doStop) { body.setAngularVelocity(0); // linearDamping = 10f; Vec2 linearVelocity = body.getLinearVelocity(); linearVelocity.x *= 0.9; // body.applyForce(new Vec2(v, 0), body.getPosition()); body.setLinearVelocity(linearVelocity); } else { Vec2 linearVelocity = body.getLinearVelocity(); final int dir = (controlsState.leftPressed ? -1 : 0) + (controlsState.rightPressed ? 1 : 0); float v = linearVelocity.x; v += dir * MOVE_ACC; v = Math.max(-MOVE_SPEED, Math.min(v, MOVE_SPEED)); linearVelocity.x = v; // body.applyForce(new Vec2(v, 0), body.getPosition()); body.setLinearVelocity(linearVelocity); // linearDamping = 1f; } body.setLinearDamping(linearDamping); }
public void setPrevEdge( final EdgeShape edge, final Vec2 core, final Vec2 cornerDir, final boolean convex) { m_prevEdge = edge; m_coreV1.set(core); m_cornerDir1.set(cornerDir); m_cornerConvex1 = convex; }
/** * Clipping for contact manifolds. Sutherland-Hodgman clipping. * * @param vOut * @param vIn * @param normal * @param offset * @return */ public static final int clipSegmentToLine( final ClipVertex[] vOut, final ClipVertex[] vIn, final Vec2 normal, float offset) { // Start with no output points int numOut = 0; // Calculate the distance of end points to the line float distance0 = Vec2.dot(normal, vIn[0].v) - offset; float distance1 = Vec2.dot(normal, vIn[1].v) - offset; // If the points are behind the plane if (distance0 <= 0.0f) { vOut[numOut++].set(vIn[0]); } if (distance1 <= 0.0f) { vOut[numOut++].set(vIn[1]); } // If the points are on different sides of the plane if (distance0 * distance1 < 0.0f) { // Find intersection point of edge and plane float interp = distance0 / (distance0 - distance1); // vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v); vOut[numOut].v.set(vIn[1].v).subLocal(vIn[0].v).mulLocal(interp).addLocal(vIn[0].v); if (distance0 > 0.0f) { vOut[numOut].id.set(vIn[0].id); } else { vOut[numOut].id.set(vIn[1].id); } ++numOut; } return numOut; }
/** * Internal method * * @param broadPhase * @param xf1 * @param xf2 */ protected void synchronize( BroadPhase broadPhase, final Transform transform1, final Transform transform2) { if (m_proxyCount == 0) { return; } for (int i = 0; i < m_proxyCount; ++i) { FixtureProxy proxy = m_proxies[i]; // Compute an AABB that covers the swept shape (may miss some rotation effect). final AABB aabb1 = pool1; final AABB aab = pool2; m_shape.computeAABB(aabb1, transform1, proxy.childIndex); m_shape.computeAABB(aab, transform2, proxy.childIndex); proxy.aabb.lowerBound.x = aabb1.lowerBound.x < aab.lowerBound.x ? aabb1.lowerBound.x : aab.lowerBound.x; proxy.aabb.lowerBound.y = aabb1.lowerBound.y < aab.lowerBound.y ? aabb1.lowerBound.y : aab.lowerBound.y; proxy.aabb.upperBound.x = aabb1.upperBound.x > aab.upperBound.x ? aabb1.upperBound.x : aab.upperBound.x; proxy.aabb.upperBound.y = aabb1.upperBound.y > aab.upperBound.y ? aabb1.upperBound.y : aab.upperBound.y; displacement.x = transform2.p.x - transform1.p.x; displacement.y = transform2.p.y - transform1.p.y; broadPhase.moveProxy(proxy.proxyId, proxy.aabb, displacement); } }
/** * Compute the collision manifold between two circles. * * @param manifold * @param circle1 * @param xfA * @param circle2 * @param xfB */ public final void collideCircles( Manifold manifold, final CircleShape circle1, final Transform xfA, final CircleShape circle2, final Transform xfB) { manifold.pointCount = 0; Transform.mulToOut(xfA, circle1.m_p, pA); Transform.mulToOut(xfB, circle2.m_p, pB); d.set(pB).subLocal(pA); float distSqr = Vec2.dot(d, d); float radius = circle1.m_radius + circle2.m_radius; if (distSqr > radius * radius) { return; } manifold.type = ManifoldType.CIRCLES; manifold.localPoint.set(circle1.m_p); manifold.localNormal.setZero(); manifold.pointCount = 1; manifold.points[0].localPoint.set(circle2.m_p); manifold.points[0].id.zero(); }
public void jump() { Vec2 linearVelocity = getBody().getLinearVelocity(); linearVelocity.y = JUMP_SPEED; getBody().setLinearVelocity(linearVelocity); SOUND_JUMP.play(); }
/** * Set the linear velocity of this body * * @param xVelocity The x component of the velocity * @param yVelocity The y component of the velocity */ public void setVelocity(float xVelocity, float yVelocity) { checkBody(); Vec2 vel = jboxBody.getLinearVelocity(); vel.x = xVelocity; vel.y = yVelocity; jboxBody.setLinearVelocity(vel); }
/** @see SupportsGenericDistance#support(Vec2, XForm, Vec2) */ public void support(final Vec2 dest, final XForm xf, final Vec2 d) { final Vec2 supportV1 = tlSupportV1.get(); final Vec2 supportV2 = tlSupportV2.get(); XForm.mulToOut(xf, m_coreV1, supportV1); XForm.mulToOut(xf, m_coreV2, supportV2); dest.set(Vec2.dot(supportV1, d) > Vec2.dot(supportV2, d) ? supportV1 : supportV2); }
public void setNextEdge( final EdgeShape edge, final Vec2 core, final Vec2 cornerDir, final boolean convex) { // djm note: the vec2s are probably pooled, don't use them m_nextEdge = edge; m_coreV2.set(core); m_cornerDir2.set(cornerDir); m_cornerConvex2 = convex; }
/** * Apply force to the center of the planetoid * * @param force */ public void applyThrust(Vec2 force) { force = force.mul(1 / Globals.PHYS_RATIO); // Nasty hack to change player speed if (this.forceFactor > 0) { force = force.mulLocal(this.forceFactor); } this.getBody().applyForce(force, this.getBody().getWorldCenter()); }
/** * Set the linear velocity of the center of mass. * * @param v the new linear velocity of the center of mass. */ public final void setLinearVelocity(Vec2 v) { if (m_type == BodyType.STATIC) { return; } if (Vec2.dot(v, v) > 0.0f) { setAwake(true); } m_linearVelocity.set(v); }
/** * Set this as a single edge. * * @param v1 * @param v2 * @deprecated */ public final void setAsEdge(final Vec2 v1, final Vec2 v2) { m_count = 2; m_vertices[0].set(v1); m_vertices[1].set(v2); m_centroid.set(v1).addLocal(v2).mulLocal(0.5f); // = 0.5f * (v1 + v2); m_normals[0].set(v2).subLocal(v1); Vec2.crossToOut(m_normals[0], 1f, m_normals[0]); // m_normals[0] = Cross(v2 - v1, 1.0f); m_normals[0].normalize(); m_normals[1].set(m_normals[0]).negateLocal(); }
/** @see Shape#computeAABB(AABB, XForm) */ @Override public void computeAABB(final AABB aabb, final XForm transform) { /*Vec2 v1 = XForm.mul(transform, m_v1); Vec2 v2 = XForm.mul(transform, m_v2); aabb.lowerBound = Vec2.min(v1, v2); aabb.upperBound = Vec2.max(v1, v2);*/ // djm we avoid one creation. crafty huh? XForm.mulToOut(transform, m_v1, aabb.lowerBound); final Vec2 v2 = tlV2.get(); XForm.mulToOut(transform, m_v2, v2); Vec2.maxToOut(aabb.lowerBound, v2, aabb.upperBound); Vec2.minToOut(aabb.lowerBound, v2, aabb.lowerBound); }
/** * Set the sleep state of the body. A sleeping body has very low CPU cost. * * @param flag set to true to put body to sleep, false to wake it. * @param flag */ public void setAwake(boolean flag) { if (flag) { if ((m_flags & e_awakeFlag) == 0) { m_flags |= e_awakeFlag; m_sleepTime = 0.0f; } } else { m_flags &= ~e_awakeFlag; m_sleepTime = 0.0f; m_linearVelocity.setZero(); m_angularVelocity = 0.0f; m_force.setZero(); m_torque = 0.0f; } }
public Vec2 getProjectileSpawnPoint() { // TODO move to an interface like IProjectileParent or something mProjectileSpawnPoint.set( mPhysics.getX() + 3, mPhysics.getY()); // TODO change arguments to mPhysics.getProjectileSpawn return mProjectileSpawnPoint; }
protected RevoluteJoint(IWorldPool argWorld, RevoluteJointDef def) { super(argWorld, def); m_localAnchorA.set(def.localAnchorA); m_localAnchorB.set(def.localAnchorB); m_referenceAngle = def.referenceAngle; m_motorImpulse = 0; m_lowerAngle = def.lowerAngle; m_upperAngle = def.upperAngle; m_maxMotorTorque = def.maxMotorTorque; m_motorSpeed = def.motorSpeed; m_enableLimit = def.enableLimit; m_enableMotor = def.enableMotor; m_limitState = LimitState.INACTIVE; }
public boolean inRange(AABB aabb) { Vec2 d = Vec2.max( aabb.lowerBound.sub(m_worldAABB.upperBound), m_worldAABB.lowerBound.sub(aabb.upperBound)); return (Math.max(d.x, d.y) < 0.0f); }
/** * Construct a world object. * * @param gravity the world gravity vector. * @param doSleep improve performance by not simulating inactive bodies. */ public World(Vec2 gravity, IWorldPool argPool) { pool = argPool; m_destructionListener = null; m_debugDraw = null; m_bodyList = null; m_jointList = null; m_bodyCount = 0; m_jointCount = 0; m_warmStarting = true; m_continuousPhysics = true; m_subStepping = false; m_stepComplete = true; m_allowSleep = true; m_gravity.set(gravity); m_flags = CLEAR_FORCES; m_inv_dt0 = 0f; m_contactManager = new ContactManager(this); m_profile = new Profile(); initializeRegisters(); }
public float raycastCallback(RayCastInput input, int nodeId) { Object userData = broadPhase.getUserData(nodeId); FixtureProxy proxy = (FixtureProxy) userData; Fixture fixture = proxy.fixture; int index = proxy.childIndex; boolean hit = fixture.raycast(output, input, index); if (hit) { float fraction = output.fraction; // Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2; temp.set(input.p2).mulLocal(fraction); point.set(input.p1).mulLocal(1 - fraction).addLocal(temp); return callback.reportFixture(fixture, point, output.normal, fraction); } return input.maxFraction; }
@Override public final boolean moveProxy( int proxyId, final org.jbox2d.collision.AABB aabb, Vec2 displacement) { assert (aabb.isValid()); assert (0 <= proxyId && proxyId < m_nodeCapacity); final DynamicTreeNode node = m_nodes[proxyId]; assert (node.child1 == null); final org.jbox2d.collision.AABB nodeAABB = node.aabb; // if (nodeAABB.contains(aabb)) { if (nodeAABB.lowerBound.x <= aabb.lowerBound.x && nodeAABB.lowerBound.y <= aabb.lowerBound.y && aabb.upperBound.x <= nodeAABB.upperBound.x && aabb.upperBound.y <= nodeAABB.upperBound.y) { return false; } removeLeaf(node); // Extend AABB final Vec2 lowerBound = nodeAABB.lowerBound; final Vec2 upperBound = nodeAABB.upperBound; lowerBound.x = aabb.lowerBound.x - Settings.aabbExtension; lowerBound.y = aabb.lowerBound.y - Settings.aabbExtension; upperBound.x = aabb.upperBound.x + Settings.aabbExtension; upperBound.y = aabb.upperBound.y + Settings.aabbExtension; // Predict AABB displacement. final float dx = displacement.x * Settings.aabbMultiplier; final float dy = displacement.y * Settings.aabbMultiplier; if (dx < 0.0f) { lowerBound.x += dx; } else { upperBound.x += dx; } if (dy < 0.0f) { lowerBound.y += dy; } else { upperBound.y += dy; } insertLeaf(proxyId); return true; }
protected MouseJoint(IWorldPool argWorld, MouseJointDef def) { super(argWorld, def); assert (def.target.isValid()); assert (def.maxForce >= 0); assert (def.frequencyHz >= 0); assert (def.dampingRatio >= 0); m_target.set(def.target); Transform.mulTransToOut(m_bodyB.getTransform(), m_target, m_localAnchor); m_maxForce = def.maxForce; m_impulse.setZero(); m_frequencyHz = def.frequencyHz; m_dampingRatio = def.dampingRatio; m_beta = 0; m_gamma = 0; }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); view = new TestView(this); setContentView(view); // new World(new Vec2(0.0f, -10.0f), true); gravity = getPreferences(Context.MODE_PRIVATE).getInt(PREF_GRAVITY, GRAVITY_ACCELEROMETER); w = (PhysicsWorld) getLastNonConfigurationInstance(); if (w == null) { Vec2 grav = new Vec2(0.0f, 0.0f); if (gravity == GRAVITY_NORMAL) { grav.y = -10.0f; } else if (gravity == GRAVITY_MOON) { grav.y = -1.67f; } w = new PhysicsWorld(); w.create(grav); } view.setModel(w); if (savedInstanceState != null) { defaultLandscape = savedInstanceState.getBoolean(KEY_DEFAULT_LANDSCAPE); } else { defaultLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; rotation = getPreferences(Context.MODE_PRIVATE).getInt(PREF_ROTATION, Surface.ROTATION_0); int orientation; if (defaultLandscape && rotation == Surface.ROTATION_90 || !defaultLandscape && rotation == Surface.ROTATION_180) { orientation = 9; } else if (defaultLandscape && rotation == Surface.ROTATION_180 || !defaultLandscape && rotation == Surface.ROTATION_270) { orientation = 8; } else if (defaultLandscape && rotation == Surface.ROTATION_270 || !defaultLandscape && rotation == Surface.ROTATION_0) { orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; } else { orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } setRequestedOrientation(orientation); } }
/** * Apply a force at a world point. If the force is not applied at the center of mass, it will * generate a torque and affect the angular velocity. This wakes up the body. * * @param force the world force vector, usually in Newtons (N). * @param point the world position of the point of application. */ public final void applyForce(Vec2 force, Vec2 point) { if (m_type != BodyType.DYNAMIC) { return; } if (isAwake() == false) { setAwake(true); } // m_force.addLocal(force); // Vec2 temp = tltemp.get(); // temp.set(point).subLocal(m_sweep.c); // m_torque += Vec2.cross(temp, force); m_force.x += force.x; m_force.y += force.y; m_torque += (point.x - m_sweep.c.x) * force.y - (point.y - m_sweep.c.y) * force.x; }
public void step(float dt, int iterations) { if (joint != null) { Vec2 force = joint.getReactionForce(); float forceAngle = PhysicsUtils.angle(force); float forceMag = force.length(); if (forceMag > reactionThreshold) { /* * First, check for direction. */ if (angleLo == angleHi || (forceAngle >= angleLo && forceAngle <= angleHi)) { // Ok, this one's done with. Kill it. joint.getBody1().getWorld().destroyJoint(joint); joint = null; joint.getBody1().getWorld().unregisterPostStep(this); } } } }
/** * Get a direction vector from start point, within screens height and width * * @return */ public Vec2 getStartDirVec(float screenWidth, float screenHeight) { Vec2 start = this.getBody().getWorldCenter().mul(Globals.PHYS_RATIO); Vec2 dir = new Vec2(); // Find where the screen is, so Vec can go through it if (start.x <= -screenWidth) { dir.x = 1; } else if (start.x >= screenWidth) { dir.x = -1; } if (start.y <= -screenHeight) { dir.y = 1; } else if (start.y >= screenHeight) { dir.y = -1; } return dir; }
/** * Find the separation between poly1 and poly2 for a given edge normal on poly1. * * @param poly1 * @param xf1 * @param edge1 * @param poly2 * @param xf2 */ public final float edgeSeparation( final PolygonShape poly1, final Transform xf1, final int edge1, final PolygonShape poly2, final Transform xf2) { int count1 = poly1.m_vertexCount; final Vec2[] vertices1 = poly1.m_vertices; final Vec2[] normals1 = poly1.m_normals; int count2 = poly2.m_vertexCount; final Vec2[] vertices2 = poly2.m_vertices; assert (0 <= edge1 && edge1 < count1); // Convert normal from poly1's frame into poly2's frame. // Vec2 normal1World = Mul(xf1.R, normals1[edge1]); Mat22.mulToOut(xf1.R, normals1[edge1], normal1World); // Vec2 normal1 = MulT(xf2.R, normal1World); Mat22.mulTransToOut(xf2.R, normal1World, normal1); // Find support vertex on poly2 for -normal. int index = 0; float minDot = Float.MAX_VALUE; for (int i = 0; i < count2; ++i) { float dot = Vec2.dot(vertices2[i], normal1); if (dot < minDot) { minDot = dot; index = i; } } // Vec2 v1 = Mul(xf1, vertices1[edge1]); // Vec2 v2 = Mul(xf2, vertices2[index]); Transform.mulToOut(xf1, vertices1[edge1], v1); Transform.mulToOut(xf2, vertices2[index], v2); float separation = Vec2.dot(v2.subLocal(v1), normal1World); return separation; }
/** * Build vertices to represent an axis-aligned box. * * @param hx the half-width. * @param hy the half-height. */ public final void setAsBox(final float hx, final float hy) { m_count = 4; m_vertices[0].set(-hx, -hy); m_vertices[1].set(hx, -hy); m_vertices[2].set(hx, hy); m_vertices[3].set(-hx, hy); m_normals[0].set(0.0f, -1.0f); m_normals[1].set(1.0f, 0.0f); m_normals[2].set(0.0f, 1.0f); m_normals[3].set(-1.0f, 0.0f); m_centroid.setZero(); }
/** @see Shape#computeSweptAABB(AABB, XForm, XForm) */ @Override public void computeSweptAABB(final AABB aabb, final XForm transform1, final XForm transform2) { // djm this method is pretty hot (called every time step) final Vec2 sweptV1 = tlSwept1.get(); final Vec2 sweptV2 = tlSwept2.get(); final Vec2 sweptV3 = tlSwept3.get(); final Vec2 sweptV4 = tlSwept4.get(); XForm.mulToOut(transform1, m_v1, sweptV1); XForm.mulToOut(transform1, m_v2, sweptV2); XForm.mulToOut(transform2, m_v1, sweptV3); XForm.mulToOut(transform2, m_v2, sweptV4); // aabb.lowerBound = Vec2.min(Vec2.min(Vec2.min(v1, v2), v3), v4); // aabb.upperBound = Vec2.max(Vec2.max(Vec2.max(v1, v2), v3), v4); // djm ok here's the non object-creation-crazy way Vec2.minToOut(sweptV1, sweptV2, aabb.lowerBound); Vec2.minToOut(aabb.lowerBound, sweptV3, aabb.lowerBound); Vec2.minToOut(aabb.lowerBound, sweptV4, aabb.lowerBound); Vec2.maxToOut(sweptV1, sweptV2, aabb.upperBound); Vec2.maxToOut(aabb.upperBound, sweptV3, aabb.upperBound); Vec2.maxToOut(aabb.upperBound, sweptV4, aabb.upperBound); }
@Override public final boolean testPoint(final Transform xf, final Vec2 p) { final Vec2 pLocal = pool1; final Vec2 temp = pool2; pLocal.set(p).subLocal(xf.p); Rot.mulTransUnsafe(xf.q, pLocal, temp); pLocal.set(temp); if (m_debug) { System.out.println("--testPoint debug--"); System.out.println("Vertices: "); for (int i = 0; i < m_count; ++i) { System.out.println(m_vertices[i]); } System.out.println("pLocal: " + pLocal); } for (int i = 0; i < m_count; ++i) { temp.set(pLocal).subLocal(m_vertices[i]); final float dot = Vec2.dot(m_normals[i], temp); if (dot > 0.0f) { return false; } } return true; }