Add explanatory comments to fov.c and fix handling of centre-of-radiance.
authorMartin Read <martin@blackswordsonics.com>
Mon, 23 Sep 2013 19:38:26 +0000 (20:38 +0100)
committerMartin Read <martin@blackswordsonics.com>
Mon, 23 Sep 2013 19:38:26 +0000 (20:38 +0100)
fov.c

diff --git a/fov.c b/fov.c
index 8a5b672..dc10191 100644 (file)
--- a/fov.c
+++ b/fov.c
 #include <string.h>
 #include <math.h>
 
+/*! \brief Transverse-step delta-y for each octant
+ */
 int trn_dy[8] = {
     0, -1, 1, 0, 0, 1, -1, 0
 };
 
+/*! \brief Transverse-step delta-x for each octant
+ */
 int trn_dx[8] = {
     1, 0, 0, 1, -1, 0, 0, -1
 };
 
+/*! \brief Radial-step delta-y for each octant
+ */
 int rdl_dy[8] = {
     -1, 0, 0, 1, 1, 0, 0, -1
 };
 
+/*! \brief Radial-step delta-x for each octant
+ */
 int rdl_dx[8] = {
     0, 1, 1, 0, 0, -1, -1, 0
 };
 
 static void compute_row(Radiance *rad, int octant, int radius, double inmost_slope, double outmost_slope);
 
+/*! \brief Default blocking function
+ *
+ *  This function returns true if the specified coordinates are out of bounds
+ *  or the terrain at the specified position is opaque.
+ */
 static bool dflt_blk(int y, int x)
 {
     return ((y <= 0) || (x <= 0) || (y >= DUN_HEIGHT - 1) || (x >= DUN_WIDTH - 1) || (terrain_is_opaque(terrain[y][x])));
 }
 
+/*! \brief Function for marking affected cells as explored
+ *
+ *  This function marks the specified tile as explored, triggers a symbol
+ *  update, and returns true.
+ */
 static bool mark_explored(int y, int x, void *pvt)
 {
     mapflags[y][x] |= MAPFLAG_EXPLORED;
@@ -64,41 +82,52 @@ static bool mark_explored(int y, int x, void *pvt)
     return true;
 }
 
-/*! \fn
- *  \brief Return the inner (cardinal-wards) blocking limit of an octant-relative coordinate
+/*! \brief Return the inner (cardinal-wards) blocking limit of an octant-relative coordinate
  */
 static inline double inner_slope(int rdl, int trn)
 {
     return trn ? ((trn - 0.5) / ((double) rdl)) : 0.0;
 }
 
+/*! \brief Return the innermost (cardinal-wards) visible slope of an octant-relative coordinate
+ */
 static inline double inner_visible_slope(int rdl, int trn)
 {
     return trn ? ((trn - 0.5) / (rdl + 0.5)) : 0.0;
 }
-/*! \fn
- *  \brief Return the outer (diagonal-wards) blocking limit of an octant-relative coordinate
+
+/*! \brief Return the outer (diagonal-wards) blocking limit of an octant-relative coordinate
  */
+
 static inline double outer_slope(int rdl, int trn)
 {
     return (rdl == trn) ? 1.0 : ((trn + 0.5) / (double) rdl);
 }
 
+/*! \brief Return the outermost (diagonal-wards) visible slope of an octant-relative coordinate
+ */
+
 static inline double outer_visible_slope(int rdl, int trn)
 {
     return (rdl == trn) ? 1.0 : ((trn + 0.5) / (rdl - 0.5));
 }
 
+/*! \brief Reset the affected flags of a Radiance object
+ */
 void clear_radiance(Radiance *rad)
 {
     memset(&(rad->affected), '\0', sizeof rad->affected);
 }
 
+/*! \brief Start computing one octant of a Radiance
+ */
 static inline void compute_octant(Radiance *rad, int octant)
 {
     compute_row(rad, octant, 1, 0.0, 1.0);
 }
 
