public void refreshContactPoints() {
    assert (manifoldPtr != null);
    if (manifoldPtr.getNumContacts() == 0) {
      return;
    }

    boolean isSwapped = manifoldPtr.getBody0() != body0;

    if (isSwapped) {
      manifoldPtr.refreshContactPoints(rootTransB, rootTransA);
    } else {
      manifoldPtr.refreshContactPoints(rootTransA, rootTransB);
    }
  }
  public void addContactPoint(Vector3f normalOnBInWorld, Vector3f pointInWorld, float depth) {
    assert (manifoldPtr != null);
    // order in manifold needs to match

    if (depth > manifoldPtr.getContactBreakingThreshold()) {
      return;
    }

    stack.vectors.push();
    try {
      boolean isSwapped = manifoldPtr.getBody0() != body0;

      Vector3f pointA = stack.vectors.get();
      pointA.scaleAdd(depth, normalOnBInWorld, pointInWorld);

      Vector3f localA = stack.vectors.get();
      Vector3f localB = stack.vectors.get();

      if (isSwapped) {
        rootTransB.invXform(pointA, localA);
        rootTransA.invXform(pointInWorld, localB);
      } else {
        rootTransA.invXform(pointA, localA);
        rootTransB.invXform(pointInWorld, localB);
      }

      ManifoldPoint newPt = pointsPool.get();
      newPt.init(localA, localB, normalOnBInWorld, depth);

      newPt.positionWorldOnA.set(pointA);
      newPt.positionWorldOnB.set(pointInWorld);

      int insertIndex = manifoldPtr.getCacheEntry(newPt);

      newPt.combinedFriction = calculateCombinedFriction(body0, body1);
      newPt.combinedRestitution = calculateCombinedRestitution(body0, body1);

      /// todo, check this for any side effects
      if (insertIndex >= 0) {
        // const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
        manifoldPtr.replaceContactPoint(newPt, insertIndex);
      } else {
        manifoldPtr.addManifoldPoint(newPt);
      }

      // User can override friction and/or restitution
      if (BulletGlobals.gContactAddedCallback != null
          &&
          // and if either of the two bodies requires custom material
          ((body0.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0
              || (body1.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0)) {
        // experimental feature info, for per-triangle material etc.
        CollisionObject obj0 = isSwapped ? body1 : body0;
        CollisionObject obj1 = isSwapped ? body0 : body1;
        BulletGlobals.gContactAddedCallback.invoke(
            newPt, obj0, partId0, index0, obj1, partId1, index1);
      }

      pointsPool.release(newPt);
    } finally {
      stack.vectors.pop();
    }
  }