summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/ray.cc
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-10-30 12:59:00 +0100
committerRobert Vollmert <rvollmert@gmx.net>2009-11-01 21:45:24 +0100
commitb9aa144a7fd572ea1695e30d7736a5f10dd2d4e8 (patch)
tree3347e9117ed8d29013c50215efbab1c4e9f702be /crawl-ref/source/ray.cc
parent03350fc556e032072673562dc15f06920bc5fc87 (diff)
downloadcrawl-ref-b9aa144a7fd572ea1695e30d7736a5f10dd2d4e8.tar.gz
crawl-ref-b9aa144a7fd572ea1695e30d7736a5f10dd2d4e8.zip
Replace ray_def by a version using "diamond rays".
Think of the map tiled with squares (the cells). Previously, a ray was blocked by any part of an opaque cell except the very corners (to allow looking through diagonal maps -- we can move through those after all). In the new version, the rays are the same, but a dungeon feature is only considered to occupy the the central "diamond": convex hull of the mid points of the edges. The corners of the diamond are considered part of the feature, so vertically or horizontally adjacent walls still block. This has some effect on LOS: It's a bit more permissive on diagonals and around corners. The main advantage is that most rays will now have a footprint (the sequence of cells it passes through) that is like the old anti-aliased rays, without requiring any ray munging. TODO: * Make sure we don't hang because of stopping at a corner. * Implement proper bouncing. * Reenable setting/getting degrees for chaos beams.
Diffstat (limited to 'crawl-ref/source/ray.cc')
-rw-r--r--crawl-ref/source/ray.cc199
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;
-}