Exemple #1
0
//helper function for ray terrain intersection
static bool cellIntersect(float h1, float h2, float h3, float h4, float X, float Y, 
                   const WFMath::Vector<3> &nDir, float dirLen,
                   const WFMath::Point<3> &sPt, WFMath::Point<3> &intersection,
                   WFMath::Vector<3> &normal, float &par)
{
    //ray plane intersection roughly using the following:
    //parametric ray eqn:  p=po + par V
    //plane eqn: p dot N + d = 0
    //
    //intersection:
    // -par = (po dot N + d ) / (V dot N)
    // 
    //
    // effectively we calculate the ray parametric variable for the
    // intersection of the plane corresponding to each triangle
    // then clip them by endpints of the ray, and by the sides of the square
    // and by the diagonal
    //
    // if they both still intersect, then we choose the earlier intersection
    
   
    //intersection points for top and bottom triangles
    WFMath::Point<3> topInt, botInt;
    
    //point to use in plane equation for both triangles
    WFMath::Vector<3> p0 = WFMath::Vector<3>(X, Y, h1);

    // square is broken into two triangles
    // top triangle |/
    bool topIntersected = false;
    WFMath::Vector<3> topNormal(h2-h3, h1-h2, 1.0);
    topNormal.normalize();
    float t = Dot(nDir, topNormal);

    float topP=0.0;

    if ((t > 1e-7) || (t < -1e-7)) {
        topP = - (Dot((sPt-WFMath::Point<3>(0.,0.,0.)), topNormal) 
               - Dot(topNormal, p0)) / t; 
        topInt = sPt + nDir*topP;
        //check the intersection is inside the triangle, and within the ray extents
        if ((topP <= dirLen) && (topP > 0.0) &&
            (topInt[0] >= X ) && (topInt[1] <= Y + 1 ) &&
            ((topInt[0] - topInt[1]) <= (X - Y)) ) {
                topIntersected=true;
        }
    }

    // bottom triangle /|
    bool botIntersected = false;
    WFMath::Vector<3> botNormal(h1-h4, h4-h3, 1.0);
    botNormal.normalize();
    float b = Dot(nDir, botNormal);
    float botP=0.0;

    if ((b > 1e-7) || (b < -1e-7)) {
        botP = - (Dot((sPt-WFMath::Point<3>(0.,0.,0.)), botNormal) 
               - Dot(botNormal, p0)) / b; 
        botInt = sPt + nDir*botP;
        //check the intersection is inside the triangle, and within the ray extents
        if ((botP <= dirLen) && (botP > 0.0) &&
            (botInt[0] <= X + 1 ) && (botInt[1] >= Y ) && 
            ((botInt[0] - botInt[1]) >= (X - Y)) ) {
                botIntersected = true;
        }
    }

    if (topIntersected && botIntersected) { //intersection with both
        if (botP <= topP) {
            intersection = botInt;
            normal = botNormal; 
            par=botP/dirLen;
            if (botP == topP) {
                normal += topNormal;
                normal.normalize();
            }
            return true;    
        }
        else {
            intersection = topInt;
            normal = topNormal; 
            par=topP/dirLen;
            return true;
        }
    }
    else if (topIntersected) { //intersection with top
        intersection = topInt;
        normal = topNormal; 
        par=topP/dirLen;
        return true;
    }
    else if (botIntersected) { //intersection with bot
        intersection = botInt;
        normal = botNormal; 
        par=botP/dirLen;
        return true;
    }

    return false;
}
Exemple #2
0
//helper function for ray terrain intersection
static bool cellIntersect(float h1, float h2, float h3, float h4,
                          float X, float Y,
                          const std::tuple<float, float, float> &nDir, float dirLen,
                          const WFMath::Point<3> &sPt,
                          WFMath::Point<3> &intersection,
                          std::tuple<float, float, float> &normal, float &par)
{
  //ray plane intersection roughly using the following:
  //parametric ray eqn:  p=po + par V
  //plane eqn: p dot N + d = 0
  //
  //intersection:
  // -par = (po dot N + d ) / (V dot N)
  //
  //
  // effectively we calculate the ray parametric variable for the
  // intersection of the plane corresponding to each triangle
  // then clip them by endpints of the ray, and by the sides of the square
  // and by the diagonal
  //
  // if they both still intersect, then we choose the earlier intersection


  //intersection points for top and bottom triangles
  WFMath::Point<3> topInt, botInt;

  //point to use in plane equation for both triangles
  std::tuple<float, float, float> p0 = std::tuple<float, float, float>(X, Y, h1);

  // square is broken into two triangles
  // top triangle |/
  bool topIntersected = false;
  std::tuple<float, float, float> topNormal(h2 - h3, h1 - h2, 1.0);
  normalise_i(topNormal);
  float t = dot(nDir, topNormal);

  decltype(t) topP = 0.0;

  if ((t > 1e-7) || (t < -1e-7))
  {
    topP = -(dot(std::tuple<float, float, float>(sPt[0], sPt[1], sPt[2]), topNormal)
             - dot(topNormal, p0)) / t;
    topInt = translate(sPt, scale(nDir, topP));
    //check the intersection is inside the triangle, and within the ray extents
    if ((topP <= dirLen) && (topP > 0.0) &&
        (topInt[0] >= X ) && (topInt[1] <= Y + 1 ) &&
        ((topInt[0] - topInt[1]) <= (X - Y)) )
    {
      topIntersected = true;
    }
  }

  // bottom triangle /|
  bool botIntersected = false;
  std::tuple<float, float, float> botNormal(h1 - h4, h4 - h3, 1.0);
  normalise_i(botNormal);
  auto b = dot(nDir, botNormal);
  decltype(b) botP = 0.0;

  if ((b > 1e-7) || (b < -1e-7))
  {
    botP = -(dot(std::tuple<float, float, float>(sPt[0], sPt[1], sPt[2]), botNormal)
             - dot(botNormal, p0)) / b;
    botInt = translate(sPt, scale(nDir, botP));
    //check the intersection is inside the triangle, and within the ray extents
    if ((botP <= dirLen) && (botP > 0.0) &&
        (botInt[0] <= X + 1 ) && (botInt[1] >= Y ) &&
        ((botInt[0] - botInt[1]) >= (X - Y)) )
    {
      botIntersected = true;
    }
  }

  if (topIntersected && botIntersected)     //intersection with both
  {
    if (botP <= topP)
    {
      intersection = botInt;
      normal = botNormal;
      par = botP / dirLen;
      if (botP == topP)
      {
        add_i(normal, topNormal);
        normalise_i(normal);
      }
      return true;
    }
    else
    {
      intersection = topInt;
      normal = topNormal;
      par = topP / dirLen;
      return true;
    }
  }
  else if (topIntersected)     //intersection with top
  {
    intersection = topInt;
    normal = topNormal;
    par = topP / dirLen;
    return true;
  }
  else if (botIntersected)     //intersection with bot
  {
    intersection = botInt;
    normal = botNormal;
    par = botP / dirLen;
    return true;
  }

  return false;
}