Пример #1
0
        private bool AddLineIntercepts(LineDef line)
        {
            int s1;
            int s2;

            // Avoid precision problems with two routines.
            if (trace.Dx > Fixed.FromInt(16) ||
                trace.Dy > Fixed.FromInt(16) ||
                trace.Dx < -Fixed.FromInt(16) ||
                trace.Dy < -Fixed.FromInt(16))
            {
                s1 = Geometry.PointOnDivLineSide(line.Vertex1.X, line.Vertex1.Y, trace);
                s2 = Geometry.PointOnDivLineSide(line.Vertex2.X, line.Vertex2.Y, trace);
            }
            else
            {
                s1 = Geometry.PointOnLineSide(trace.X, trace.Y, line);
                s2 = Geometry.PointOnLineSide(trace.X + trace.Dx, trace.Y + trace.Dy, line);
            }

            if (s1 == s2)
            {
                // Line isn't crossed.
                return(true);
            }

            // Hit the line.
            target.MakeFrom(line);

            var frac = InterceptVector(trace, target);

            if (frac < Fixed.Zero)
            {
                // Behind source.
                return(true);
            }

            // Try to early out the check.
            if (earlyOut && frac < Fixed.One && line.BackSector == null)
            {
                // Stop checking.
                return(false);
            }

            intercepts[interceptCount].Frac  = frac;
            intercepts[interceptCount].Line  = line;
            intercepts[interceptCount].Thing = null;
            interceptCount++;

            // Continue.
            return(true);
        }
Пример #2
0
        /// <summary>
        /// Returns true if strace crosses the given subsector successfully.
        /// </summary>
        private bool CrossSubsector(int subsectorNumber, int validCount)
        {
            var map       = world.Map;
            var subsector = map.Subsectors[subsectorNumber];
            var count     = subsector.SegCount;

            // Check lines.
            for (var i = 0; i < count; i++)
            {
                var seg  = map.Segs[subsector.FirstSeg + i];
                var line = seg.LineDef;

                // Allready checked other side?
                if (line.ValidCount == validCount)
                {
                    continue;
                }

                line.ValidCount = validCount;

                var v1 = line.Vertex1;
                var v2 = line.Vertex2;
                var s1 = Geometry.DivLineSide(v1.X, v1.Y, trace);
                var s2 = Geometry.DivLineSide(v2.X, v2.Y, trace);

                // Line isn't crossed?
                if (s1 == s2)
                {
                    continue;
                }

                occluder.MakeFrom(line);
                s1 = Geometry.DivLineSide(trace.X, trace.Y, occluder);
                s2 = Geometry.DivLineSide(targetX, targetY, occluder);

                // Line isn't crossed?
                if (s1 == s2)
                {
                    continue;
                }

                // The check below is imported from Chocolate Doom to
                // avoid crash due to two-sided lines with no backsector.
                if (line.BackSector == null)
                {
                    return(false);
                }

                // Stop because it is not two sided anyway.
                // Might do this after updating validcount?
                if ((line.Flags & LineFlags.TwoSided) == 0)
                {
                    return(false);
                }

                // Crosses a two sided line.
                var front = seg.FrontSector;
                var back  = seg.BackSector;

                // No wall to block sight with?
                if (front.FloorHeight == back.FloorHeight &&
                    front.CeilingHeight == back.CeilingHeight)
                {
                    continue;
                }

                // Possible occluder because of ceiling height differences.
                Fixed openTop;
                if (front.CeilingHeight < back.CeilingHeight)
                {
                    openTop = front.CeilingHeight;
                }
                else
                {
                    openTop = back.CeilingHeight;
                }

                // Because of ceiling height differences.
                Fixed openBottom;
                if (front.FloorHeight > back.FloorHeight)
                {
                    openBottom = front.FloorHeight;
                }
                else
                {
                    openBottom = back.FloorHeight;
                }

                // Quick test for totally closed doors.
                if (openBottom >= openTop)
                {
                    // Stop.
                    return(false);
                }

                var frac = InterceptVector(trace, occluder);

                if (front.FloorHeight != back.FloorHeight)
                {
                    var slope = (openBottom - sightZStart) / frac;
                    if (slope > bottomSlope)
                    {
                        bottomSlope = slope;
                    }
                }

                if (front.CeilingHeight != back.CeilingHeight)
                {
                    var slope = (openTop - sightZStart) / frac;
                    if (slope < topSlope)
                    {
                        topSlope = slope;
                    }
                }

                if (topSlope <= bottomSlope)
                {
                    // Stop.
                    return(false);
                }
            }

            // Passed the subsector ok.
            return(true);
        }