17 static inline float gridceil(
float d)
19 float c = std::ceil(d);
20 return (c==d) ? c+1.0f : c;
23 static inline double gridceil(
double d)
25 auto c = std::ceil(d);
26 return (c==d) ? c+1.0 : c;
29 static inline float gridfloor(
float d)
31 float c = std::floor(d);
32 return (c==d) ? c-1.0f : c;
35 static inline double gridfloor(
double d)
37 auto c = std::floor(d);
38 return (c==d) ? c-1.0 : c;
43 bool Intersect(
const Terrain &t,
const WFMath::AxisBox<3> &bbox)
45 float max, min=bbox.lowCorner()[1];
46 const int res = t.getResolution();
47 const float spacing = t.getSpacing();
51 int xlow = (int) floor(bbox.lowCorner()[0] / spacing);
52 int xhigh = (int) gridceil(bbox.highCorner()[0] / spacing);
53 int zlow = (int) floor(bbox.lowCorner()[2] / spacing);
54 int zhigh = (int) gridceil(bbox.highCorner()[2] / spacing);
57 for (
int x = xlow; x < xhigh; x++) {
58 for (
int z = zlow; z < zhigh; z++) {
61 Segment *thisSeg=t.getSegmentAtIndex(x,z);
64 max=thisSeg->getMax();
73 int min_x = (int) floor(bbox.lowCorner()[0] - ((float)x * spacing));
74 if (min_x < 0) min_x = 0;
76 int max_x = (int) gridceil(bbox.highCorner()[0] - ((float)x * spacing));
77 if (max_x > res) min_x = res;
79 int min_z = (int) floor(bbox.lowCorner()[2] - ((float)z * spacing));
80 if (min_z < 0) min_z = 0;
82 int max_z = (int) gridceil(bbox.highCorner()[2] - ((float)z * spacing));
83 if (max_z > res) min_z = res;
89 for (
int xpt = min_x; xpt <= max_x; xpt++) {
90 for (
int zpt = min_z; zpt <= max_z; zpt++) {
92 if (thisSeg->get(xpt,zpt) > min) {
106 static bool HOT(
const Terrain &t,
const WFMath::Point<3> &pt,
double & h)
108 WFMath::Vector<3> normal;
110 if (!t.getHeightAndNormal(pt[0], pt[2], terrHeight, normal)) {
114 h = (pt[1] - terrHeight);
118 bool Intersect(
const Terrain &t,
const WFMath::Point<3> &pt)
121 return HOT(t, pt, h) && h <= 0.0;
125 static bool cellIntersect(
double h1,
double h2,
double h3,
double h4,
double X,
double Z,
126 const WFMath::Vector<3> &nDir,
float dirLen,
127 const WFMath::Point<3> &sPt, WFMath::Point<3> &intersection,
128 WFMath::Vector<3> &normal,
double &par)
147 WFMath::Point<3> topInt, botInt;
150 WFMath::Vector<3> p0 = WFMath::Vector<3>(X, h1, Z);
154 bool topIntersected =
false;
155 WFMath::Vector<3> topNormal(h2-h3, 1.0, h1-h2);
156 topNormal.normalize();
157 double t = Dot(nDir, topNormal);
161 if ((t > 1e-7) || (t < -1e-7)) {
162 topP = - (Dot((sPt-WFMath::Point<3>(0,0,0)), topNormal)
163 - Dot(topNormal, p0)) / t;
164 topInt = sPt + nDir*topP;
166 if ((topP <= dirLen) && (topP > 0.0) &&
167 (topInt[0] >= X ) && (topInt[2] <= Z + 1 ) &&
168 ((topInt[0] - topInt[2]) <= (X - Z)) ) {
174 bool botIntersected =
false;
175 WFMath::Vector<3> botNormal(h1-h4, 1.0, h4-h3);
176 botNormal.normalize();
177 double b = Dot(nDir, botNormal);
180 if ((b > 1e-7) || (b < -1e-7)) {
181 botP = - (Dot((sPt-WFMath::Point<3>(0,0,0)), botNormal)
182 - Dot(botNormal, p0)) / b;
183 botInt = sPt + nDir*botP;
185 if ((botP <= dirLen) && (botP > 0.0) &&
186 (botInt[0] <= X + 1 ) && (botInt[2] >= Z ) &&
187 ((botInt[0] - botInt[2]) >= (X - Z)) ) {
188 botIntersected =
true;
192 if (topIntersected && botIntersected) {
194 intersection = botInt;
204 intersection = topInt;
210 else if (topIntersected) {
211 intersection = topInt;
216 else if (botIntersected) {
217 intersection = botInt;
236 bool Intersect(
const Terrain &t,
const WFMath::Point<3> &sPt,
const WFMath::Vector<3>& dir,
237 WFMath::Point<3> &intersection, WFMath::Vector<3> &normal,
double &par)
246 if (HOT(t, sPt, hot) && hot < 0.0)
return true;
248 double paraX=0.0, paraZ=0.0;
252 WFMath::Point<3> last(sPt), next(sPt);
253 WFMath::Vector<3> nDir(dir);
255 float dirLen = dir.mag();
258 if (dir[0] != 0.0f) {
260 double crossX = (dir[0] > 0.0f) ? gridceil(last[0]) : gridfloor(last[0]);
261 pX = (crossX - last[0]) * paraX;
262 pX = std::min(pX, 1.0);
269 if (dir[2] != 0.0f) {
271 double crossZ = (dir[2] > 0.0f) ? gridceil(last[2]) : gridfloor(last[2]);
272 pZ = (crossZ - sPt[2]) * paraZ;
273 pZ = std::min(pZ, 1.0);
280 paraX = std::abs(paraX);
281 paraZ = std::abs(paraZ);
283 bool endpoint =
false;
288 next = sPt + (pX * dir);
292 next = sPt + (pZ * dir);
300 float x= (dir[0] > 0) ? std::floor(last[0]) : std::floor(next[0]);
301 float z= (dir[2] > 0) ? std::floor(last[2]) : std::floor(next[2]);
304 h3 = t.get(x+1, z+1);
306 auto height = std::max( std::max(h1, h2),
309 if ( (last[1] < height) || (next[1] < height) ) {
311 if (cellIntersect(h1, h2, h3, h4, x, z, nDir, dirLen, sPt,
312 intersection, normal, par)) {
317 if ((pX >= 1.0f) && (pZ >= 1.0f)) {
321 else endpoint =
true;
static constexpr float defaultLevel
Height value used when no data is available.