Package org.jbox2d.collision

Source Code of org.jbox2d.collision.Collision$EdgeResults

/*******************************************************************************
* Copyright (c) 2011, Daniel Murphy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the <organization> nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL DANIEL MURPHY BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package org.jbox2d.collision;

import org.jbox2d.collision.Distance.SimplexCache;
import org.jbox2d.collision.Manifold.ManifoldType;
import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.collision.shapes.Shape;
import org.jbox2d.common.Mat22;
import org.jbox2d.common.MathUtils;
import org.jbox2d.common.Settings;
import org.jbox2d.common.Transform;
import org.jbox2d.common.Vec2;
import org.jbox2d.pooling.IWorldPool;

// updated to rev 100
/**
* Functions used for computing contact points, distance
* queries, and TOI queries. Collision methods are non-static for pooling speed,
* retrieve a collision object from the {@link SingletonPool}.
* Should not be constructed.
*
* @author Daniel Murphy
*/
public class Collision {
  public static final int NULL_FEATURE = Integer.MAX_VALUE;
 
  private final IWorldPool pool;
 
  public Collision(IWorldPool argPool) {
    incidentEdge[0] = new ClipVertex();
    incidentEdge[1] = new ClipVertex();
    clipPoints1[0] = new ClipVertex();
    clipPoints1[1] = new ClipVertex();
    clipPoints2[0] = new ClipVertex();
    clipPoints2[1] = new ClipVertex();
    pool = argPool;
  }
 
  private final DistanceInput input = new DistanceInput();
  private final SimplexCache cache = new SimplexCache();
  private final DistanceOutput output = new DistanceOutput();
 
  /**
   * Determine if two generic shapes overlap.
   *
   * @param shapeA
   * @param shapeB
   * @param xfA
   * @param xfB
   * @return
   */
  public final boolean testOverlap(Shape shapeA, Shape shapeB, Transform xfA, Transform xfB) {
    input.proxyA.set(shapeA);
    input.proxyB.set(shapeB);
    input.transformA.set(xfA);
    input.transformB.set(xfB);
    input.useRadii = true;
   
    cache.count = 0;
   
    pool.getDistance().distance(output, cache, input);
    // djm note: anything significant about 10.0f?
    return output.distance < 10.0f * Settings.EPSILON;
  }
 
  /**
   * Compute the point states given two manifolds. The states pertain to the transition
   * from manifold1
   * to manifold2. So state1 is either persist or remove while state2 is either add or
   * persist.
   *
   * @param state1
   * @param state2
   * @param manifold1
   * @param manifold2
   */
  public static final void getPointStates(final PointState[] state1, final PointState[] state2,
      final Manifold manifold1, final Manifold manifold2) {
   
    for (int i = 0; i < Settings.maxManifoldPoints; i++) {
      state1[i] = PointState.NULL_STATE;
      state2[i] = PointState.NULL_STATE;
    }
   
    // Detect persists and removes.
    for (int i = 0; i < manifold1.pointCount; i++) {
      ContactID id = manifold1.points[i].id;
     
      state1[i] = PointState.REMOVE_STATE;
     
      for (int j = 0; j < manifold2.pointCount; j++) {
        if (manifold2.points[j].id.isEqual(id)) {
          state1[i] = PointState.PERSIST_STATE;
          break;
        }
      }
    }
   
    // Detect persists and adds
    for (int i = 0; i < manifold2.pointCount; i++) {
      ContactID id = manifold2.points[i].id;
     
      state2[i] = PointState.ADD_STATE;
     
      for (int j = 0; j < manifold1.pointCount; j++) {
        if (manifold1.points[j].id.isEqual(id)) {
          state2[i] = PointState.PERSIST_STATE;
          break;
        }
      }
    }
  }
 
