@Override
    public boolean needsCollision(BroadphaseProxy proxy0) {
      // don't collide with itself
      if (proxy0.clientObject == me) {
        return false;
      }

      // don't do CCD when the collision filters are not matching
      if (!super.needsCollision(proxy0)) {
        return false;
      }

      CollisionObject otherObj = (CollisionObject) proxy0.clientObject;

      // call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
      if (dispatcher.needsResponse(me, otherObj)) {
        // don't do CCD when there are already contact points (touching contact/penetration)
        ObjectArrayList<PersistentManifold> manifoldArray =
            new ObjectArrayList<PersistentManifold>();
        BroadphasePair collisionPair = pairCache.findPair(me.getBroadphaseHandle(), proxy0);
        if (collisionPair != null) {
          if (collisionPair.algorithm != null) {
            // manifoldArray.resize(0);
            collisionPair.algorithm.getAllContactManifolds(manifoldArray);
            for (int j = 0; j < manifoldArray.size(); j++) {
              PersistentManifold manifold = manifoldArray.getQuick(j);
              if (manifold.getNumContacts() > 0) {
                return false;
              }
            }
          }
        }
      }
      return true;
    }
  public void rayTest(
      Vector3f rayFromWorld, Vector3f rayToWorld, CollisionWorld.RayResultCallback resultCallback) {
    Transform rayFromTrans = new Transform();
    rayFromTrans.setIdentity();
    rayFromTrans.origin.set(rayFromWorld);
    Transform rayToTrans = new Transform();
    rayToTrans.setIdentity();
    rayToTrans.origin.set(rayToWorld);

    Transform tmpTrans = new Transform();

    for (int i = 0; i < overlappingObjects.size(); i++) {
      CollisionObject collisionObject = overlappingObjects.getQuick(i);

      // only perform raycast if filterMask matches
      if (resultCallback.needsCollision(collisionObject.getBroadphaseHandle())) {
        CollisionWorld.rayTestSingle(
            rayFromTrans,
            rayToTrans,
            collisionObject,
            collisionObject.getCollisionShape(),
            collisionObject.getWorldTransform(tmpTrans),
            resultCallback);
      }
    }
  }
  public void convexSweepTest(
      ConvexShape castShape,
      Transform convexFromWorld,
      Transform convexToWorld,
      CollisionWorld.ConvexResultCallback resultCallback,
      float allowedCcdPenetration) {
    Transform convexFromTrans = new Transform();
    Transform convexToTrans = new Transform();

    convexFromTrans.set(convexFromWorld);
    convexToTrans.set(convexToWorld);

    Vector3f castShapeAabbMin = new Vector3f();
    Vector3f castShapeAabbMax = new Vector3f();

    // compute AABB that encompasses angular movement
    {
      Vector3f linVel = new Vector3f();
      Vector3f angVel = new Vector3f();
      TransformUtil.calculateVelocity(convexFromTrans, convexToTrans, 1f, linVel, angVel);
      Transform R = new Transform();
      R.setIdentity();
      R.setRotation(convexFromTrans.getRotation(new Quat4f()));
      castShape.calculateTemporalAabb(R, linVel, angVel, 1f, castShapeAabbMin, castShapeAabbMax);
    }

    Transform tmpTrans = new Transform();

    // go over all objects, and if the ray intersects their aabb + cast shape aabb,
    // do a ray-shape query using convexCaster (CCD)
    for (int i = 0; i < overlappingObjects.size(); i++) {
      CollisionObject collisionObject = overlappingObjects.getQuick(i);

      // only perform raycast if filterMask matches
      if (resultCallback.needsCollision(collisionObject.getBroadphaseHandle())) {
        // RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
        Vector3f collisionObjectAabbMin = new Vector3f();
        Vector3f collisionObjectAabbMax = new Vector3f();
        collisionObject
            .getCollisionShape()
            .getAabb(
                collisionObject.getWorldTransform(tmpTrans),
                collisionObjectAabbMin,
                collisionObjectAabbMax);
        AabbUtil2.aabbExpand(
            collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
        float[] hitLambda =
            new float[] {1f}; // could use resultCallback.closestHitFraction, but needs testing
        Vector3f hitNormal = new Vector3f();
        if (AabbUtil2.rayAabb(
            convexFromWorld.origin,
            convexToWorld.origin,
            collisionObjectAabbMin,
            collisionObjectAabbMax,
            hitLambda,
            hitNormal)) {
          CollisionWorld.objectQuerySingle(
              castShape,
              convexFromTrans,
              convexToTrans,
              collisionObject,
              collisionObject.getCollisionShape(),
              collisionObject.getWorldTransform(tmpTrans),
              resultCallback,
              allowedCcdPenetration);
        }
      }
    }
  }