Ejemplo n.º 1
0
 internal InteractiveGenerationContext(List <Segment> segments, Quadtree quadtree, DebugData debugData, PriorityQueue <Segment, int> priorityQueue)
 {
     this.segments        = segments;
     this.quadtree        = quadtree;
     this.debugData       = debugData;
     this.priorityQueue   = priorityQueue;
     globalDerivationStep = 0;
     ended = false;
 }
Ejemplo n.º 2
0
        public static void Spawn(Segment segment, int density, float radius, Quadtree quadtree, ref List <Allotment> newAllotments)
        {
            Vector2 segmentCenter = (segment.End + segment.Start) * 0.5f;

            for (int i = 0; i < density; i++)
            {
                float   randomAngle  = UnityEngine.Random.value * 2.0f * Mathf.PI;
                float   randomRadius = UnityEngine.Random.value * radius;
                Vector2 center       = new Vector2(
                    segmentCenter.x + randomRadius * Mathf.Sin(randomAngle),
                    segmentCenter.y + randomRadius * Mathf.Cos(randomAngle)
                    );
                Allotment newAllotment;
                if (SpawnBuilding(center, segment.Direction, quadtree, out newAllotment, newAllotments))
                {
                    newAllotments.Add(newAllotment);
                }
            }
        }
Ejemplo n.º 3
0
        public static void Generate(out List <Segment> segments, out Quadtree quadtree, out DebugData debugData)
        {
            Segment root1 = new Segment(new Vector2(0, 0), new Vector2(Config.highwaySegmentLength, 0), true, false);
            Segment root2 = new Segment(new Vector2(0, 0), new Vector2(-Config.highwaySegmentLength, 0), true, false);

            root2.Branches.Add(root1);
            root1.Branches.Add(root2);

            segments = new List <Segment>();
            quadtree = new Quadtree(Config.QuadtreeParams, Config.quadtreeMaxObjects, Config.quadtreeMaxLevels);

            PriorityQueue <Segment, int> priorityQueue = new PriorityQueue <Segment, int>(new Comparison <int>((i1, i2) => i2.CompareTo(i1)));

            priorityQueue.Enqueue(root1, 0);
            priorityQueue.Enqueue(root2, 0);

            debugData = new DebugData();
            int derivationStep = 0;

            while (priorityQueue.Count > 0 && segments.Count < Config.segmentCountLimit && derivationStep++ < Config.derivationStepLimit)
            {
                var item    = priorityQueue.Dequeue();
                var segment = item.Value;
                if (LocalConstraints(segment, segments, quadtree, debugData))
                {
                    segment.SetupBranchLinks();
                    AddSegment(segment, segments, quadtree);
                    var queueItems   = GlobalGoals(segment);
                    int basePriority = item.Priority + 1;
                    foreach (var queueItem in queueItems)
                    {
                        priorityQueue.Enqueue(queueItem.Item1, basePriority + queueItem.Item2);
                    }
                }
            }

            // DEBUG:
            if (derivationStep == Config.derivationStepLimit)
            {
                Debug.Log("generation was interrupted for security reasons");
            }
        }
Ejemplo n.º 4
0
        static bool SpawnBuilding(Vector2 center, float direction, Quadtree quadtree, out Allotment allotment, List <Allotment> allotments)
        {
            allotment = new Allotment(default(Vector2),
                                      0,
                                      UnityEngine.Random.Range(Config.allotmentMinHalfDiagonal, Config.allotmentMaxHalfDiagonal),
                                      UnityEngine.Random.Range(Config.allotmentMinAspect, Config.allotmentMaxAspect));
            allotment.UpdateCenterAndDirection(center, direction);
            bool allow = false;

            for (int j = 0; j < Config.allotmentPlacementLoopLimit; j++)
            {
                int     c = 0;
                Vector2 offset;
                var     colliders = quadtree.Retrieve(allotment.GetCollider().GetAABB());
                for (int k = 0; k < colliders.Count && (c == 0 || j < Config.allotmentPlacementLoopLimit - 1); k++)
                {
                    if (allotment.GetCollider().Collide(((ICollidable)colliders[k].reference).GetCollider(), out offset))
                    {
                        c++;
                        allotment.Center = (allotment.Center + offset);
                    }
                }
                for (int k = 0; k < allotments.Count && (c == 0 || j < Config.allotmentPlacementLoopLimit - 1); k++)
                {
                    if (allotment.GetCollider().Collide(allotments[k].GetCollider(), out offset))
                    {
                        c++;
                        allotment.Center = (allotment.Center + offset);
                    }
                }
                if (c == 0)
                {
                    allow = true;
                    break;
                }
            }
            return(allow);
        }
