summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-10-30 13:08:22 +0100
committerRobert Vollmert <rvollmert@gmx.net>2009-11-01 21:45:24 +0100
commitb456d4c4fa57ab3eebfce79af43efaf457303f7e (patch)
tree6cefdfe82ec9d2a97a38c74abd3a49ef56f5e031
parentb9aa144a7fd572ea1695e30d7736a5f10dd2d4e8 (diff)
downloadcrawl-ref-b456d4c4fa57ab3eebfce79af43efaf457303f7e.tar.gz
crawl-ref-b456d4c4fa57ab3eebfce79af43efaf457303f7e.zip
Adapt los.cc to new ray_defs.
* Adapt los_ray. * Register rays using geom::ray. * Change cellray comparison functions (remove slope_diff which I didn't understand, add first_diag which prefers rays that start on diagonals for easier meph cloud targetting) The rays that are actually being cast may need changing. For now, rays that hit diamond corners are simply discarded.
-rw-r--r--crawl-ref/source/los.cc129
1 files changed, 55 insertions, 74 deletions
diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc
index 3a4f9267fd..69be2ec42c 100644
--- a/crawl-ref/source/los.cc
+++ b/crawl-ref/source/los.cc
@@ -53,6 +53,7 @@
#include "debug.h"
#include "directn.h"
#include "externs.h"
+#include "geom2d.h"
#include "losparam.h"
#include "player.h"
#include "ray.h"
@@ -158,27 +159,40 @@ struct los_ray : public ray_def
unsigned int start;
unsigned int length;
- los_ray(double ax, double ay, double s)
- : ray_def(ax, ay, s), length(0)
+ los_ray(geom::ray _r)
+ : ray_def(_r), length(0)
{
}
// Shoot a ray from the given start point (accx, accy) with the given
// slope, bounded by the pre-calc bounds function.
// Returns the cells it travels through, excluding the origin.
+ // Returns an empty vector if this was a bad ray.
std::vector<coord_def> footprint()
{
std::vector<coord_def> cs;
los_ray copy = *this;
coord_def c;
+ coord_def old;
int cellnum;
for (cellnum = 0; true; ++cellnum)
{
- copy.raw_advance_pos();
+ old = c;
+ if (!copy.advance())
+ {
+//#ifdef DEBUG_DIAGNOSTICS
+// mprf(MSGCH_DIAGNOSTICS,
+// "discarding corner ray (%f,%f) + t*(%f,%f)",
+// r.start.x, r.start.y, r.dir.x, r.dir.y);
+//#endif
+ cs.clear();
+ break;
+ }
c = copy.pos();
if (!bds_precalc(c))
break;
cs.push_back(c);
+ ASSERT((c - old).rdist() == 1);
}
return cs;
}
@@ -218,7 +232,7 @@ struct cellray
unsigned int end; // Relative index (inside ray) of end cell.
cellray(const los_ray& r, unsigned int e)
- : ray(r), end(e), imbalance(-1), slope_diff(-1)
+ : ray(r), end(e), imbalance(-1), first_diag(false)
{
}
@@ -238,7 +252,7 @@ struct cellray
// Parameters used in find_ray. These need to be calculated
// only for the minimal cellrays.
int imbalance;
- double slope_diff;
+ bool first_diag;
void calc_params();
};
@@ -253,16 +267,12 @@ bool _is_better(const cellray& a, const cellray& b)
ASSERT(a.target() == b.target());
// calc_params() has been called.
ASSERT(a.imbalance >= 0 && b.imbalance >= 0);
- if (a.end < b.end)
- return (true);
- else if (a.end > b.end)
- return (false);
- else if (a.imbalance < b.imbalance)
+ if (a.imbalance < b.imbalance)
return (true);
else if (a.imbalance > b.imbalance)
return (false);
else
- return (a.slope_diff < b.slope_diff);
+ return (a.first_diag);
}
enum compare_type
@@ -381,12 +391,12 @@ static std::vector<int> _find_minimal_cellrays()
}
// Create and register the ray defined by the arguments.
-static void _register_ray(double accx, double accy, double slope)
+static void _register_ray(geom::ray r)
{
- los_ray ray = los_ray(accx, accy, slope);
+ los_ray ray = los_ray(r);
std::vector<coord_def> coords = ray.footprint();
- if (_is_duplicate_ray(coords))
+ if (coords.empty() || _is_duplicate_ray(coords))
return;
ray.start = ray_coords.size();
@@ -482,8 +492,8 @@ void raycast()
// register perpendiculars FIRST, to make them top choice
// when selecting beams
- _register_ray(0.5, 0.5, 1000.0);
- _register_ray(0.5, 0.5, 0.0);
+ _register_ray(geom::ray(0.6, 0.5, 0.0, 1.0));
+ _register_ray(geom::ray(0.5, 0.6, 1.0, 0.0));
// For a slope of M = y/x, every x we move on the X axis means
// that we move y on the y axis. We want to look at the resolution
@@ -507,21 +517,14 @@ void raycast()
const int xangle = xyangles[i].first;
const int yangle = xyangles[i].second;
- const double slope = ((double)(yangle)) / xangle;
- const double rslope = ((double)(xangle)) / yangle;
- for (int intercept = 1; intercept <= LOS_INTERCEPT_MULT*yangle; ++intercept )
+ for (int intercept = 1; intercept < LOS_INTERCEPT_MULT*yangle; ++intercept )
{
double xstart = ((double)intercept) / (LOS_INTERCEPT_MULT*yangle);
- double ystart = 1;
-
- // now move back just inside the cell
- // y should be "about to change"
- xstart -= EPSILON_VALUE * xangle;
- ystart -= EPSILON_VALUE * yangle;
+ double ystart = 0.5;
- _register_ray(xstart, ystart, slope);
+ _register_ray(geom::ray(xstart, ystart, xangle, yangle));
// also draw the identical ray in octant 2
- _register_ray(ystart, xstart, rslope);
+ _register_ray(geom::ray(ystart, xstart, yangle, xangle));
}
}
@@ -529,52 +532,30 @@ void raycast()
_create_blockrays();
}
-static void _set_ray_quadrant(ray_def& ray, int sx, int sy, int tx, int ty)
-{
- ray.quadx = tx >= sx ? 1 : -1;
- ray.quady = ty >= sy ? 1 : -1;
-}
-
-static const double VERTICAL_SLOPE = 10000.0;
-static double _calc_slope(double x, double y)
-{
- if (double_is_zero(x))
- return (VERTICAL_SLOPE);
-
- const double slope = y / x;
- return (slope > VERTICAL_SLOPE ? VERTICAL_SLOPE : slope);
-}
-
-static double _slope_factor(const ray_def &ray)
-{
- double xdiff = fabs(ray.accx - 0.5), ydiff = fabs(ray.accy - 0.5);
-
- if (double_is_zero(xdiff) && double_is_zero(ydiff))
- return ray.slope;
-
- const double slope = _calc_slope(ydiff, xdiff);
- return (slope + ray.slope) / 2.0;
-}
-
static int _imbalance(ray_def ray, const coord_def& target)
{
int imb = 0;
int diags = 0, straights = 0;
while (ray.pos() != target)
{
- adv_type adv = ray.advance();
- if (adv == ADV_XY)
- {
- straights = 0;
- if (++diags > imb)
- imb = diags;
- diags++;
- }
- else
+ coord_def old = ray.pos();
+ if (!ray.advance())
+ ASSERT(false);
+ switch((ray.pos() - old).abs())
{
+ case 1:
diags = 0;
if (++straights > imb)
imb = straights;
+ break;
+ case 2:
+ straights = 0;
+ if (++diags > imb)
+ imb = diags;
+ break;
+ default:
+ ASSERT(false);
+ break;
}
}
return imb;
@@ -584,7 +565,7 @@ void cellray::calc_params()
{
coord_def trg = target();
imbalance = _imbalance(ray, trg);
- slope_diff = _slope_factor(ray) - _calc_slope(trg.x, trg.y);
+ first_diag = ((*this)[0].abs() == 2);
}
// Find ray in positive quadrant.
@@ -687,14 +668,14 @@ bool find_ray(const coord_def& source, const coord_def& target,
return (false);
if (signx < 0)
- ray.accx = 1.0 - ray.accx;
+ ray.r.start.x = 1.0 - ray.r.start.x;
if (signy < 0)
- ray.accy = 1.0 - ray.accy;
-
- ray.accx += source.x;
- ray.accy += source.y;
+ ray.r.start.y = 1.0 - ray.r.start.y;
+ ray.r.dir.x *= signx;
+ ray.r.dir.y *= signy;
- _set_ray_quadrant(ray, source.x, source.y, target.x, target.y);
+ ray.r.start.x += source.x;
+ ray.r.start.y += source.y;
return (true);
}
@@ -735,11 +716,11 @@ dungeon_feature_type ray_blocker(const coord_def& source,
void fallback_ray(const coord_def& source, const coord_def& target,
ray_def& ray)
{
- ray.accx = source.x + 0.5;
- ray.accy = source.y + 0.5;
+ ray.r.start.x = source.x + 0.5;
+ ray.r.start.y = source.y + 0.5;
coord_def diff = target - source;
- ray.slope = _calc_slope(std::abs(diff.x), std::abs(diff.y));
- _set_ray_quadrant(ray, source.x, source.y, target.x, target.y);
+ ray.r.dir.x = diff.x;
+ ray.r.dir.y = diff.y;
}
// Count the number of matching features between two points along