示例#1
0
 /**
  * Set all the default options. You must call this option when you
  * create a new settings data structure.
  *
  * These settings are the defaults used:
  *
  * - shape: FOV_SHAPE_CIRCLE_PRECALCULATE
  * - corner_peek: FOV_CORNER_NOPEEK
  * - opaque_apply: FOV_OPAQUE_APPLY
  *
  * Callbacks still need to be set up after calling this function.
  *
  * \param settings data structure containing settings.
  */
 public void fov_settings_init(fov_settings_type settings)
 {
     settings.shape                  = fov_shape_type.FOV_SHAPE_CIRCLE_PRECALCULATE;
     settings.corner_peek            = fov_corner_peek_type.FOV_CORNER_NOPEEK;
     settings.opaque_apply           = fov_opaque_apply_type.FOV_OPAQUE_APPLY;
     settings.m_OnOpaqueEventHandler = null;
     settings.m_OnApplyEventHandler  = null;
     settings.heights.Clear();
     settings.numheights = 0;
 }
示例#2
0
        /**
         * Calculate a full circle field of view from a source at (x,y).
         *
         * \param settings  data structure containing settings.
         * \param map map data structure to be passed to callbacks.
         * \param source  data structure holding source of light.
         * \param source_x x-axis coordinate from which to start.
         * \param source_y y-axis coordinate from which to start.
         * \param radius Euclidean distance from (x,y) after which to stop.
         */
        public void fov_circle(fov_settings_type settings, map _map, Color source, int source_x, int source_y, uint radius)
        {
            fov_private_data_type data = new fov_private_data_type();

            data.settings = settings;
            data._map     = _map;
            data.source   = source;
            data.source_x = source_x;
            data.source_y = source_y;
            data.radius   = radius;

            _fov_circle(data);
        }
示例#3
0
        private static uint height(fov_settings_type settings, int x, uint maxdist)
        {
            if (maxdist > settings.numheights)
            {
                settings.numheights = maxdist;
            }

            if (settings.heights != null)
            {
                if (!settings.heights.ContainsKey(maxdist - 1))
                {
                    settings.heights.Add(maxdist - 1, precalculate_heights(maxdist));
                }
                if (settings.heights.ContainsKey(maxdist - 1))
                {
                    List <uint> val = null;
                    settings.heights.TryGetValue(maxdist - 1, out val);
                    return(val[Mathf.Abs(x)]);
                }
            }
            return(0);
        }
示例#4
0
        /* Octants -------------------------------------------------------- */

        private static void fov_octant(
            fov_private_data_type data, int dx, float start_slope, float end_slope,
            int signx, int signy, char rx, char ry, bool apply_edge, bool apply_diag)
        {
            int               x = 0;
            int               y = 0;
            int               dy, dy0, dy1;
            uint              h            = 0;
            int               prev_blocked = -1;
            float             end_slope_next;
            fov_settings_type settings = data.settings;

            if (dx == 0)
            {
                fov_octant(data, dx + 1, start_slope, end_slope, signx, signy, rx, ry, apply_edge, apply_diag);
                return;
            }
            else if ((uint)dx > data.radius)
            {
                return;
            }

            dy0 = (int)(0.5f + ((float)dx) * start_slope);
            dy1 = (int)(0.5f + ((float)dx) * end_slope);

            if (rx == 'x')
            {
                x = data.source_x + signx * dx;
            }
            else if (rx == 'y')
            {
                y = data.source_y + signx * dx;
            }

            if (ry == 'y')
            {
                y = data.source_y + signy * dy0;
            }
            else if (ry == 'x')
            {
                x = data.source_x + signy * dy0;
            }



            if (!apply_diag && dy1 == dx)
            {
                /* We do diagonal lines on every second octant, so they don't get done twice. */
                --dy1;
            }

            switch (settings.shape)
            {
            case fov_shape_type.FOV_SHAPE_CIRCLE_PRECALCULATE:
                h = height(settings, dx, data.radius);
                break;

            case fov_shape_type.FOV_SHAPE_CIRCLE:
                h = (uint)Mathf.Sqrt((float)(data.radius * data.radius - dx * dx));
                break;

            case fov_shape_type.FOV_SHAPE_OCTAGON:
                h = (uint)(data.radius - dx) << 1;
                break;

            default:
                h = data.radius;
                break;
            }
            ;

            if ((uint)dy1 > h)
            {
                if (h == 0)
                {
                    return;
                }
                dy1 = (int)h;
            }

            /*fprintf(stderr, "(%2d) = [%2d .. %2d] (%f .. %f), h=%d,edge=%d\n",
             *      dx, dy0, dy1, ((float)dx)*start_slope,
             *      0.5f + ((float)dx)*end_slope, h, apply_edge);*/

            for (dy = dy0; dy <= dy1; ++dy)
            {
                if (ry == 'y')
                {
                    y = data.source_y + signy * dy;
                }
                else if (ry == 'x')
                {
                    x = data.source_x + signy * dy;
                }

                if (settings.m_OnOpaqueEventHandler(data._map, x, y))
                {
                    if (settings.opaque_apply == fov_opaque_apply_type.FOV_OPAQUE_APPLY && (apply_edge || dy > 0))
                    {
                        settings.m_OnApplyEventHandler(data._map, x, y, dx, dy, data.source);
                    }
                    if (prev_blocked == 0)
                    {
                        end_slope_next = fov_slope((float)dx + 0.5f, (float)dy - 0.5f);
                        fov_octant(data, dx + 1, start_slope, end_slope_next, signx, signy, rx, ry, apply_edge, apply_diag);
                    }
                    prev_blocked = 1;
                }
                else
                {
                    if (apply_edge || dy > 0)
                    {
                        settings.m_OnApplyEventHandler(data._map, x, y, dx, dy, data.source);
                    }
                    if (prev_blocked == 1)
                    {
                        start_slope = fov_slope((float)dx - 0.5f, (float)dy - 0.5f);
                    }
                    prev_blocked = 0;
                }
            }

            if (prev_blocked == 0)
            {
                fov_octant(data, dx + 1, start_slope, end_slope, signx, signy, rx, ry, apply_edge, apply_diag);
            }
        }