+/*! \brief Compute one (partial) row of a Radiance and recurse.
+ */
 static void compute_row(Radiance *rad, int octant, int radius, double inmost_slope, double outmost_slope)
 {
     int trn;
@@ -108,24 +137,44 @@ static void compute_row(Radiance *rad, int octant, int radius, double inmost_slo
     int outer_idx;
     int inner_idx;
     double isl;
-    double ivs;
-    double ovs;
+
+    /* 
+     * We should never get the slopes mismatched like this, but if we do,
+     * return immediately.
+     */
     if (inmost_slope >= outmost_slope)
     {
         return;
     }
+    /* 
+     * The inner_idx and outer_idx values are used to control which tiles of
+     * the current row we actually examine.
+     */
     inner_idx = 0.5 + (inmost_slope * radius);
     outer_idx = 0.5 + (outmost_slope * radius);
+    /*
+     * dx and dy - the position of the "cursor" relative to the centre of
+     * the potentially affected area - are calculated using the rdl_* and trn_*
+     * arrays.
+     */
     dx = radius * rdl_dx[octant] + outer_idx * trn_dx[octant];
     dy = radius * rdl_dy[octant] + outer_idx * trn_dy[octant];
+    /*
+     * Iterate over the range of transverse deflections from outer_idx to
+     * inner_idx.
+     */
     for (trn = outer_idx; trn >= inner_idx; --trn)
     {
+        /* Get the inner "grazing" slope of the diamond inside the tile. */
         isl = inner_slope(radius, trn);
+        /* Mark the tile being examined as affected. */
         rad->affected[MAX_FOV_RADIUS + dy][MAX_FOV_RADIUS + dx] = true;
         if (block_flag)
         {
+            /* If the previous tile was opaque... */
             if (rad->opaque_fun(dy + rad->centre_y, dx + rad->centre_x))
             {
+                /* ... then if this one is too, update the slope */
                 if (outmost_slope > isl)
                 {
                     outmost_slope = isl;
@@ -133,29 +182,50 @@ static void compute_row(Radiance *rad, int octant, int radius, double inmost_slo
             }
             else
             {
+                /* ... and if not, clear the blocking flag. */
                 block_flag = false;
             }
         }
         else
         {
+            /* Otherwise... */
             if (rad->opaque_fun(dy + rad->centre_y, dx + rad->centre_x))
             {
+                /* ... if the current tile is opaque, set the blocking flag. */
                 block_flag = true;
+                /* 
+                 * and if we're not examining the first tile of this strip,
+                 * and we're not examining the last row of the octant,
+                 * recursively examine the diagonalwards portion of the
+                 * next row.
+                 */
                 if ((trn < outer_idx) && (radius < rad->radius))
                 {
                     compute_row(rad, octant, radius + 1, outer_slope(radius, trn), outmost_slope);
                 }
+                /*
+                 * Update the outermost slope to reflect what is occluded by
+                 * this cell.
+                 */
                 if (outmost_slope > isl)
                 {
                     outmost_slope = isl;
                 }
             }
         }
+        /* 
+         * Advance whichever of dx or dy is the transverse coordinate for this
+         * octant. 
+         */
         dx -= trn_dx[octant];
         dy -= trn_dy[octant];
     }
     if ((radius < rad->radius) && !block_flag)
     {
+        /*
+         * If we haven't reached the last row, and the last tile we examined
+         * in this row wasn't opaque, recursively compute the next row.
+         */
         compute_row(rad, octant, radius + 1, inmost_slope, outmost_slope);
     }
 }
@@ -163,17 +233,19 @@ static void compute_row(Radiance *rad, int octant, int radius, double inmost_slo
 void compute_radiance(Radiance *rad)
 {
     int oct;
+    /* Compute the eight octants in order. */
     for (oct = 0; oct < 8; ++oct)
     {
         compute_octant(rad, oct);
     }
+    /* Mark the centre as (un)affected according to the Radiance's setup. */
     if (rad->exclude_centre)
     {
         rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = false;
     }
     else
     {
-        rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = false;
+        rad->affected[MAX_FOV_RADIUS][MAX_FOV_RADIUS] = true;
     }
 }
 
@@ -183,6 +255,7 @@ void resolve_radiance(Radiance *rad)
     int x;
     int i;
     int j;
+
     switch (rad->order)
     {
     case Reo_ascending:
@@ -219,5 +292,6 @@ void compute_fov(void)
     compute_radiance(&player_fov);
     resolve_radiance(&player_fov);
 }
+
 /* fov.c */
 // vim:cindent