diff options
Diffstat (limited to 'crawl-ref/source/ray.cc')
-rw-r--r-- | crawl-ref/source/ray.cc | 199 |
1 files changed, 18 insertions, 181 deletions
diff --git a/crawl-ref/source/ray.cc b/crawl-ref/source/ray.cc index 1094c5f0ae..e6952f2102 100644 --- a/crawl-ref/source/ray.cc +++ b/crawl-ref/source/ray.cc @@ -1,210 +1,47 @@ /* - * File: ray.cc - * Summary: Ray definition + * File: .cc + * Summary: */ #include "AppHdr.h" -#include "ray.h" +#include <cmath> -#include <math.h> +#include "ray.h" +#include "geom2d.h" -#include "los.h" -#include "terrain.h" +static geom::grid diamonds(geom::lineseq(1, 1, 0.5, 1), + geom::lineseq(1, -1, -0.5, 1)); static int ifloor(double d) { return static_cast<int>(floor(d)); } -ray_def::ray_def(double ax, double ay, double s, int qx, int qy, int idx) - : accx(ax), accy(ay), slope(s), quadx(qx), quady(qy), cycle_idx(idx) -{ -} - -int ray_def::x() const -{ - return ifloor(accx); -} - -int ray_def::y() const -{ - return ifloor(accy); -} - coord_def ray_def::pos() const { - return coord_def(x(), y()); + // TODO: Assert we're in a central diamond. + int x = ifloor(r.start.x); + int y = ifloor(r.start.y); + return (coord_def(x, y)); } -static double _reflect(double p, double c) +bool ray_def::advance() { - return (c + c - p); -} - -double ray_def::reflect(bool rx, double oldx, double newx) const -{ - if (rx ? fabs(slope) > 1.0 : fabs(slope) < 1.0) - return (_reflect(oldx, floor(oldx) + 0.5)); - - const double flnew = floor(newx); - const double flold = floor(oldx); - return (_reflect(oldx, - flnew > flold ? flnew : - flold > flnew ? flold : - (newx + oldx) / 2)); -} - -void ray_def::set_reflect_point(const double oldx, const double oldy, - bool blocked_x, bool blocked_y) -{ - if (blocked_x == blocked_y) - { - // What to do? - accx = oldx; - accy = oldy; - return; - } - - if (blocked_x) - { - ASSERT(int(oldy) != int(accy)); - accy = oldy; - accx = reflect(true, oldx, accx); - } - else - { - ASSERT(int(oldx) != int(accx)); - accx = oldx; - accy = reflect(false, oldy, accy); - } + return (geom::nextcell(r, diamonds, true) + && geom::nextcell(r, diamonds, false)); } void ray_def::advance_and_bounce() { - int oldx = x(), oldy = y(); - const double oldaccx = accx, oldaccy = accy; - adv_type rc = advance(); - int newx = x(), newy = y(); - ASSERT(feat_is_solid(grd[newx][newy])); - - const bool blocked_x = feat_is_solid(grd[oldx][newy]); - const bool blocked_y = feat_is_solid(grd[newx][oldy]); - - if (double_is_zero(slope) || slope > 100.0) - { - quadx = -quadx; - quady = -quady; - } - else if (rc == ADV_X) - quadx = -quadx; - else if (rc == ADV_Y) - quady = -quady; - else // rc == ADV_XY - { - ASSERT((oldx != newx) && (oldy != newy)); - if (blocked_x && blocked_y) - { - quadx = -quadx; - quady = -quady; - } - else if (blocked_x) - quady = -quady; - else - quadx = -quadx; - } - - set_reflect_point(oldaccx, oldaccy, blocked_x, blocked_y); + // XXX + r.dir *= -1; } void ray_def::regress() { - quadx = -quadx; quady= -quady; + r.dir *= -1; advance(); - quadx = -quadx; quady= -quady; -} - -// Advance a ray in the positive quadrant. -// note that slope must be nonnegative! -// returns 0 if the advance was in x, 1 if it was in y, 2 if it was -// the diagonal -adv_type ray_def::raw_advance_pos() -{ - // handle perpendiculars - if (double_is_zero(slope)) - { - accx += 1.0; - return ADV_X; - } - if (slope > 100.0) - { - accy += 1.0; - return ADV_Y; - } - - const double xtarget = ifloor(accx) + 1; - const double ytarget = ifloor(accy) + 1; - const double xdistance = xtarget - accx; - const double ydistance = ytarget - accy; - double distdiff = xdistance * slope - ydistance; - - // exact corner - if (double_is_zero(distdiff)) - { - // move somewhat away from the corner - if (slope > 1.0) - { - accx = xtarget + EPSILON_VALUE * 2; - accy = ytarget + EPSILON_VALUE * 2 * slope; - } - else - { - accx = xtarget + EPSILON_VALUE * 2 / slope; - accy = ytarget + EPSILON_VALUE * 2; - } - return ADV_XY; - } - - // move to the boundary - double traveldist; - adv_type rc; - if (distdiff > 0.0) - { - traveldist = ydistance / slope; - rc = ADV_Y; - } - else - { - traveldist = xdistance; - rc = ADV_X; - } - - // and a little into the next cell, taking care - // not to go too far - if (distdiff < 0.0) - distdiff = -distdiff; - traveldist += std::min(EPSILON_VALUE * 10.0, 0.5 * distdiff / slope); - - accx += traveldist; - accy += traveldist * slope; - return rc; + r.dir *= -1; } -/* - * Mirror ray into positive quadrant or back. - * this.quad{x,y} are not touched (used for the flip back). - */ -void ray_def::flip() -{ - accx = 0.5 + quadx * (accx - 0.5); - accy = 0.5 + quady * (accy - 0.5); -} - -adv_type ray_def::advance() -{ - adv_type rc; - flip(); - rc = raw_advance_pos(); - flip(); - return rc; -} |