Ejemplo n.º 1
0
        public LaserRay SetLaserCollisionlessIntersect(LaserSource src, FPoint e, LaserRayTerminator t)
        {
            if ((Start - e).LengthSquared() < FloatMath.EPSILON4)
            {
                src.Lasers.Remove(this);

                return(Source?.SetLaserCollisionlessIntersect(src, Source.End, t));
            }

            End        = e;
            Terminator = t;
            _length    = null;
            _angle     = null;

            TerminatorRays.Clear();

#if DEBUG
            if (!Start.IsValid)
            {
                SAMLog.Error("LASER::Assert_3-SV", "!Start.IsValid");
            }
            if (!End.IsValid)
            {
                SAMLog.Error("LASER::Assert_3-EV", "!End.IsValid");
            }
            if ((End - Start).LengthSquared() < FloatMath.EPSILON7 * FloatMath.EPSILON7)
            {
                SAMLog.Error("LASER::Assert_3-ESV", "(End - Start).LengthSquared() < FloatMath.EPSILON7 * FloatMath.EPSILON7");
            }
#endif

            return(this);
        }
Ejemplo n.º 2
0
        private bool TestForLaserCollision(LaserSource src1, LaserRay ray1, bool nofault)
        {
            float       minU         = float.MaxValue;
            FPoint      minP1        = FPoint.Zero;
            FPoint      minP2        = FPoint.Zero;
            LaserRay    minRay2      = null;
            LaserSource minSrc2      = null;
            bool        minTermOther = false;


            foreach (var src2 in Sources)
            {
                foreach (var ray2 in src2.Lasers)
                {
                    if (src1 == src2 && ray1 == ray2)
                    {
                        continue;
                    }

                    // (Not only) Direct (parallel) Collision
                    FPoint intersect;
                    float  u;
                    if (RayParallality(ray1.Start, ray1.End, ray1.SourceDistance, ray2.Start, ray2.End, ray2.SourceDistance, src1 == src2, out intersect, out u))
                    {
                        if (u < minU)
                        {
                            var pp1 = intersect.ProjectPointOntoLineSegment(ray1.Start, ray1.End);
                            var pp2 = intersect.ProjectPointOntoLineSegment(ray2.Start, ray2.End);

                            if ((pp1 - pp2).LengthSquared() < RAY_WIDTH * RAY_WIDTH)
                            {
                                minU         = u;
                                minP1        = pp1;
                                minP2        = pp2;
                                minRay2      = ray2;
                                minSrc2      = src2;
                                minTermOther = true;
                                continue;
                            }
                        }
                    }

                    // Normal intersection collision
                    if (Math2D.LineIntersectionExt(ray1.Start, ray1.End, ray2.Start, ray2.End, -0.1f, out intersect, out u, out _))
                    {
                        if (u < minU)
                        {
                            var pp1 = intersect.ProjectPointOntoLineSegment(ray1.Start, ray1.End);
                            var pp2 = intersect.ProjectPointOntoLineSegment(ray2.Start, ray2.End);

                            if ((pp1 - pp2).LengthSquared() < RAY_WIDTH * RAY_WIDTH)
                            {
                                minU         = u;
                                minP1        = pp1;
                                minP2        = pp2;
                                minRay2      = ray2;
                                minSrc2      = src2;
                                minTermOther = true;
                                continue;
                            }
                        }
                    }
                }
            }

            // Collision with other intersection

            foreach (var src2 in Sources)
            {
                foreach (var ray2 in src2.Lasers)
                {
                    if (ray2.Terminator != LaserRayTerminator.LaserMultiTerm &&
                        ray2.Terminator != LaserRayTerminator.LaserFaultTerm &&
                        ray2.Terminator != LaserRayTerminator.LaserSelfTerm)
                    {
                        continue;
                    }

                    var hpu = ray2.End.ProjectOntoLine(ray1.Start, ray1.End);
                    if (hpu < minU)
                    {
                        FPoint hp = ray1.Start + (ray1.End - ray1.Start) * hpu;

                        if ((hp - ray2.End).LengthSquared() < RAY_WIDTH)
                        {
                            minU         = hpu;
                            minP1        = hp;
                            minRay2      = ray2;
                            minSrc2      = src2;
                            minTermOther = false;
                        }
                    }
                }
            }

            // Take best

            if (minRay2 != null)
            {
                if (!minTermOther)
                {
                    // we hit another ray intersection

                    ray1 = ray1.SetLaserIntersect(src1, minP1, minRay2, minSrc2, LaserRayTerminator.LaserMultiTerm);
                    if (ray1 != null)
                    {
                        foreach (var termray in minRay2.TerminatorRays)
                        {
                            if (termray.Item2 != minSrc2)
                            {
                                termray.Item1.TerminatorRays.Add(Tuple.Create(ray1, src1));
                            }
                        }
                        minRay2.TerminatorRays.Add(Tuple.Create(ray1, src1));
                    }

                    return(true);
                }
                else if (nofault)
                {
                    // nofault mode - just terminate this one

                    ray1 = ray1.SetLaserCollisionlessIntersect(src1, minP1, LaserRayTerminator.LaserFaultTerm);

                    return(true);
                }
                else if (src1 == minSrc2)
                {
                    // we hit ourself

                    ray1 = ray1.SetLaserCollisionlessIntersect(src1, minP1, LaserRayTerminator.LaserSelfTerm);
                    if (ray1 != null)
                    {
                        minRay2.SelfCollRays.Add(ray1);
                        foreach (var r in ray1.SelfCollRays)
                        {
                            _faultRays.Add(Tuple.Create(r, src1));
                        }
                        ray1.SelfCollRays.Clear();
                    }

                    return(true);
                }
                else
                {
                    // we hit someone else

                    ray1 = ray1.SetLaserIntersect(src1, minP1, minRay2, minSrc2, LaserRayTerminator.LaserMultiTerm);
                    if (ray1 != null)
                    {
                        foreach (var r in ray1.SelfCollRays)
                        {
                            _faultRays.Add(Tuple.Create(r, src1));
                        }
                        ray1.SelfCollRays.Clear();
                    }

                    CutRayAndUpdate(minSrc2, minRay2, minP2, src1, ray1);

                    return(true);
                }
            }


            return(false);
        }