示例#1
0
bool Intersect(const Terrain &t, const WFMath::Point<3> &sPt, const WFMath::Vector<3>& dir,
        WFMath::Point<3> &intersection, WFMath::Vector<3> &normal, float &par)
{
    //FIXME early reject using segment max
    //FIXME handle height point getting in a more optimal way
    //FIXME early reject for vertical ray


    // check if startpoint is below ground
    if (HOT(t, sPt) < 0.0) return true;
    
    float paraX=0.0, paraY=0.0; //used to store the parametric gap between grid crossings 
    float pX, pY; //the accumulators for the parametrics as we traverse the ray
    float h1,h2,h3,h4,height;

    WFMath::Point<3> last(sPt), next(sPt);
    WFMath::Vector<3> nDir(dir);
    nDir.normalize();
    float dirLen = dir.mag();
    
    //work out where the ray first crosses an X grid line
    if (dir[0] != 0.0f) {
        paraX = 1.0f/dir[0];
        float crossX = (dir[0] > 0.0f) ? gridceil(last[0]) : gridfloor(last[0]);
        pX = (crossX - last[0]) * paraX;
        pX = std::min(pX, 1.0f);
    }
    else { //parallel: never crosses
        pX = 1.0f;
    }

    //work out where the ray first crosses a Y grid line
    if (dir[1] != 0.0f) {
        paraY = 1.0f/dir[1];
        float crossY = (dir[1] > 0.0f) ? gridceil(last[1]) : gridfloor(last[1]);
        pY = (crossY - sPt[1]) * paraY;
        pY = std::min(pY, 1.0f);
    }
    else { //parallel: never crosses
        pY = 1.0f;
    }

    //ensure we traverse the ray forwards 
    paraX = std::abs(paraX);
    paraY = std::abs(paraY);

    bool endpoint = false;
    //check each candidate tile for an intersection
    while (1) {
        last = next;
        if (pX < pY) { // cross x grid line first
            next = sPt + (pX * dir);
            pX += paraX; // set x accumulator to current p
        }
        else { //cross y grid line first
            next = sPt + (pY * dir);
            if (pX == pY) {
                pX += paraX; //unusual case where ray crosses corner
            }
            pY += paraY; // set y accumulator to current p
        }

        //FIXME these gets could be optimized a bit
        float x= (dir[0] > 0) ? std::floor(last[0]) : std::floor(next[0]);
        float y= (dir[1] > 0) ? std::floor(last[1]) : std::floor(next[1]);
        h1 = t.get(x, y);
        h2 = t.get(x, y+1);
        h3 = t.get(x+1, y+1);
        h4 = t.get(x+1, y);
        height = std::max( std::max(h1, h2), 
                           std::max(h3, h4)); 
        
        if ( (last[2] < height) || (next[2] < height) ) {
            // possible intersect with this tile
            if (cellIntersect(h1, h2, h3, h4, x, y, nDir, dirLen, sPt,
                              intersection, normal, par)) {
                return true;
            }
        }

        if ((pX >= 1.0f) && (pY >= 1.0f)) {
            if (endpoint) {
                break;
            }
            else endpoint = true;
        }
    }

    return false;
}
示例#2
0
bool Intersect(const Terrain &t, const WFMath::Point<3> &pt) 
{
    return HOT(t, pt) <= 0.0;
}
示例#3
0
bool Intersect(Terrain const &t, const WFMath::Point<3> &pt)
{
  float h;
  return HOT(t, pt, h) && h <= 0.0;
}