  /**
   * 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;
  }
 
  // #### COLLISION STUFF (not from collision.h or collision.cpp) ####
 
  // djm pooling
  private final Vec2 d = new Vec2();
  private final Vec2 pA = new Vec2();
  private final Vec2 pB = new Vec2();
 
  /**
   * 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();
  }
 
  // djm pooling, and from above
  private final Vec2 c = new Vec2();
  private final Vec2 cLocal = new Vec2();
  private final Vec2 temp = new Vec2();
  private final Vec2 temp2 = new Vec2();
 
  /**
   * Compute the collision manifold between a polygon and a circle.
   *
   * @param manifold
   * @param polygon
   * @param xfA
   * @param circle
   * @param xfB
   */
  public final void collidePolygonAndCircle(Manifold manifold, final PolygonShape polygon, final Transform xfA,
      final CircleShape circle, final Transform xfB) {
    manifold.pointCount = 0;
   
    // Compute circle position in the frame of the polygon.
    Transform.mulToOut(xfB, circle.m_p, c);
    Transform.mulTransToOut(xfA, c, cLocal);
   
    // Find the min separating edge.
    int normalIndex = 0;
    float separation = Float.MIN_VALUE;
    float radius = polygon.m_radius + circle.m_radius;
    int vertexCount = polygon.m_vertexCount;
   
    Vec2[] vertices = polygon.m_vertices;
    Vec2[] normals = polygon.m_normals;
   
    for (int i = 0; i < vertexCount; i++) {
      temp.set(cLocal).subLocal(vertices[i]);
      float s = Vec2.dot(normals[i], temp);
     
      if (s > radius) {
        // early out
        return;
      }
     
      if (s > separation) {
        separation = s;
        normalIndex = i;
      }
    }
   
    // Vertices that subtend the incident face.
    int vertIndex1 = normalIndex;
    int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
    Vec2 v1 = vertices[vertIndex1];
    Vec2 v2 = vertices[vertIndex2];
   
    // If the center is inside the polygon ...
    if (separation < Settings.EPSILON) {
      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(normals[normalIndex]);
      manifold.localPoint.set(v1).addLocal(v2).mulLocal(.5f);
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
      return;
    }
   
    // Compute barycentric coordinates
    temp.set(cLocal).subLocal(v1);
    temp2.set(v2).subLocal(v1);
    float u1 = Vec2.dot(temp, temp2);
    temp.set(cLocal).subLocal(v2);
    temp2.set(v1).subLocal(v2);
    float u2 = Vec2.dot(temp, temp2);
   
    if (u1 <= 0f) {
      if (MathUtils.distanceSquared(cLocal, v1) > radius * radius) {
        return;
      }
     
      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(cLocal).subLocal(v1);
      manifold.localNormal.normalize();
      manifold.localPoint.set(v1);
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
    }
    else if (u2 <= 0.0f) {
      if (MathUtils.distanceSquared(cLocal, v2) > radius * radius) {
        return;
      }
     
      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(cLocal).subLocal(v2);
      manifold.localNormal.normalize();
      manifold.localPoint.set(v2);
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
    }
    else {
      // Vec2 faceCenter = 0.5f * (v1 + v2);
      // (temp is faceCenter)
      temp.set(v1).addLocal(v2).mulLocal(.5f);
     
      temp2.set(cLocal).subLocal(temp);
      separation = Vec2.dot(temp2, normals[vertIndex1]);
      if (separation > radius) {
        return;
      }
     
      manifold.pointCount = 1;
      manifold.type = ManifoldType.FACE_A;
      manifold.localNormal.set(normals[vertIndex1]);
      manifold.localPoint.set(temp); // (faceCenter)
      manifold.points[0].localPoint.set(circle.m_p);
      manifold.points[0].id.zero();
    }
  }
 
  // djm pooling
  private final Vec2 normal1World = new Vec2();
  private final Vec2 normal1 = new Vec2();
  private final Vec2 v1 = new Vec2();
  private final Vec2 v2 = new Vec2();
 
  /**
   * 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;
  }
 
  // djm pooling, and from above
  private final Vec2 dLocal1 = new Vec2();
 
  /**
   * Find the max separation between poly1 and poly2 using edge normals from poly1.
   *
   * @param edgeIndex
   * @param poly1
   * @param xf1
   * @param poly2
   * @param xf2
   * @return
   */
  public final void findMaxSeparation(EdgeResults results, final PolygonShape poly1, final Transform xf1,
      final PolygonShape poly2, final Transform xf2) {
    int count1 = poly1.m_vertexCount;
    final Vec2[] normals1 = poly1.m_normals;
   
    // Vector pointing from the centroid of poly1 to the centroid of poly2.
    Transform.mulToOut(xf2, poly2.m_centroid, d);
    Transform.mulToOut(xf1, poly1.m_centroid, temp);
    d.subLocal(temp);
   
    Mat22.mulTransToOut(xf1.R, d, dLocal1);
   
    // Find edge normal on poly1 that has the largest projection onto d.
    int edge = 0;
    float dot;
    float maxDot = Float.MIN_VALUE;
    for (int i = 0; i < count1; i++) {
      dot = Vec2.dot(normals1[i], dLocal1);
      if (dot > maxDot) {
        maxDot = dot;
        edge = i;
      }
    }
   
    // Get the separation for the edge normal.
    float s = edgeSeparation(poly1, xf1, edge, poly2, xf2);
   
    // Check the separation for the previous edge normal.
    int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
    float sPrev = edgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
   
    // Check the separation for the next edge normal.
    int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
    float sNext = edgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
   
    // Find the best edge and the search direction.
    int bestEdge;
    float bestSeparation;
    int increment;
    if (sPrev > s && sPrev > sNext) {
      increment = -1;
      bestEdge = prevEdge;
      bestSeparation = sPrev;
    }
    else if (sNext > s) {
      increment = 1;
      bestEdge = nextEdge;
      bestSeparation = sNext;
    }
    else {
      results.edgeIndex = edge;
      results.separation = s;
      return;
    }
   
    // Perform a local search for the best edge normal.
    for (;;) {
      if (increment == -1) {
        edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
      }
      else {
        edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
      }
     
      s = edgeSeparation(poly1, xf1, edge, poly2, xf2);
     
      if (s > bestSeparation) {
        bestEdge = edge;
        bestSeparation = s;
      }
      else {
        break;
      }
    }
   
    results.edgeIndex = bestEdge;
    results.separation = bestSeparation;
  }
 
