Ejemplo n.º 1
0
        private void CalculateFovQuadrant(fovStateT state)
        {
            LinkedList <bumpT> steepBumps   = new LinkedList <bumpT>();
            LinkedList <bumpT> shallowBumps = new LinkedList <bumpT>();
            // activeFields is sorted from shallow-to-steep.
            LinkedList <fieldT> activeFields = new LinkedList <fieldT>();

            activeFields.AddLast(new fieldT());
            activeFields.Last.Value.m_Shallow.m_Near = new Point2I(0, 1);
            activeFields.Last.Value.m_Shallow.m_Far  = new Point2I(state.m_Extent.m_X, 0);
            activeFields.Last.Value.m_Steep.m_Near   = new Point2I(1, 0);
            activeFields.Last.Value.m_Steep.m_Far    = new Point2I(0, state.m_Extent.m_Y);

            Point2I dest = new Point2I(0, 0);

            // Visit the source square exactly once (in quadrant 1).
            if (state.m_Quadrant.m_X == 1 && state.m_Quadrant.m_Y == 1)
            {
                ActIsBlocked(state, dest);
            }

            CLikeIterator <fieldT> currentField = new CLikeIterator <fieldT>(
                activeFields.First);
            int i    = 0;
            int j    = 0;
            int maxI = state.m_Extent.m_X + state.m_Extent.m_Y;

            // For each square outline
            for (i = 1; i <= maxI && activeFields.Count > 0; ++i)
            {
                int startJ = Max(0, i - state.m_Extent.m_X);
                int maxJ   = Min(i, state.m_Extent.m_Y);
                // Visit the nodes in the outline
                for (j = startJ; j <= maxJ && !currentField.IsAtEnd(); ++j)
                {
                    dest.m_X = i - j;
                    dest.m_Y = j;
                    VisitSquare(state, dest, currentField, steepBumps,
                                shallowBumps, activeFields);
                }
                currentField = new CLikeIterator <fieldT>(activeFields.First);
            }
        }
Ejemplo n.º 2
0
        private void VisitSquare(fovStateT state, Point2I dest,
                                 CLikeIterator <fieldT> currentField, LinkedList <bumpT> steepBumps,
                                 LinkedList <bumpT> shallowBumps, LinkedList <fieldT> activeFields)
        {
            // The top-left and bottom-right corners of the destination square.
            Point2I topLeft     = new Point2I(dest.m_X, dest.m_Y + 1);
            Point2I bottomRight = new Point2I(dest.m_X + 1, dest.m_Y);

            while (!currentField.IsAtEnd() &&
                   currentField.GetCurrent().m_Steep
                   .IsBelowOrContains(bottomRight))
            {
                // case ABOVE
                // The square is in case 'above'. This means that it is ignored
                // for the currentField. But the steeper fields might need it.
                currentField.GotoNext();
            }
            if (currentField.IsAtEnd())
            {
                // The square was in case 'above' for all fields. This means that
                // we no longer care about it or any squares in its diagonal rank.
                return;
            }

            // Now we check for other cases.
            if (currentField.GetCurrent().m_Shallow.IsAboveOrContains(topLeft))
            {
                // case BELOW
                // The shallow line is above the extremity of the square, so that
                // square is ignored.
                return;
            }
            // The square is between the lines in some way. This means that we
            // need to visit it and determine whether it is blocked.
            bool isBlocked = ActIsBlocked(state, dest);

            if (!isBlocked)
            {
                // We don't care what case might be left, because this square does
                // not obstruct.
                return;
            }

            if (currentField.GetCurrent().m_Shallow.IsAbove(bottomRight) &&
                currentField.GetCurrent().m_Steep.IsBelow(topLeft))
            {
                // case BLOCKING
                // Both lines intersect the square. This current field has ended.
                currentField.RemoveCurrent();
            }
            else if (currentField.GetCurrent().m_Shallow.IsAbove(bottomRight))
            {
                // case SHALLOW BUMP
                // The square intersects only the shallow line.
                AddShallowBump(topLeft, currentField.GetCurrent(), steepBumps,
                               shallowBumps);
                CheckField(currentField);
            }
            else if (currentField.GetCurrent().m_Steep.IsBelow(topLeft))
            {
                // case STEEP BUMP
                // The square intersects only the steep line.
                AddSteepBump(bottomRight, currentField.GetCurrent(), steepBumps,
                             shallowBumps);
                CheckField(currentField);
            }
            else
            {
                // case BETWEEN
                // The square intersects neither line. We need to split into two
                // fields.
                fieldT steeperField   = currentField.GetCurrent();
                fieldT shallowerField = new fieldT(currentField.GetCurrent());
                currentField.InsertBeforeCurrent(shallowerField);
                AddSteepBump(bottomRight, shallowerField, steepBumps, shallowBumps);
                currentField.GotoPrevious();
                if (!CheckField(currentField)) // did not remove
                {
                    currentField.GotoNext();   // point to the original element
                }
                AddShallowBump(topLeft, steeperField, steepBumps, shallowBumps);
                CheckField(currentField);
            }
        }