Ejemplo n.º 5
0
        public static InteractiveGenerationContext BeginInteractiveGeneration()
        {
            List <Segment> segments;
            Quadtree       quadtree;
            DebugData      debugData;

            debugData = new DebugData();

            Segment root1 = new Segment(new Vector2(0, 0), new Vector2(Config.highwaySegmentLength, 0), true, false);

            //Segment root2 = new Segment(new Vector2(0, 0), new Vector2(-Config.HIGHWAY_SEGMENT_LENGTH, 0), true, false);
            //root2.Branches.Add(root1);
            //root1.Branches.Add(root2);

            segments = new List <Segment>();
            quadtree = new Quadtree(Config.QuadtreeParams, Config.quadtreeMaxObjects, Config.quadtreeMaxLevels);

            PriorityQueue <Segment, int> priorityQueue = new PriorityQueue <Segment, int>(new Comparison <int>((i1, i2) => i2.CompareTo(i1)));

            priorityQueue.Enqueue(root1, 0);
            //priorityQueue.Enqueue(root2, 0);

            return(new InteractiveGenerationContext(segments, quadtree, debugData, priorityQueue));
        }
Ejemplo n.º 6
0
 static void AddSegment(Segment segment, List <Segment> segments, Quadtree quadtree)
 {
     segment.Index = segments.Count;
     segments.Add(segment);
     quadtree.Insert(segment);
 }
Ejemplo n.º 7
0
        static bool LocalConstraints(Segment segment, List <Segment> segments, Quadtree quadtree, DebugData debugData)
        {
            int         priority = 0;
            Func <bool> action   = null;
            float       t0       = -1;

            var matches = quadtree.Retrieve(segment);

            for (int i = 0, j = 0, k = matches.Count - 1; j <= k; i = j += 1)
            {
                Segment other = (Segment)matches[i].reference;

                if (segment == other)
                {
                    continue;
                }

                // intersection check
                if (priority <= 4)
                {
                    Vector2 intersection;
                    float   t1;
                    if (segment.Intersect(other, out intersection, out t1))
                    {
                        if (t0 == -1 || t1 < t0)
                        {
                            t0       = t1;
                            priority = 4;
                            action   = () =>
                            {
                                float dirDiff          = Mathf.Abs(other.Direction - segment.Direction) % 180.0f;
                                float minDirectionDiff = Mathf.Min(dirDiff, Mathf.Abs(dirDiff - 180.0f));
                                if (minDirectionDiff < Config.minIntersectionDeviation)
                                {
                                    return(false);
                                }
                                IntersectSegments(intersection, other, segment, segments, quadtree);
                                if (debugData != null)
                                {
                                    debugData.intersections.Add(intersection);
                                }
                                return(true);
                            };
                        }
                    }
                }
                // snap to crossing within radius check
                if (priority <= 3)
                {
                    if ((segment.End - other.End).magnitude <= Config.snapDistance)
                    {
                        priority = 3;
                        action   = () =>
                        {
                            List <Segment> links;
                            segment.End     = other.End;
                            segment.Severed = true;
                            foreach (var destination in segment.Destinations)
                            {
                                int index = destination.Sources.IndexOf(other);
                                if (index != -1)
                                {
                                    continue;
                                }
                                destination.Sources.Add(other);
                            }
                            links = other.StartIsBackwards() ? other.Forwards : other.Branches;
                            if (links.Any((Segment link) =>
                            {
                                return(((link.Start == segment.End) &&
                                        (link.End == segment.Start)) ||
                                       ((link.Start == segment.Start) && (link.End == segment.End)));
                            }))
                            {
                                return(false);
                            }
                            links.ForEach((Segment link) =>
                            {
                                link.LinksForEndContaining(other).Add(segment);
                                segment.Forwards.Add(link);
                            });
                            links.Add(segment);
                            segment.Forwards.Add(other);
                            if (debugData != null)
                            {
                                debugData.snaps.Add(other.End);
                            }
                            return(true);
                        };
                    }
                }
                // intersection within radius check
                if (priority <= 2)
                {
                    var     e0          = (segment.End - other.Start);
                    var     e1          = (other.End - other.Start);
                    Vector2 proj        = Vector3.Project(e0, e1);
                    Vector2 pointOnLine = (other.Start + proj);
                    float   distance2   = Vector2.SqrMagnitude(segment.End - pointOnLine);
                    float   lineProj2   = Mathf.Sign(Vector3.Dot(e0, e1)) * Vector2.SqrMagnitude(proj);
                    float   length2     = Vector2.SqrMagnitude(e1);
                    if (distance2 < Config.snapDistance * Config.snapDistance && lineProj2 >= 0 && lineProj2 <= length2)
                    {
                        Vector2 point;
                        point    = pointOnLine;
                        priority = 2;
                        action   = () =>
                        {
                            float dirDiff    = Math.Abs(other.Direction - segment.Direction) % 180.0f;
                            float minDirDiff = Math.Min(dirDiff, Math.Abs(dirDiff - 180.0f));
                            if (minDirDiff < Config.minIntersectionDeviation)
                            {
                                return(false);
                            }
                            IntersectSegments(point, other, segment, segments, quadtree);
                            if (debugData != null)
                            {
                                debugData.intersectionsRadius.Add(point);
                            }
                            return(true);
                        };
                    }
                }
            }

            if (action != null)
            {
                return(action());
            }

            return(true);
        }
