heightfieldParticle method

bool heightfieldParticle(
  1. Heightfield si,
  2. Particle sj,
  3. Vector3 xi,
  4. Vector3 xj,
  5. Quaternion qi,
  6. Quaternion qj,
  7. Body bi,
  8. Body bj, [
  9. Shape? rsi,
  10. Shape? rsj,
  11. bool justTest = false,
])

Implementation

bool heightfieldParticle(
  Heightfield si,
  Particle sj,
  Vector3 xi,
  Vector3 xj,
  Quaternion qi,
  Quaternion qj,
  Body bi,
  Body bj,
  [
    Shape? rsi,
    Shape? rsj,
    bool justTest = false
]){
  final data = si.data;
  final radius = sj.boundingSphereRadius;
  final w = si.elementSize;
  final worldPillarOffset = _convexHeightfieldTmp2;

  // Get sphere position to heightfield local!
  final localConvexPos = _convexHeightfieldTmp1;
  Transform.pointToLocalFrame(xi, qi, xj, localConvexPos);

  // Get the index of the data points to test against
  int iMinX = ((localConvexPos.x - radius) / w).floor() - 1;
  int iMaxX = ((localConvexPos.x + radius) / w).ceil() + 1;
  int iMinY = ((localConvexPos.y - radius) / w).floor() - 1;
  int iMaxY = ((localConvexPos.y + radius) / w).ceil() + 1;

  // Bail out if we are out of the terrain
  if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) {
    return false;
  }

  // Clamp index to edges
  if (iMinX < 0) {
    iMinX = 0;
  }
  if (iMaxX < 0) {
    iMaxX = 0;
  }
  if (iMinY < 0) {
    iMinY = 0;
  }
  if (iMaxY < 0) {
    iMaxY = 0;
  }
  if (iMinX >= data.length) {
    iMinX = data.length - 1;
  }
  if (iMaxX >= data.length) {
    iMaxX = data.length - 1;
  }
  if (iMaxY >= data[0].length) {
    iMaxY = data[0].length - 1;
  }
  if (iMinY >= data[0].length) {
    iMinY = data[0].length - 1;
  }

  List<double> minMax = [0,0];
  si.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
  final min = minMax[0];
  final max = minMax[1];

  // Bail out if we can't touch the bounding height box
  if (localConvexPos.z - radius > max || localConvexPos.z + radius < min) {
    return false;
  }

  for (int i = iMinX; i < iMaxX; i++) {
    for (int j = iMinY; j < iMaxY; j++) {
      bool intersecting = false;
      // Lower triangle
      si.getConvexTrianglePillar(i, j, false);
      Transform.pointToWorldFrame(xi, qi, si.pillarOffset, worldPillarOffset);
      if (
        xj.distanceTo(worldPillarOffset) <= si.pillarConvex.boundingSphereRadius
      ) {
        intersecting = particleConvex(si.pillarConvex, sj, worldPillarOffset, xj, qi, qj, bi, bj, rsi, rsj, justTest);
      }

      if (justTest && intersecting) {
        return true;
      }

      // Upper triangle
      si.getConvexTrianglePillar(i, j, true);
      Transform.pointToWorldFrame(xi, qi, si.pillarOffset, worldPillarOffset);
      if (
        xj.distanceTo(worldPillarOffset) <= si.pillarConvex.boundingSphereRadius
      ) {
        intersecting = particleConvex(si.pillarConvex, sj, worldPillarOffset, xj, qi, qj, bi, bj, rsi, rsj, justTest);
      }

      if (justTest && intersecting) {
        return true;
      }
    }
  }
  return false;
}