Example #1
0
    private void WeightWayPointsAlongSegments()
    {
        for (var i = 0; i < _vertices.Count; i++)
        {
            var firstVertex = _vertices[i];
            var nextVertex  = i == _vertices.Count - 1 ? _vertices[0] : _vertices[i + 1];

            _wayPoints.Add(firstVertex);

            var distanceBetween = Vector2.Distance(firstVertex.ProjectedPoint, nextVertex.ProjectedPoint);

            var pointsToAdd = Mathf.FloorToInt(distanceBetween / _minDistanceBetweenNewPointsBetweenVertices) <= 0
                ? 1
                : Mathf.FloorToInt(distanceBetween / _minDistanceBetweenNewPointsBetweenVertices);

            if (pointsToAdd == 1)
            {
                var obstaclePoint = new ObstaclePoint
                {
                    IsSidePoint         = true,
                    PreviousVertexPoint = firstVertex,
                    NextVertexPoint     = nextVertex,
                    PercentOfSegment    = 0.5f,
                    ProjectedPoint      = Vector2.Lerp(firstVertex.ProjectedPoint, nextVertex.ProjectedPoint, 0.5f)
                };

                _wayPoints.Add(obstaclePoint);
            }
            else
            {
                for (var j = 0; j < pointsToAdd - 1; j++)
                {
                    var percentOfSegment = (j + 1) / (float)pointsToAdd;

                    var pointPosition =
                        Vector2.Lerp(firstVertex.ProjectedPoint, nextVertex.ProjectedPoint, percentOfSegment);

                    var projectedPointFrom  = pointPosition;
                    var projectionDirection = firstVertex.Normal;
                    var obstaclePoint       = new ObstaclePoint
                    {
                        IsSidePoint         = true,
                        StartingPosition    = pointPosition,
                        ProjectedPointFrom  = projectedPointFrom,
                        ProjectionDirection = projectionDirection,
                        ProjectedPoint      = pointPosition,
                        NextVertexPoint     = nextVertex,
                        PreviousVertexPoint = firstVertex,
                        PercentOfSegment    = percentOfSegment
                    };

                    _wayPoints.Add(obstaclePoint);
                }
            }
        }
    }
Example #2
0
 private void ResetForNewDraw()
 {
     _pointIndex               = 0;
     _startingPoint            = null;
     _shouldNotCheckForCorners = false;
     _wayPoints.Clear();
     _obstaclePoints.Clear();
     _vertices.Clear();
     _debugIntersections.Clear();
     _debugTangent.Clear();
     _debugReverseNormals.Clear();
     _debugReverseTangents.Clear();
 }
Example #3
0
    public Queue <ObstaclePoint> BestPath(ObstaclePoint closestToStart, ObstaclePoint closestToEnd, Vector2 destination)
    {
        var forwardPath = new Queue <ObstaclePoint>();
        var reversePath = new Queue <ObstaclePoint>();

        var closestPointToDestinationIndex = closestToEnd.WayPointIndex;

        var currentObstaclePoint = closestToStart;

        forwardPath.Enqueue(currentObstaclePoint);

        var forwardDistanceSum = 0f;

        while (currentObstaclePoint.WayPointIndex != closestPointToDestinationIndex)
        {
            forwardDistanceSum += currentObstaclePoint.DistanceToNextWayPoint;

            currentObstaclePoint = currentObstaclePoint.NextWayPoint;
            forwardPath.Enqueue(currentObstaclePoint);
        }

        var closestToFinalDestination = Vector2.Distance(closestToEnd.ProjectedPoint, destination);

        currentObstaclePoint = closestToStart;
        reversePath.Enqueue(currentObstaclePoint);
        var reverseDistanceSum = 0f;

        while (currentObstaclePoint.WayPointIndex != closestPointToDestinationIndex)
        {
            reverseDistanceSum += currentObstaclePoint.DistanceToPreviousWayPoint;

            currentObstaclePoint = currentObstaclePoint.PreviousWayPoint;
            reversePath.Enqueue(currentObstaclePoint);
        }

        forwardDistanceSum += closestToFinalDestination;
        reverseDistanceSum += closestToFinalDestination;

        var selectedPath = forwardDistanceSum < reverseDistanceSum ? forwardPath : reversePath;

        _selectedPath = selectedPath;

        return(selectedPath);
    }
