Beispiel #1
0
        FieldConnectPoint ToFieldConnectPoint(RiverPoint riverPoint)
        {
            var point = new FieldConnectPoint();

            point.Initialize(riverPoint.Position, PointType.kRiver);
            return(point);
        }
Beispiel #2
0
        void AbsorbPoint(RiverPoint currentPoint, RiverPoint absorptionPoint)
        {
            Vector3           currentPos = currentPoint.Position;
            List <RiverPoint> nextPoints = currentPoint.NextPoints;

            if (nextPoints.Contains(absorptionPoint) == false)
            {
                nextPoints.Add(absorptionPoint);

                Vector3 normDir   = (absorptionPoint.Position - currentPos).normalized;
                float   halfWidth = width * 0.5f;
                var     leftBase  = new Vector3(-normDir.z, 0, normDir.x) * halfWidth;
                var     rightBase = new Vector3(normDir.z, 0, -normDir.x) * halfWidth;
                Vector3 left      = leftBase + currentPos;
                Vector3 right     = rightBase + currentPos;

                vertices.Add(left);
                vertices.Add(right);
            }

            List <RiverPoint> prevPoints = absorptionPoint.PrevPoints;

            if (prevPoints.Contains(currentPoint) == false)
            {
                prevPoints.Add(currentPoint);
            }
        }
Beispiel #3
0
        void AddToPointMap(RiverPoint point)
        {
            Vector2Int        chunk = GetChunk(point.Position);
            List <RiverPoint> pointsInChunk;

            if (riverPointsMap.TryGetValue(chunk, out pointsInChunk) == false)
            {
                pointsInChunk = new List <RiverPoint>();
                riverPointsMap.Add(chunk, pointsInChunk);
            }
            if (pointsInChunk.Contains(point) == false)
            {
                pointsInChunk.Add(point);
            }
        }
        void GenerateRoadAlongRiver(RiverPoint riverRoot)
        {
            roadAlongRiverPoints.Clear();
            leftRoadPoints.Clear();
            rightRoadPoints.Clear();
            for (int i0 = 0; i0 < riverRoot.NextPoints.Count; ++i0)
            {
                GenerateRoadAlongRiverRecursive(riverRoot, null, riverRoot.NextPoints[i0], false, false);
            }

            roadAlongRiverPoints.AddRange(leftRoadPoints);
            roadAlongRiverPoints.AddRange(rightRoadPoints);

            points.AddRange(roadAlongRiverPoints);
        }
Beispiel #5
0
        void ConnectPointsRecursive(FieldConnectPoint prevPoint, RiverPoint currentPoint, Dictionary <RiverPoint, FieldConnectPoint> connectPointMap, int pointLevel)
        {
            if (connectPointMap.TryGetValue(currentPoint, out FieldConnectPoint point) == false)
            {
                point       = ToFieldConnectPoint(currentPoint);
                point.Index = points.Count;
                points.Add(point);
                connectPointMap.Add(currentPoint, point);
                int leftIndex = leftRightPoints.Count * 2;
                leftRightPoints.Add(new Vector3[] { vertices[leftIndex], vertices[leftIndex + 1] });
                if (point.Index - prevPoint.Index > 1)
                {
                    leftRightPoints.Add(new Vector3[] { vertices[leftIndex + 2], vertices[leftIndex + 3] });
                    pointLevels.Add(pointLevel - 1);
                    pointLevels.Add(pointLevel);
                }
                else
                {
                    pointLevels.Add(pointLevel);
                }

                prevPoint.SetConnection(point);
                point.SetConnection(prevPoint);

                List <RiverPoint> nextPoints = currentPoint.NextPoints;
                for (int i0 = 0; i0 < nextPoints.Count; ++i0)
                {
                    ConnectPointsRecursive(point, nextPoints[i0], connectPointMap, pointLevel + 1);
                }
            }
            else
            {
                prevPoint.SetConnection(point);
                point.SetConnection(prevPoint);
                int leftIndex = leftRightPoints.Count * 2;
                leftRightPoints.Add(new Vector3[] { vertices[leftIndex], vertices[leftIndex + 1] });
                pointLevels.Add(pointLevel);
            }
        }