  // djm pooling from above
  public final void findIncidentEdge(final ClipVertex[] c, final PolygonShape poly1, final Transform xf1, int edge1,
      final PolygonShape poly2, final Transform xf2) {
    int count1 = poly1.m_vertexCount;
    final Vec2[] normals1 = poly1.m_normals;
   
    int count2 = poly2.m_vertexCount;
    final Vec2[] vertices2 = poly2.m_vertices;
    final Vec2[] normals2 = poly2.m_normals;
   
    assert (0 <= edge1 && edge1 < count1);
   
    // Get the normal of the reference edge in poly2's frame.
    Mat22.mulToOut(xf1.R, normals1[edge1], normal1); // temporary
    // b2Vec2 normal1 = b2MulT(xf2.R, b2Mul(xf1.R, normals1[edge1]));
    Mat22.mulTransToOut(xf2.R, normal1, normal1);
   
    // Find the incident edge on poly2.
    int index = 0;
    float minDot = Float.MAX_VALUE;
    for (int i = 0; i < count2; ++i) {
      float dot = Vec2.dot(normal1, normals2[i]);
      if (dot < minDot) {
        minDot = dot;
        index = i;
      }
    }
   
    // Build the clip vertices for the incident edge.
    int i1 = index;
    int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
   
    Transform.mulToOut(xf2, vertices2[i1], c[0].v); // = Mul(xf2, vertices2[i1]);
    c[0].id.features.referenceEdge = edge1;
    c[0].id.features.incidentEdge = i1;
    c[0].id.features.incidentVertex = 0;
   
    Transform.mulToOut(xf2, vertices2[i2], c[1].v); // = Mul(xf2, vertices2[i2]);
    c[1].id.features.referenceEdge = edge1;
    c[1].id.features.incidentEdge = i2;
    c[1].id.features.incidentVertex = 1;
  }
 
  private final EdgeResults results1 = new EdgeResults();
  private final EdgeResults results2 = new EdgeResults();
  private final ClipVertex[] incidentEdge = new ClipVertex[2];
  private final Vec2 localTangent = new Vec2();
  private final Vec2 localNormal = new Vec2();
  private final Vec2 planePoint = new Vec2();
  private final Vec2 tangent = new Vec2();
  private final Vec2 normal = new Vec2();
  private final Vec2 v11 = new Vec2();
  private final Vec2 v12 = new Vec2();
  private final ClipVertex[] clipPoints1 = new ClipVertex[2];
  private final ClipVertex[] clipPoints2 = new ClipVertex[2];
 
