Пример #1
0
bool insideSurfaceClosest(const Point3D &pTest, const Surface &s, const SpacialHash &faceHash, ClosestPointInfo *inf, float stopBelow, bool allowQuickTest){
  if (inf)
    inf->type = DIST_TYPE_INVALID;

  //  quick bounding box test
  if (allowQuickTest){
    if (pTest.x < s.pMin.x || pTest.x > s.pMax.x ||
        pTest.y < s.pMin.y || pTest.y > s.pMax.y ||
        pTest.z < s.pMin.z || pTest.z > s.pMax.z){
      return false;
      }
    }

  ClosestPointInfo localClosestInf;
  if (!inf)
    inf = &localClosestInf;
  float dist = getClosestPoint(inf, pTest, s, faceHash, stopBelow);

  if (dist < stopBelow){
    //  optimise for dodec
    return true;
    }

  //  vector to point on surface
  Vector3D v;
  v.difference(pTest, inf->pClose);
  v.norm();

  if (inf->type == FACE){
    //  face test 
    Vector3D n;
    s.getTriangleNormal(&n, inf->triangle);
    double dt = n.dot(v);
    return dt <= 0;
    }
  else if (inf->type == EDGE){
    //  edge test
    const Surface::Triangle *tri = &s.triangles.index(inf->triangle);

    //  edge will be between vertices v[num] and v[(num+1)%3]
    int e[2];
    e[0] = tri->v[inf->num];
    e[1] = tri->v[(inf->num+1)%3];

    int neigh = findNeighbour(s, *tri, e);
    if (neigh >= 0){
      //  make a plane for one of the triangles
      Vector3D n1;
      s.getTriangleNormal(&n1, inf->triangle);
      Point3D p1 = s.vertices.index(e[0]).p;
      Plane pl1;
      pl1.assign(n1, p1);

      //  get the point from the other triangle which is not part of edge
      const Surface::Triangle *tri2 = &s.triangles.index(neigh);
      for (int i = 0; i < 3; i++){
        if (tri2->v[i] != e[0] && tri2->v[i] != e[1])
          break;
        }
      CHECK_DEBUG0(i != 3);
      Point3D p2 = s.vertices.index(e[1]).p;
      
      //  get signed distance to plane
      float dist = pl1.dist(p2);

      //  need normal for second triangle
      Vector3D n2;
      s.getTriangleNormal(&n2, neigh);

      if (dist <= 0.0f){
        //  faces form convex spike, back facing to both
        return v.dot(n1) <= 0 && v.dot(n2) <= 0;
        }
      else{
        //  faces form concavity, back facing to either
        return v.dot(n1) <= 0 || v.dot(n2) <= 0;
        }
      }
    else{
      OUTPUTINFO("HHHHHMMMMMMM loose edge\n");
      return false;  //  only one triangle on edge - use face ??
      }
    }
  else{// if (minType == VERTEX)
    // chosen triangle
    const Surface::Triangle *tri = &s.triangles.index(inf->triangle);

    //  chosen vertex
    int vI = tri->v[inf->num];
    Vector3D n;
    s.getVertexNormal(&n, vI);
    return n.dot(v) <= 0;

/*
    //  get all faces
    Array<int> tris;
    s.findNeighbours(&tris, vI, inf->triangle);

    //  behind test for all faces
    int numTri = tris.getSize();
    for (int i = 0; i < numTri; i++){
      Vector3D n;
      s.getTriangleNormal(&n, tris.index(i));
      double dt = n.dot(v);
      if (dt > 0)
        return false;
      }

    //  must be behind all
    return true;*/
    }
}