findSeparatingAxis method

bool findSeparatingAxis(
  1. ConvexPolyhedron hullB,
  2. Vec3 posA,
  3. Quaternion quatA,
  4. Vec3 posB,
  5. Quaternion quatB,
  6. Vec3 target, [
  7. List<int>? faceListA,
  8. List<int>? faceListB,
])

Find the separating axis between this hull and another @param target The target vector to save the axis in @return Returns false if a separation is found, else true

Implementation

bool findSeparatingAxis(
  ConvexPolyhedron hullB,
  Vec3 posA,
  Quaternion quatA,
  Vec3 posB,
  Quaternion quatB,
  final Vec3 target,[
  List<int>? faceListA,
  List<int>? faceListB
]) {
  final faceANormalWS3 = Vec3();
  final worldNormal1 = Vec3();
  final deltaC = Vec3();
  final worldEdge0 = Vec3();
  final worldEdge1 = Vec3();
  final cross = Vec3();

  double dmin = double.infinity;
  final hullA = this;
  //int curPlaneTests = 0;

  if (hullA.uniqueAxes != null) {
    final numFacesA = faceListA != null? faceListA.length : hullA.faces.length;

    // Test face normals from hullA
    for (int i = 0; i < numFacesA; i++) {
      final fi = faceListA != null? faceListA[i] : i;

      // Get world face normal
      faceANormalWS3.copy(hullA.faceNormals[fi]!);
      quatA.vmult(faceANormalWS3, faceANormalWS3);

      final d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
      if (d == null) {
        return false;
      }
      if (d < dmin) {
        dmin = d;
        target.copy(faceANormalWS3);
      }
    }
  } else if(hullA.uniqueAxes != null){
    // Test unique axes
    for (int i = 0; i != hullA.uniqueAxes!.length; i++) {
      // Get world axis
      quatA.vmult(hullA.uniqueAxes![i], faceANormalWS3);

      final d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
      if (d == null) {
        return false;
      }
      if (d < dmin) {
        dmin = d;
        target.copy(faceANormalWS3);
      }
    }
  }

  if (hullB.uniqueAxes !=  null) {
    // Test face normals from hullB
    final numFacesB = faceListB != null ? faceListB.length : hullB.faces.length;
    for (int i = 0; i < numFacesB; i++) {
      final fi = faceListB != null? faceListB[i] : i;

      worldNormal1.copy(hullB.faceNormals[fi]!);
      quatB.vmult(worldNormal1, worldNormal1);
      //curPlaneTests++;
      final d = hullA.testSepAxis(worldNormal1, hullB, posA, quatA, posB, quatB);
      if (d == null) {
        return false;
      }
      if (d < dmin) {
        dmin = d;
        target.copy(worldNormal1);
      }
    }
  } else {
    // Test unique axes in B
    final int len = hullB.uniqueAxes?.length ?? 0;
    for (int i = 0; i != len; i++) {
      quatB.vmult(hullB.uniqueAxes![i], worldNormal1);

      //curPlaneTests++;
      final d = hullA.testSepAxis(worldNormal1, hullB, posA, quatA, posB, quatB);
      if (d == null) {
        return false;
      }
      if (d < dmin) {
        dmin = d;
        target.copy(worldNormal1);
      }
    }
  }

  // Test edges
  for (int e0 = 0; e0 != hullA.uniqueEdges.length; e0++) {
    // Get world edge
    quatA.vmult(hullA.uniqueEdges[e0], worldEdge0);

    for (int e1 = 0; e1 != hullB.uniqueEdges.length; e1++) {
      // Get world edge 2
      quatB.vmult(hullB.uniqueEdges[e1], worldEdge1);
      worldEdge0.cross(worldEdge1, cross);

      if (!cross.almostZero()) {
        cross.normalize();
        final dist = hullA.testSepAxis(cross, hullB, posA, quatA, posB, quatB);
        if (dist == null) {
          return false;
        }
        if (dist < dmin) {
          dmin = dist;
          target.copy(cross);
        }
      }
    }
  }

  posB.vsub(posA, deltaC);
  if (deltaC.dot(target) > 0.0) {
    target.negate(target);
  }

  return true;
}