Beispiel #6
0
        void GenerateRiverRecursive(RiverPoint riverPoint, Vector3 dir, float bendability)
        {
            RiverPoint currentPoint = riverPoint;
            Vector3    currentPos   = currentPoint.Position;
            Vector3    nextDir      = dir;
            int        numStep      = 0;
            int        totalStep    = 0;
            float      bend         = bendability;
            float      angleRange   = parameter.AngleRange;
            float      halfWidth    = width * 0.5f;
            float      stepSize     = parameter.StepSize;
            var        step         = new Vector3(0, 0, stepSize);

            while (IsInsideField(currentPos) != false)
            {
                ++numStep;
                ++totalStep;

                Vector3    nextPos      = currentPos + nextDir;
                Vector2Int currentChunk = GetChunk(currentPos);
                Vector2Int nextChunk    = GetChunk(nextPos);

                RiverPoint absorptionPoint = null;
                if (TryGetAbsorptionPoint(currentPos, nextPos, currentChunk, stepSize * 0.5f, out absorptionPoint) != false)
                {
                    AbsorbPoint(currentPoint, absorptionPoint);

                    currentPoint = absorptionPoint;
                    currentPos   = currentPoint.Position;

                    break;
                }
                else if (currentChunk != nextChunk && TryGetAbsorptionPoint(currentPos, nextPos, nextChunk, stepSize * 0.5f, out absorptionPoint) != false)
                {
                    AbsorbPoint(currentPoint, absorptionPoint);

                    currentPoint = absorptionPoint;
                    currentPos   = currentPoint.Position;

                    break;
                }
                else
                {
                    float angle = Mathf.Atan2(nextDir.x, nextDir.z) * Mathf.Rad2Deg;

                    if (canBranch != false && numStep >= numStepWithoutBranching)
                    {
                        if (DetectFromPercent(branchingProbability) != false)
                        {
                            numStep = 0;
                            branchingProbability    = CalcBranchingProbability();
                            numStepWithoutBranching = CalcNumStepWithoutBranching();
                            float   angle2   = angle + Mathf.Lerp(minAngleForBranching, angleRange, (float)random.NextDouble()) * (random.Next(2) == 0 ? -1 : 1);
                            Vector3 nextDir2 = Quaternion.Euler(0, angle2, 0) * step;
                            GenerateRiverRecursive(currentPoint, nextDir2, bend);
                        }
                    }

                    var nextPoint = new RiverPoint();
                    nextPoint.Position = nextPos;
                    nextPoint.Width    = width;
                    nextPoint.PrevPoints.Add(currentPoint);
                    currentPoint.NextPoints.Add(nextPoint);
                    AddToPointMap(nextPoint);

                    Vector3 normDir   = nextDir.normalized;
                    var     leftBase  = new Vector3(-normDir.z, 0, normDir.x) * halfWidth;
                    var     rightBase = new Vector3(normDir.z, 0, -normDir.x) * halfWidth;
                    Vector3 left      = leftBase + currentPos;
                    Vector3 right     = rightBase + currentPos;

                    vertices.Add(left);
                    vertices.Add(right);

                    float nextAngle = angle + angleRange * (float)random.NextDouble() - angleRange * 0.5f;
                    bend     *= (1.0f - parameter.BendabilityAttenuation);
                    nextAngle = Mathf.Lerp(angle, nextAngle, bend);
                    nextDir   = Quaternion.Euler(0, nextAngle, 0) * step;

                    currentPoint = nextPoint;
                    currentPos   = currentPoint.Position;
                }
            }

            if (totalStep != 0)
            {
                Vector3 normDir = nextDir.normalized;
                Vector3 left    = new Vector3(-normDir.z, 0, normDir.x) * halfWidth + currentPos;
                Vector3 right   = new Vector3(normDir.z, 0, -normDir.x) * halfWidth + currentPos;
                vertices.Add(left);
                vertices.Add(right);
            }
        }
