summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-10-31 20:56:16 +0100
committerRobert Vollmert <rvollmert@gmx.net>2009-11-01 21:45:26 +0100
commitbe58c68878c08c4d1373c2f38c9ef11d66010d06 (patch)
treecf58242500fe30c94dc0f2b34cfcb1180ebfdb75 /crawl-ref
parentb81b08f9aa02afd4a8195bf8d8b846b7de0788cd (diff)
downloadcrawl-ref-be58c68878c08c4d1373c2f38c9ef11d66010d06.tar.gz
crawl-ref-be58c68878c08c4d1373c2f38c9ef11d66010d06.zip
Simplify geom2d ray advance code.
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/geom2d.cc64
-rw-r--r--crawl-ref/source/geom2d.h2
-rw-r--r--crawl-ref/source/ray.cc11
3 files changed, 31 insertions, 46 deletions
diff --git a/crawl-ref/source/geom2d.cc b/crawl-ref/source/geom2d.cc
index 35ec5138ae..861e2748f8 100644
--- a/crawl-ref/source/geom2d.cc
+++ b/crawl-ref/source/geom2d.cc
@@ -56,10 +56,12 @@ double nextintersect(const ray &r, const lineseq &ls)
ASSERT(!parallel(r.dir, ls.f));
double fp = ls.f(r.start);
double fd = ls.f(r.dir);
- // want smallest positive t with
+ // want smallest positive t > 0 with
// fp + t*fd = ls.offset + k*ls.dist, k integral
double a = (fp - ls.offset) / ls.dist;
double k = (ls.dist*fd) > 0 ? ceil(a) : floor(a);
+ if (double_is_zero(k - a))
+ k += (ls.dist*fd > 0 ? 1 : -1);
double t = (k - a) * ls.dist / fd;
return (t);
}
@@ -72,55 +74,37 @@ static double tdist(const ray &r, const lineseq &ls)
return (std::abs(ls.dist / ls.f(r.dir)));
}
-// Shoot the ray inside the next cell.
-// Returns true if successfully advanced into a new cell,
-// false if it hit a corner.
-bool ray::to_next_cell(const grid &g)
+// Move the ray towards the next grid line.
+// Half way there if "half" is true, else all the way there
+// Returns whether it hit a corner.
+bool ray::to_grid(const grid &g, bool half)
{
// ASSERT(!parallel(g.vert, g.horiz));
- lineseq ls;
+ bool corner = false;
+ double t = 0;
if (parallel(dir, g.ls1.f))
- ls = g.ls2;
+ t = nextintersect(*this, g.ls2);
else if (parallel(dir, g.ls2.f))
- ls = g.ls1;
+ t = nextintersect(*this, g.ls1);
else
{
- double s = nextintersect(*this, g.ls1);
- double t = nextintersect(*this, g.ls2);
- double sd = tdist(*this, g.ls1);
- double td = tdist(*this, g.ls2);
- if (double_is_zero(s - t))
- {
- // Move onto the corner. The fact that we're on a corner
- // should be tracked externally.
- advance(s);
- return (false);
- }
- double dmin = std::min(s,t);
- double dnext = std::min(std::max(s,t), dmin + std::min(sd, td));
- advance((dmin + dnext) / 2.0);
- return (true);
+ double r = nextintersect(*this, g.ls1);
+ double s = nextintersect(*this, g.ls2);
+ t = std::min(r, s);
+ corner = double_is_zero(r - s);
}
- // parallel: just advance an extra half
- double s = nextintersect(*this, ls);
- advance(s + 0.5 * tdist(*this, ls));
- return (true);
+ advance(half ? 0.5 * t : t);
+ return (corner && !half);
}
-// Move a ray by half a cell: starting at a corner of the grid,
-// it ends up within the next cell.
-void ray::move_half_cell(const grid &g)
+// Shoot the ray inside the next cell, stopping at corners.
+// Returns true if it hit a corner.
+bool ray::to_next_cell(const grid &g)
{
- // ASSERT(!parallel(g.vert, g.horiz));
- lineseq ls;
- double t;
- if (parallel(dir, g.ls1.f))
- t = tdist(*this, g.ls2);
- else if (parallel(dir, g.ls2.f))
- t = tdist(*this, g.ls1);
- else
- t = std::min(tdist(*this, g.ls1), tdist(*this, g.ls2));
- advance(0.5 * t);
+ if (to_grid(g, false))
+ return (true);
+ to_grid(g, true);
+ return (false);
}
vector normal(const form &f)
diff --git a/crawl-ref/source/geom2d.h b/crawl-ref/source/geom2d.h
index 6f7e147ab1..e06f8bc28f 100644
--- a/crawl-ref/source/geom2d.h
+++ b/crawl-ref/source/geom2d.h
@@ -46,7 +46,7 @@ struct ray
vector shoot(double t) const;
void advance(double t);
- void move_half_cell(const grid &g);
+ bool to_grid(const grid& g, bool half);
bool to_next_cell(const grid& g);
};
diff --git a/crawl-ref/source/ray.cc b/crawl-ref/source/ray.cc
index 56fc3058d1..f93cf12668 100644
--- a/crawl-ref/source/ray.cc
+++ b/crawl-ref/source/ray.cc
@@ -65,7 +65,8 @@ coord_def ray_def::pos() const
return (coord_def(x, y));
}
-// Return false if we passed or hit a corner.
+// Return true if we didn't hit a corner, hence if this
+// is a good ray so far.
bool ray_def::advance()
{
ASSERT(on_corner || in_diamond_int(r.start));
@@ -73,17 +74,17 @@ bool ray_def::advance()
{
ASSERT (is_corner(r.start));
on_corner = false;
- r.move_half_cell(diamonds);
+ r.to_grid(diamonds, true);
}
else
{
// Starting inside a diamond.
- bool c = !r.to_next_cell(diamonds);
+ bool c = r.to_next_cell(diamonds);
if (c)
{
// r is now on a corner, going from diamond to diamond.
- r.move_half_cell(diamonds);
+ r.to_grid(diamonds, true);
return (false);
}
}
@@ -91,7 +92,7 @@ bool ray_def::advance()
// Now inside a non-diamond.
ASSERT(!in_diamond(r.start));
- if (r.to_next_cell(diamonds))
+ if (!r.to_next_cell(diamonds))
{
ASSERT(in_diamond_int(r.start));
return (true);