示例#5
0
        /**
         * Calculate a field of view from source at (x,y), pointing
         * in the given direction and with the given angle. The larger
         * the angle, the wider, "less focused" the beam. Each side of the
         * line pointing in the direction from the source will be half the
         * angle given such that the angle specified will be represented on
         * the raster.
         *
         * \param settings data structure containing settings.
         * \param map  map data structure to be passed to callbacks.
         * \param source data structure holding source of light.
         * \param source_x x-axis coordinate from which to start.
         * \param source_y y-axis coordinate from which to start.
         * \param radius Euclidean distance from (x,y) after which to stop.
         * \param direction One of eight directions the beam of light can point.
         * \param angle The angle at the base of the beam of light, in degrees.
         */
        public void fov_beam(fov_settings_type settings, map _map, Color source, int source_x, int source_y,
                             uint radius, fov_direction_type direction, float angle)
        {
            fov_private_data_type data = new fov_private_data_type();
            float start_slope, end_slope, a;

            data.settings = settings;
            data._map     = _map;
            data.source   = source;
            data.source_x = source_x;
            data.source_y = source_y;
            data.radius   = radius;

            if (angle <= 0.0f)
            {
                return;
            }
            else if (angle >= 360.0f)
            {
                _fov_circle(data);
            }

            /* Calculate the angle as a percentage of 45 degrees, halved (for
             * each side of the centre of the beam). e.g. angle = 180.0f means
             * half the beam is 90.0 which is 2x45, so the result is 2.0.
             */
            a = angle / 90.0f;

            if (direction == fov_direction_type.FOV_EAST)
            {
                end_slope = betweenf(a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    start_slope = betweenf(2.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    end_slope = betweenf(a - 2.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    start_slope = betweenf(4.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f);
                }
            }
            if (direction == fov_direction_type.FOV_WEST)
            {
                end_slope = betweenf(a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    start_slope = betweenf(2.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    end_slope = betweenf(a - 2.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    start_slope = betweenf(4.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f);
                }
            }
            if (direction == fov_direction_type.FOV_NORTH)
            {
                end_slope = betweenf(a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    start_slope = betweenf(2.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    end_slope = betweenf(a - 2.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    start_slope = betweenf(4.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f);
                }
            }
            if (direction == fov_direction_type.FOV_SOUTH)
            {
                end_slope = betweenf(a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    start_slope = betweenf(2.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    end_slope = betweenf(a - 2.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    start_slope = betweenf(4.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f);
                }
            }



            if (direction == fov_direction_type.FOV_NORTHEAST)
            {
                start_slope = betweenf(1.0f - a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    end_slope = betweenf(a - 1.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    start_slope = betweenf(3.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    end_slope = betweenf(a - 3.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope);
                }
            }
            if (direction == fov_direction_type.FOV_NORTHWEST)
            {
                start_slope = betweenf(1.0f - a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    end_slope = betweenf(a - 1.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    start_slope = betweenf(3.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    end_slope = betweenf(a - 3.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope);
                }
            }
            if (direction == fov_direction_type.FOV_SOUTHEAST)
            {
                start_slope = betweenf(1.0f - a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    end_slope = betweenf(a - 1.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    start_slope = betweenf(3.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    end_slope = betweenf(a - 3.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope);
                }
            }
            if (direction == fov_direction_type.FOV_SOUTHWEST)
            {
                start_slope = betweenf(1.0f - a, 0.0f, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f);
                _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f);

                if (a - 1.0f > Mathf.Epsilon)
                { /* a > 1.0f */
                    end_slope = betweenf(a - 1.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope);
                }
                if (a - 2.0f > Mathf.Epsilon)
                { /* a > 2.0f */
                    start_slope = betweenf(3.0f - a, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f);
                }
                if (a - 3.0f > Mathf.Epsilon)
                { /* a > 3.0f */
                    end_slope = betweenf(a - 3.0f, 0.0f, 1.0f);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope);
                    _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope);
                }
            }
        }
示例#6
0
 /**
  * Free any memory that may have been cached in the settings
  * structure.
  *
  * \param settings  data structure containing settings.
  */
 public void fov_settings_free(fov_settings_type settings)
 {
     settings.heights.Clear();
     settings.numheights = 0;
 }
示例#7
0
 /**
  * Set the function used to apply lighting to a map tile.
  *
  * \param settings data structure containing settings.
  * \param f The function called to apply lighting to a map tile.
  */
 public void fov_settings_set_apply_lighting_function(fov_settings_type settings, OnApplyEventHandler eventHandler)
 {
     settings.m_OnApplyEventHandler = eventHandler;
 }
示例#8
0
 /**
  * Set the function used to test whether a map tile is opaque.
  *
  * \param settings data structure containing settings.
  * \param f The function called to test whether a map tile is opaque.
  */
 public void fov_settings_set_opacity_test_function(fov_settings_type settings, OnOpaqueEventHandler eventHandler)
 {
     settings.m_OnOpaqueEventHandler = eventHandler;
 }
示例#9
0
 /**
  * Whether to call the apply callback on opaque tiles.
  *
  * \param settings  data structure containing settings.
  * \param value One of the following values:
  *
  * - FOV_OPAQUE_APPLY \b (default): Call apply callback on opaque tiles.
  * - FOV_OPAQUE_NOAPPLY: Do not call the apply callback on opaque tiles.
  */
 public void fov_settings_set_opaque_apply(fov_settings_type settings, fov_opaque_apply_type value)
 {
     settings.opaque_apply = value;
 }
示例#10
0
 /**
  * <em>NOT YET IMPLEMENTED</em>.
  *
  * Set whether sources will peek around corners.
  *
  * \param settings data structure containing settings.
  * \param value One of the following values:
  *
  * - FOV_CORNER_PEEK \b (default): Renders:
  * \verbatim
  * ........
  * ........
  * ........
  * ..@#
  * ...#
  * \endverbatim
  * - FOV_CORNER_NOPEEK: Renders:
  * \verbatim
  * ......
  * .....
  * ....
  * ..@#
  * ...#
  * \endverbatim
  */
 public void fov_settings_set_corner_peek(fov_settings_type settings, fov_corner_peek_type value)
 {
     settings.corner_peek = value;
 }
示例#11
0
 /**
  * Set the shape of the field of view.
  *
  * \param settings  data structure containing settings.
  * \param value One of the following values, where R is the radius:
  *
  * - FOV_SHAPE_CIRCLE_PRECALCULATE \b (default): Limit the FOV to a
  * circle with radius R by precalculating, which consumes more memory
  * at the rate of 4*(R+2) bytes per R used in calls to fov_circle.
  * Each radius is only calculated once so that it can be used again.
  * Use fov_free() to free this precalculated data's memory.
  *
  * - FOV_SHAPE_CIRCLE: Limit the FOV to a circle with radius R by
  * calculating on-the-fly.
  *
  * - FOV_SHAPE_OCTOGON: Limit the FOV to an octogon with maximum radius R.
  *
  * - FOV_SHAPE_SQUARE: Limit the FOV to an R*R square.
  */
 public void fov_settings_set_shape(fov_settings_type settings, fov_shape_type value)
 {
     settings.shape = value;
 }