Ejemplo n.º 8
0
        static void IntersectSegments(Vector2 intersection, Segment segment0, Segment segment1, List <Segment> segments, Quadtree quadtree)
        {
            bool    startIsBackwards = segment0.StartIsBackwards();
            Segment splitPart        = new Segment(segment0);

            splitPart.Destinations.Add(segment0);
            AddSegment(splitPart, segments, quadtree);
            splitPart.End  = intersection;
            segment0.Start = intersection;
            foreach (var source0 in segment0.Sources)
            {
                int index = source0.Destinations.IndexOf(segment0);
                if (index == -1)
                {
                    continue;
                }
                source0.Destinations[index] = splitPart;
            }
            splitPart.Sources = new List <Segment>(segment0.Sources);
            segment0.Sources.Clear();
            segment0.Sources.Add(splitPart);
            segment0.Sources.Add(segment1);
            splitPart.Branches = new List <Segment>(segment0.Branches);
            splitPart.Forwards = new List <Segment>(segment0.Forwards);
            Segment        firstSplit, secondSplit;
            List <Segment> linksToFix;

            if (startIsBackwards)
            {
                firstSplit  = splitPart;
                secondSplit = segment0;
                linksToFix  = splitPart.Branches;
            }
            else
            {
                firstSplit  = segment0;
                secondSplit = splitPart;
                linksToFix  = splitPart.Forwards;
            }
            foreach (var link in linksToFix)
            {
                int index = link.Branches.IndexOf(segment0);
                if (index != -1)
                {
                    link.Branches[index] = splitPart;
                }
                else
                {
                    index = link.Forwards.IndexOf(segment0);
                    link.Forwards[index] = splitPart;
                }
            }
            firstSplit.Forwards = new List <Segment>();
            firstSplit.Forwards.Add(segment1);
            firstSplit.Forwards.Add(secondSplit);
            secondSplit.Branches = new List <Segment>();
            secondSplit.Branches.Add(segment1);
            secondSplit.Branches.Add(firstSplit);
            segment1.Forwards.Add(firstSplit);
            segment1.Forwards.Add(secondSplit);
            segment1.End = intersection;
            segment1.Destinations.Clear();
            segment1.Severed = true;
        }