Example #4
0
    private void FindNextPoint(Vector2 point, Vector2 normal)
    {
        var tangent                  = (Vector2)Vector3.Cross(normal, Vector3.forward);
        var offsetPoint              = point + normal * OffsetDistance;
        var tangentCheckPoint        = offsetPoint + tangent * FixedStep;
        var reverseNormalCheckPoint  = tangentCheckPoint - normal * (OffsetDistance + .005f);
        var reverseTangentCheckPoint = reverseNormalCheckPoint - tangent * (FixedStep * 2);

        var found = false;

        var obstaclePoint = new ObstaclePoint {
            StartingPosition = point, Normal = normal, ObstaclePointIndex = _pointIndex++, Tangent = tangent
        };

        if (_startingPoint == null)
        {
            _startingPoint = obstaclePoint;
        }

        if (_obstaclePoints.Count > 1)
        {
            if (Vector2.Distance(_startingPoint.StartingPosition, point) < FixedStep)
            {
                return;
            }

            if (_vertices.Count > 0)
            {
                if (Vector2.Distance(_startingPoint.StartingPosition, obstaclePoint.StartingPosition) <= FixedStep && _vertices[0].Normal == normal)
                {
                    _shouldNotCheckForCorners = true;
                }
            }

            if (Vector2.Dot(_obstaclePoints[_obstaclePoints.Count - 1].Normal, normal) < 0.95f && !_shouldNotCheckForCorners)
            {
                if (_obstaclePoints[_obstaclePoints.Count - 1].NextIsCorner)
                {
                    obstaclePoint.IsInsideCorner = true;
                }
                _vertices.Add(obstaclePoint);
            }
        }

        _obstaclePoints.Add(obstaclePoint);

        var hit = Physics2D.Raycast(offsetPoint, tangent, FixedStep);

        if (hit)
        {
            obstaclePoint.NextIsCorner = true;
            _debugReverseTangents.Add(new [] { offsetPoint, hit.point });
            found = true;
        }
        else
        {
            _debugReverseTangents.Add(new [] { offsetPoint, tangentCheckPoint });

            hit = Physics2D.Raycast(tangentCheckPoint, -normal, OffsetDistance + FixedStep);

            if (hit)
            {
                _debugReverseNormals.Add(new [] { tangentCheckPoint, hit.point });

                found = true;
            }
            else
            {
                _debugReverseTangents.Add(new [] { tangentCheckPoint, reverseNormalCheckPoint });

                hit = Physics2D.Raycast(reverseNormalCheckPoint, -tangent, FixedStep * 2);

                if (hit)
                {
                    _debugReverseTangents.Add(new [] { reverseNormalCheckPoint, hit.point });
                    found = true;
                }
                else
                {
                    _debugReverseTangents.Add(new [] { reverseNormalCheckPoint, reverseTangentCheckPoint });
                }
            }
        }

        if (found && _obstaclePoints.Count < MaxChecks)
        {
            FindNextPoint(hit.point, hit.normal);
        }
    }
        public override void MarkIntersectWithSurface(ObstacleSurface otherSurface, MovementMechanism forMechanism)
        {
            Hitbox hitbox = forMechanism.Hitbox;

            switch (hitbox.Type)
            {
            case Hitbox.HitboxType.Square:
            {
                //SquareHitbox square = hitbox as SquareHitbox;
            }
            break;

            default:
                throw new NotImplementedException("Unknown hitbox type");
            }
            SimpleVolume vol    = MyVolume;
            Orientation  offset = forMechanism.HitboxOffset(otherSurface);

            //Reverse changes to find how this object intersects with original surface instead of the other way around.
            vol.MinX = vol.MinX - offset.x - hitbox.MaxXIncrease((Rotation)offset);
            vol.MaxX = vol.MaxX - offset.x + hitbox.MaxXDecrease((Rotation)offset);
            vol.MinY = vol.MinY - offset.y - hitbox.MaxYIncrease((Rotation)offset);
            vol.MaxY = vol.MaxY - offset.y + hitbox.MaxYDecrease((Rotation)offset);
            vol.MinZ = vol.MinZ - offset.z - hitbox.MaxZIncrease((Rotation)offset);
            vol.MaxZ = vol.MaxZ - offset.z + hitbox.MaxZDecrease((Rotation)offset);

            Vector normal = otherSurface.GetNormal();
            int    height = otherSurface.GetHeight();

            //Important: These indices match the obstacle point indices.
            int[] differences = new int[8];
            differences[0] = (int)normal.DotProduct(vol.MinX, vol.MinY, vol.MinZ) - height;
            differences[1] = (int)normal.DotProduct(vol.MaxX, vol.MinY, vol.MinZ) - height;
            differences[2] = (int)normal.DotProduct(vol.MaxX, vol.MaxY, vol.MinZ) - height;
            differences[3] = (int)normal.DotProduct(vol.MinX, vol.MaxY, vol.MinZ) - height;
            differences[4] = (int)normal.DotProduct(vol.MinX, vol.MinY, vol.MaxZ) - height;
            differences[5] = (int)normal.DotProduct(vol.MaxX, vol.MinY, vol.MaxZ) - height;
            differences[6] = (int)normal.DotProduct(vol.MaxX, vol.MaxY, vol.MaxZ) - height;
            differences[7] = (int)normal.DotProduct(vol.MinX, vol.MaxY, vol.MaxZ) - height;

            List <int> negativeHeights = new List <int>(8);
            List <int> positiveHeights = new List <int>(8);

            if (differences[0] > 0)
            {
                positiveHeights.Add(0);
            }
            else
            {
                negativeHeights.Add(0);
            }
            if (differences[1] > 0)
            {
                positiveHeights.Add(1);
            }
            else
            {
                negativeHeights.Add(1);
            }
            if (differences[2] > 0)
            {
                positiveHeights.Add(2);
            }
            else
            {
                negativeHeights.Add(2);
            }
            if (differences[3] > 0)
            {
                positiveHeights.Add(3);
            }
            else
            {
                negativeHeights.Add(3);
            }
            if (differences[4] > 0)
            {
                positiveHeights.Add(4);
            }
            else
            {
                negativeHeights.Add(4);
            }
            if (differences[5] > 0)
            {
                positiveHeights.Add(5);
            }
            else
            {
                negativeHeights.Add(5);
            }
            if (differences[6] > 0)
            {
                positiveHeights.Add(6);
            }
            else
            {
                negativeHeights.Add(6);
            }
            if (differences[7] > 0)
            {
                positiveHeights.Add(7);
            }
            else
            {
                negativeHeights.Add(7);
            }

            if (positiveHeights.Count == 0 || negativeHeights.Count == 0)
            {
                return;
            }
            for (int i = 0; i < negativeHeights.Count; i++)
            {
                int pointId = negativeHeights[i];
                for (int j = 0; j < 3; j++)
                {
                    SurfaceLine   line       = PointLine(pointId, j);
                    ObstaclePoint otherPoint = line.Start;
                    if (otherPoint.id == pointId)
                    {
                        otherPoint = line.End;
                    }
                    if (differences[otherPoint.id] > 0)
                    {
                        double ratio = differences[pointId] / (differences[pointId] - differences[otherPoint.id]);
                        Point  start = PointPosition(pointId);
                        Point  end   = otherPoint.Position;
                        Point  intersectPoint;
                        intersectPoint.x = start.x + (int)((end.x - start.x) * ratio);
                        intersectPoint.y = start.y + (int)((end.y - start.y) * ratio);
                        intersectPoint.z = start.z + (int)((end.z - start.z) * ratio);

                        List <Point> IntersectingPoints = new List <Point>();
                        IntersectingPoints.Add(intersectPoint);
                        SurfaceLine previousLine      = line;
                        SurfaceLine nextLine          = new SurfaceLine(); //compiler has failed me for once, this shouldn't need initialization here.
                        int         previousSurfaceId = -1;
                        do
                        {
                            ObstacleSurface nextSurface = previousLine.Left;
                            if (previousSurfaceId == nextSurface.surfaceIndex)
                            {
                                nextSurface = previousLine.Right;
                            }
                            for (int k = 0; k < 4; k++)
                            {
                                nextLine = nextSurface.GetLine(k);
                                if (nextLine.id == previousLine.id)
                                {
                                    continue;
                                }
                                ObstaclePoint nextStart = nextLine.Start;
                                ObstaclePoint nextEnd   = nextLine.End;
                                if ((differences[nextStart.id] > 0 && differences[nextEnd.id] <= 0) ||
                                    (differences[nextStart.id] <= 0 && differences[nextEnd.id] > 0))
                                {
                                    start            = nextStart.Position;
                                    end              = nextEnd.Position;
                                    ratio            = differences[nextStart.id] / (differences[nextStart.id] - differences[nextEnd.id]);
                                    intersectPoint.x = start.x + (int)((end.x - start.x) * ratio);
                                    intersectPoint.y = start.y + (int)((end.y - start.y) * ratio);
                                    intersectPoint.z = start.z + (int)((end.z - start.z) * ratio);

                                    IntersectingPoints.Add(intersectPoint);

                                    break;
                                }
                            }

                            previousSurfaceId = nextSurface.surfaceIndex;
                            previousLine      = nextLine;
                        }while (nextLine.id != line.id);

                        otherSurface.AddIntersectLines(IntersectingPoints, this, forMechanism);

                        return;
                    }
                }
            }
        }