  /**
   * Compute the collision manifold between two polygons.
   *
   * @param manifold
   * @param polygon1
   * @param xf1
   * @param polygon2
   * @param xf2
   */
  public final void collidePolygons(Manifold manifold, final PolygonShape polyA, final Transform xfA,
      final PolygonShape polyB, final Transform xfB) {
    // Find edge normal of max separation on A - return if separating axis is found
    // Find edge normal of max separation on B - return if separation axis is found
    // Choose reference edge as min(minA, minB)
    // Find incident edge
    // Clip
   
    // The normal points from 1 to 2
   
    manifold.pointCount = 0;
    float totalRadius = polyA.m_radius + polyB.m_radius;
   
    findMaxSeparation(results1, polyA, xfA, polyB, xfB);
    if (results1.separation > totalRadius) {
      return;
    }
   
    findMaxSeparation(results2, polyB, xfB, polyA, xfA);
    if (results2.separation > totalRadius) {
      return;
    }
   
    final PolygonShape poly1; // reference polygon
    final PolygonShape poly2; // incident polygon
    Transform xf1, xf2;
    int edge1; // reference edge
    int flip;
    final float k_relativeTol = 0.98f;
    final float k_absoluteTol = 0.001f;
   
    if (results2.separation > k_relativeTol * results1.separation + k_absoluteTol) {
      poly1 = polyB;
      poly2 = polyA;
      xf1 = xfB;
      xf2 = xfA;
      edge1 = results2.edgeIndex;
      manifold.type = ManifoldType.FACE_B;
      flip = 1;
    }
    else {
      poly1 = polyA;
      poly2 = polyB;
      xf1 = xfA;
      xf2 = xfB;
      edge1 = results1.edgeIndex;
      manifold.type = ManifoldType.FACE_A;
      flip = 0;
    }
   
    findIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
   
    int count1 = poly1.m_vertexCount;
    final Vec2[] vertices1 = poly1.m_vertices;
   
    v11.set(vertices1[edge1]);
    v12.set(edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0]);
   
    localTangent.set(v12).subLocal(v11);
    localTangent.normalize();
   
    Vec2.crossToOut(localTangent, 1f, localNormal); // Vec2 localNormal = Cross(dv,
                            // 1.0f);
   
    planePoint.set(v11).addLocal(v12).mulLocal(.5f); // Vec2 planePoint = 0.5f * (v11
                              // + v12);
   
    Mat22.mulToOut(xf1.R, localTangent, tangent); // Vec2 sideNormal = Mul(xf1.R, v12
                            // - v11);
    Vec2.crossToOut(tangent, 1f, normal); // Vec2 frontNormal = Cross(sideNormal,
                        // 1.0f);
   
    Transform.mulToOut(xf1, v11, v11);
    Transform.mulToOut(xf1, v12, v12);
    // v11 = Mul(xf1, v11);
    // v12 = Mul(xf1, v12);
   
    // Face offset
    float frontOffset = Vec2.dot(normal, v11);
   
    // Side offsets, extended by polytope skin thickness.
    float sideOffset1 = -Vec2.dot(tangent, v11) + totalRadius;
    float sideOffset2 = Vec2.dot(tangent, v12) + totalRadius;
   
    // Clip incident edge against extruded edge1 side edges.
    // ClipVertex clipPoints1[2];
    // ClipVertex clipPoints2[2];
    int np;
   
    // Clip to box side 1
    // np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
    tangent.negateLocal();
    np = clipSegmentToLine(clipPoints1, incidentEdge, tangent, sideOffset1);
    tangent.negateLocal();
   
    if (np < 2) {
      return;
    }
   
    // Clip to negative box side 1
    np = clipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2);
   
    if (np < 2) {
      return;
    }
   
    // Now clipPoints2 contains the clipped points.
    manifold.localNormal.set(localNormal);
    manifold.localPoint.set(planePoint);
   
    int pointCount = 0;
    for (int i = 0; i < Settings.maxManifoldPoints; ++i) {
      float separation = Vec2.dot(normal, clipPoints2[i].v) - frontOffset;
     
      if (separation <= totalRadius) {
        ManifoldPoint cp = manifold.points[pointCount];
        Transform.mulTransToOut(xf2, clipPoints2[i].v, cp.localPoint);
        // cp.m_localPoint = MulT(xf2, clipPoints2[i].v);
        cp.id.set(clipPoints2[i].id);
        cp.id.features.flip = flip;
        ++pointCount;
      }
    }
   
    manifold.pointCount = pointCount;
  }
 
  /**
   * Java-specific class for returning edge results
   */
  private static class EdgeResults {
    public float separation;
    public int edgeIndex;
  }
 
  /**
   * Used for computing contact manifolds.
   */
  public static class ClipVertex{
    public final Vec2 v;
    public final ContactID id;

    public ClipVertex(){
      v = new Vec2();
      id = new ContactID();
    }

    public void set(final ClipVertex cv){
      v.set(cv.v);
      id.set(cv.id);
    }
  }
 
  /**
   * This is used for determining the state of contact points.
   * @author Daniel Murphy
   */
  public static enum PointState {
    /**
     * point does not exist
     */
    NULL_STATE,
    /**
     * point was added in the update
     */
    ADD_STATE,
    /**
     * point persisted across the update
     */
    PERSIST_STATE,
    /**
     * point was removed in the update
     */
    REMOVE_STATE
  }

TOP

Related Classes of org.jbox2d.collision.Collision$EdgeResults

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.