Beispiel #7
0
        public void Generate(RiverParameter parameter, System.Random random)
        {
            lastInterruptionTime = System.DateTime.Now;

            this.parameter          = parameter;
            this.random             = random;
            width                   = Mathf.Lerp(parameter.MinInitialWidth, parameter.MaxInitialWidth, (float)random.NextDouble());
            branchingProbability    = CalcBranchingProbability();
            numStepWithoutBranching = CalcNumStepWithoutBranching();

            points.Clear();
            vertices.Clear();
            riverPointsMap.Clear();
            leftRightPoints.Clear();
            pointLevels.Clear();
            quadranglesMap.Clear();

            Vector3 initialPosition = DecideInitialPosition();
            float   initialAngle    = DecideInitialAngle(initialPosition);

            rootPoint          = new RiverPoint();
            rootPoint.Position = initialPosition;
            rootPoint.Width    = width;
            AddToPointMap(rootPoint);

            var     step       = new Vector3(0, 0, parameter.StepSize);
            Vector3 initialDir = Quaternion.Euler(0, initialAngle, 0) * step;

            minAngleForBranching = Mathf.Atan2(width * 0.5f, parameter.StepSize) * Mathf.Rad2Deg * 2;
            canBranch            = parameter.AngleRange >= minAngleForBranching;

            GenerateRiverRecursive(rootPoint, initialDir, 1);

            ConnectPoints();
            for (int i0 = 0; i0 < leftRightPoints.Count - 1; ++i0)
            {
                if (pointLevels[i0 + 1] - pointLevels[i0] == 1)
                {
                    Vector3 point1, point2, point3, point4;
                    point1 = leftRightPoints[i0][0];
                    point2 = leftRightPoints[i0 + 1][0];
                    point3 = leftRightPoints[i0 + 1][1];
                    point4 = leftRightPoints[i0][1];
                    Vector2Int chunk1, chunk2, chunk3, chunk4;
                    chunk1 = GetChunk(point1);
                    chunk2 = GetChunk(point2);
                    chunk3 = GetChunk(point3);
                    chunk4 = GetChunk(point4);
                    var chunks = new List <Vector2Int>();
                    chunks.Add(chunk1);
                    if (chunk2 != chunk1)
                    {
                        chunks.Add(chunk2);
                    }
                    if (chunk3 != chunk1 && chunk3 != chunk2)
                    {
                        chunks.Add(chunk3);
                    }
                    if (chunk4 != chunk1 && chunk4 != chunk2 && chunk4 != chunk3)
                    {
                        chunks.Add(chunk4);
                    }

                    for (int i1 = 0; i1 < chunks.Count; ++i1)
                    {
                        Vector2Int       chunk = chunks[i1];
                        List <Vector3[]> quadrangles;
                        if (quadranglesMap.TryGetValue(chunk, out quadrangles) == false)
                        {
                            quadrangles = new List <Vector3[]>();
                            quadranglesMap.Add(chunk, quadrangles);
                        }
                        quadrangles.Add(new Vector3[] { point1, point2, point3, point4 });
                    }
                }
            }
        }
