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; }
bool Intersect(const Terrain &t, const WFMath::Point<3> &pt) { return HOT(t, pt) <= 0.0; }
bool Intersect(Terrain const &t, const WFMath::Point<3> &pt) { float h; return HOT(t, pt, h) && h <= 0.0; }