Beispiel #8
0
        bool TryGetAbsorptionPoint(Vector3 startPos, Vector3 endPos, Vector2Int chunk, float distance, out RiverPoint absorptionPoint)
        {
            bool foundPoint = false;

            absorptionPoint = null;

            bool isIntersecting = false;
            var  nearestPoint   = new KeyValuePair <float, RiverPoint>(float.MaxValue, null);

            if (riverPointsMap.TryGetValue(chunk, out List <RiverPoint> pointsInChunk) != false)
            {
                for (int i0 = 0; i0 < pointsInChunk.Count; ++i0)
                {
                    RiverPoint currentPoint = pointsInChunk[i0];
                    Vector3    currentPos   = currentPoint.Position;
                    var        intersection = new Vector3();

                    List <RiverPoint> prevPoints = currentPoint.PrevPoints;
                    for (int i1 = 0; i1 < prevPoints.Count; ++i1)
                    {
                        RiverPoint prevPoint = prevPoints[i1];
                        Vector3    prevPos   = prevPoint.Position;
                        if (IsIntersectingLineSegment(startPos, endPos, prevPos, currentPos) != false)
                        {
                            isIntersecting = true;
                            foundPoint     = true;
                            TryGetIntersection(startPos, endPos, prevPos, currentPos, out intersection);
                            float dist1 = (prevPos - intersection).sqrMagnitude;
                            float dist2 = (currentPos - intersection).sqrMagnitude;
                            absorptionPoint = dist1 < dist2 ? prevPoint : currentPoint;
                            break;
                        }
                        else
                        {
                            float dist1 = (prevPos - endPos).sqrMagnitude;
                            float dist2 = (currentPos - endPos).sqrMagnitude;
                            if (dist1 < nearestPoint.Key)
                            {
                                nearestPoint = new KeyValuePair <float, RiverPoint>(dist1, prevPoint);
                            }
                            if (dist2 < nearestPoint.Key)
                            {
                                nearestPoint = new KeyValuePair <float, RiverPoint>(dist2, currentPoint);
                            }
                        }
                    }


                    List <RiverPoint> nextPoints = currentPoint.NextPoints;
                    for (int i1 = 0; i1 < nextPoints.Count; ++i1)
                    {
                        RiverPoint nextPoint = nextPoints[i1];
                        Vector3    nextPos   = nextPoint.Position;
                        if (IsIntersectingLineSegment(startPos, endPos, currentPos, nextPos) != false)
                        {
                            isIntersecting = true;
                            foundPoint     = true;
                            TryGetIntersection(startPos, endPos, currentPos, nextPos, out intersection);
                            float dist1 = (currentPos - intersection).sqrMagnitude;
                            float dist2 = (nextPos - intersection).sqrMagnitude;
                            absorptionPoint = dist1 < dist2 ? currentPoint : nextPoint;
                            break;
                        }
                        else
                        {
                            float dist1 = (currentPos - endPos).sqrMagnitude;
                            float dist2 = (nextPos - endPos).sqrMagnitude;
                            if (dist1 < nearestPoint.Key)
                            {
                                nearestPoint = new KeyValuePair <float, RiverPoint>(dist1, currentPoint);
                            }
                            if (dist2 < nearestPoint.Key)
                            {
                                nearestPoint = new KeyValuePair <float, RiverPoint>(dist2, nextPoint);
                            }
                        }
                    }

                    if (isIntersecting != false)
                    {
                        break;
                    }
                }
            }

            if (isIntersecting == false)
            {
                if (nearestPoint.Key < distance * distance)
                {
                    absorptionPoint = nearestPoint.Value;
                    foundPoint      = true;
                }
            }

            return(foundPoint);
        }
        void GenerateRoadAlongRiverRecursive(RiverPoint currentPoint, RiverPoint prevPoint, RiverPoint nextPoint, bool addedLeftPoint, bool addedRightPoint)
        {
            Vector3 pos     = currentPoint.Position;
            Vector3 nextPos = nextPoint.Position;

            Vector3 dir     = nextPos - pos;
            Vector3 prevDir = prevPoint != null ? pos - prevPoint.Position : dir;

            float      angle    = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
            Quaternion rotation = Quaternion.Euler(0, angle, 0);

            float dist      = currentPoint.Width * 0.5f + parameter.DistanceFromRiver + parameter.Width * 0.5f;
            var   leftBase  = new Vector3(-dist, 0, 0);
            var   rightBase = new Vector3(dist, 0, 0);

            float cross = Vector3.Cross(prevDir, dir).y;

            bool addedL = false;
            bool addedR = false;

            if (addedLeftPoint == false || cross > 0)
            {
                Vector3 left = rotation * leftBase + pos;
                if (river.Covers(left) == false)
                {
                    var leftPoint = new FieldPoint
                    {
                        Position = left,
                        Type     = PointType.kRoadAlongRiver,
                    };
                    leftRoadPoints.Add(leftPoint);
                    AddToPointMap(leftPoint);
                    addedL = true;
                }
            }

            if (addedRightPoint == false || cross < 0)
            {
                Vector3 right = rotation * rightBase + pos;
                if (river.Covers(right) == false)
                {
                    var rightPoint = new FieldPoint
                    {
                        Position = right,
                        Type     = PointType.kRoadAlongRiver,
                    };
                    rightRoadPoints.Add(rightPoint);
                    AddToPointMap(rightPoint);
                    addedR = true;
                }
            }

            if (nextPoint.NextPoints.Count > 0)
            {
                for (int i0 = 0; i0 < nextPoint.NextPoints.Count; ++i0)
                {
                    GenerateRoadAlongRiverRecursive(nextPoint, currentPoint, nextPoint.NextPoints[i0], addedL, addedR);
                }
            }
            else
            {
                Vector3 nextLeft = rotation * leftBase + nextPos;
                if (river.Covers(nextLeft) == false)
                {
                    var leftPoint2 = new FieldPoint
                    {
                        Position = nextLeft,
                        Type     = PointType.kRoadAlongRiver,
                    };
                    leftRoadPoints.Add(leftPoint2);
                    AddToPointMap(leftPoint2);
                }

                Vector3 nextRight = rotation * rightBase + nextPos;
                if (river.Covers(nextRight) == false)
                {
                    var rightPoint2 = new FieldPoint
                    {
                        Position = nextRight,
                        Type     = PointType.kRoadAlongRiver,
                    };
                    rightRoadPoints.Add(rightPoint2);
                    AddToPointMap(rightPoint2);
                }
            }
        }