コード例 #1
0
ファイル: HeightQuadTree.cs プロジェクト: Hengle/UnityApex
        private HeightQuadTree(MatrixBounds bounds, int depth, int maxDepth)
        {
            _bounds   = bounds;
            _depth    = depth;
            _maxDepth = maxDepth;

            _indexes = new DynamicArray <VectorXZ>(10);
        }
コード例 #2
0
ファイル: HeightQuadTree.cs プロジェクト: andrewstarnes/wwtd2
        private HeightQuadTree(int startX, int startZ, int sizeX, int sizeZ, int depth, int maxDepth)
        {
            _bounds = new MatrixBounds(startX, startZ, startX + (sizeX - 1), startZ + (sizeZ - 1));
            _depth = depth;
            _maxDepth = maxDepth;

            _indexes = new DynamicArray<VectorXZ>(10);
        }
コード例 #3
0
ファイル: HeightQuadTree.cs プロジェクト: andrewstarnes/wwtd2
        private HeightQuadTree(MatrixBounds bounds, int depth, int maxDepth)
        {
            _bounds = bounds;
            _depth = depth;
            _maxDepth = maxDepth;

            _indexes = new DynamicArray<VectorXZ>(10);
        }
コード例 #4
0
ファイル: HeightQuadTree.cs プロジェクト: Hengle/UnityApex
        private HeightQuadTree(int startX, int startZ, int sizeX, int sizeZ, int depth, int maxDepth)
        {
            _bounds   = new MatrixBounds(startX, startZ, startX + (sizeX - 1), startZ + (sizeZ - 1));
            _depth    = depth;
            _maxDepth = maxDepth;

            _indexes = new DynamicArray <VectorXZ>(10);
        }
コード例 #5
0
 public bool Contains(MatrixBounds other)
 {
     if (other.maxRow > this.maxRow || other.minRow < this.minRow || other.maxColumn > this.maxColumn)
     {
         return(false);
     }
     return(other.minColumn >= this.minColumn);
 }
コード例 #6
0
 public static MatrixBounds Combine(MatrixBounds first, MatrixBounds second)
 {
     if (first.isEmpty)
     {
         return(second);
     }
     if (second.isEmpty)
     {
         return(first);
     }
     return(new MatrixBounds(Math.Min(first.minColumn, second.minColumn), Math.Min(first.minRow, second.minRow), Math.Max(first.maxColumn, second.maxColumn), Math.Max(first.maxRow, second.maxRow)));
 }
コード例 #7
0
ファイル: HeightQuadTree.cs プロジェクト: Hengle/UnityApex
        public IHeightLookup PrepareForUpdate(MatrixBounds suggestedBounds, out MatrixBounds requiredBounds)
        {
            if (!_bounds.Contains(suggestedBounds))
            {
                throw new ArgumentException("Cannot update a quadtree of a smaller size than requested bounds.", "suggestedBounds");
            }

            var updater = GetUpdateTree(null, 0, suggestedBounds);

            if (updater != null)
            {
                requiredBounds = updater.bounds;
                return(updater);
            }

            //The update covers an area that requires a full reindexing.
            //This can happen with even very small areas, they just need to overlap one of the borders between subtrees.
            //And this is why dynamic updates are not friends with quad trees
            requiredBounds = _bounds;
            _lookup        = null;
            _subTrees      = null;
            _indexes       = new DynamicArray <VectorXZ>(10);
            return(this);
        }
コード例 #8
0
ファイル: HeightQuadTree.cs プロジェクト: andrewstarnes/wwtd2
        public IHeightLookup PrepareForUpdate(MatrixBounds suggestedBounds, out MatrixBounds requiredBounds)
        {
            if (!_bounds.Contains(suggestedBounds))
            {
                throw new ArgumentException("Cannot update a quadtree of a smaller size than requested bounds.", "suggestedBounds");
            }

            var updater = GetUpdateTree(null, 0, suggestedBounds);

            if (updater != null)
            {
                requiredBounds = updater.bounds;
                return updater;
            }

            //The update covers an area that requires a full reindexing.
            //This can happen with even very small areas, they just need to overlap one of the borders between subtrees.
            //And this is why dynamic updates are not friends with quad trees
            requiredBounds = _bounds;
            _lookup = null;
            _subTrees = null;
            _indexes = new DynamicArray<VectorXZ>(10);
            return this;
        }
コード例 #9
0
ファイル: Matrix.cs プロジェクト: xwf20050250/Apex-Game-Tools
 /// <summary>
 /// Applies an action to a range of items
 /// </summary>
 /// <param name="bounds">The bounds specifying the index range.</param>
 /// <param name="act">The action to apply. This can be anything from modifying the items to collecting data from the items.</param>
 public void Apply(MatrixBounds bounds, Action <T> act)
 {
     Apply(bounds.minColumn, bounds.maxColumn, bounds.minRow, bounds.maxRow, act);
 }
コード例 #10
0
ファイル: HeightQuadTree.cs プロジェクト: andrewstarnes/wwtd2
        private UpdatingHeightTree GetUpdateTree(HeightQuadTree parent, int parentIdx, MatrixBounds suggestedBounds)
        {
            if (_subTrees != null)
            {
                for (int i = 0; i < 4; i++)
                {
                    if (_subTrees[i]._bounds.Contains(suggestedBounds))
                    {
                        return _subTrees[i].GetUpdateTree(this, i, suggestedBounds);
                    }
                }
            }

            if (parent != null)
            {
                var freshStart = new HeightQuadTree(_bounds, _depth, _maxDepth);
                return new UpdatingHeightTree(freshStart, parent, parentIdx);
            }

            return null;
        }
コード例 #11
0
 public override IEnumerator AssignHeightSettings(MatrixBounds bounds)
 {
     yield break;
 }
コード例 #12
0
        /// <summary>
        /// Combines two bounds to create a new bounds that covers the area of both plus any area between them.
        /// If one <see cref="isEmpty"/> it will return the other.
        /// </summary>
        /// <param name="first">The first bounds.</param>
        /// <param name="second">The second bounds.</param>
        /// <returns>A new bounds that covers the area of both plus any area between them.</returns>
        public static MatrixBounds Combine(MatrixBounds first, MatrixBounds second)
        {
            if (first.isEmpty)
            {
                return second;
            }

            if (second.isEmpty)
            {
                return first;
            }

            return new MatrixBounds(
                Math.Min(first.minColumn, second.minColumn),
                Math.Min(first.minRow, second.minRow),
                Math.Max(first.maxColumn, second.maxColumn),
                Math.Max(first.maxRow, second.maxRow));
        }
コード例 #13
0
 /// <summary>
 /// Determines whether this bounds contains the other bounds.
 /// </summary>
 /// <param name="other">The other bounds.</param>
 /// <returns><c>true</c> if contained; otherwise <c>false</c></returns>
 public bool Contains(MatrixBounds other)
 {
     return ((other.maxRow <= this.maxRow) && (other.minRow >= this.minRow) && (other.maxColumn <= this.maxColumn) && (other.minColumn >= this.minColumn));
 }
コード例 #14
0
        public override IEnumerator AssignHeightSettings(MatrixBounds bounds)
        {
            var maxColumn = bounds.maxColumn;
            var maxRow = bounds.maxRow;
            bool isPartial = (maxColumn - bounds.minColumn < _matrix.columns - 1) || (maxRow - bounds.minRow < _matrix.rows - 1);
            var ledgeThreshold = Mathf.Tan(GameServices.heightStrategy.ledgeThreshold * Mathf.Deg2Rad) * _matrix.granularity;

            var rawMatrix = _matrix.rawMatrix;
            for (int x = bounds.minColumn; x <= maxColumn; x++)
            {
                for (int z = bounds.minRow; z <= maxRow; z++)
                {
                    var c = rawMatrix[x, z] as RichCell;
                    if (c.isPermanentlyBlocked)
                    {
                        continue;
                    }

                    //Process neighbours
                    for (int dz = -1; dz <= 1; dz++)
                    {
                        for (int dx = -1; dx <= 1; dx++)
                        {
                            if (dx == 0 && dz == 0)
                            {
                                continue;
                            }

                            var n = _matrix[x + dx, z + dz] as RichCell;
                            if (n == null || n.isPermanentlyBlocked)
                            {
                                continue;
                            }

                            //If height data has already been assigned (by neighbour) we don't want to do it again,
                            //unless its a partial in which case we have to since neighbours are not necessarily covered by the update
                            if (!isPartial && c.HasInitializedHeightData(dx, dz))
                            {
                                continue;
                            }

                            UpdateCellHeightData(c, n, ledgeThreshold, dx, dz);

                            yield return null;
                        }
                    } /* end neighbour loop */
                }
            }

            if (!isPartial)
            {
                yield break;
            }

            //Update corner diagonals, this is only relevant for partial updates
            //Since the cells being updated only update their own relation to neighbours, there will potentially be 4 connections not updated,
            //those are the diagonals between the cells surround each corner of the bounds, e.g. bottom left corner the connection between the cell to the left and the cell below that corner.
            //since updates also update the involved neighbour, we only have to update 4 additional cells, and only on a specific diagonal.
            var bll = _matrix[bounds.minColumn - 1, bounds.minRow] as RichCell;
            var blb = _matrix[bounds.minColumn, bounds.minRow - 1] as RichCell;

            var tll = _matrix[bounds.minColumn - 1, bounds.maxRow] as RichCell;
            var tlt = _matrix[bounds.minColumn, bounds.maxRow + 1] as RichCell;

            var brr = _matrix[bounds.maxColumn + 1, bounds.minRow] as RichCell;
            var brb = _matrix[bounds.maxColumn, bounds.minRow - 1] as RichCell;

            var trr = _matrix[bounds.maxColumn + 1, bounds.maxRow] as RichCell;
            var trt = _matrix[bounds.maxColumn, bounds.maxRow + 1] as RichCell;

            if (bll != null && blb != null)
            {
                UpdateCellHeightData(bll, blb, ledgeThreshold, 1, -1);
                yield return null;
            }

            if (tll != null && tlt != null)
            {
                UpdateCellHeightData(tll, tlt, ledgeThreshold, 1, 1);
                yield return null;
            }

            if (brr != null && brb != null)
            {
                UpdateCellHeightData(brr, brb, ledgeThreshold, -1, -1);
                yield return null;
            }

            if (trr != null && trt != null)
            {
                UpdateCellHeightData(trr, trt, ledgeThreshold, -1, 1);
                yield return null;
            }
        }
コード例 #15
0
 static MatrixBounds()
 {
     MatrixBounds.nullBounds = new MatrixBounds(-1, -1, -2, -2);
 }
コード例 #16
0
 public IHeightLookup PrepareForUpdate(MatrixBounds suggestedBounds, out MatrixBounds requiredBounds)
 {
     requiredBounds = suggestedBounds;
     return(this);
 }
コード例 #17
0
ファイル: HeightQuadTree.cs プロジェクト: Hengle/UnityApex
 IHeightLookup IHeightLookup.PrepareForUpdate(MatrixBounds suggestedBounds, out MatrixBounds requiredBounds)
 {
     throw new InvalidOperationException("This is a temporary construct used for dynamic updates only.");
 }
コード例 #18
0
ファイル: DynamicObstacle.cs プロジェクト: forwolk/UnityApex
            public MatrixBounds Prepare(CellMatrix matrix, bool block)
            {
                _lastCoverage = _newCoverage;

                if (!block)
                {
                    _newCoverage = MatrixBounds.nullBounds;
                    return _lastCoverage;
                }

                var velocity = _parent.GetVelocity();

                var sensitivity = (matrix.cellSize / 2f) - (_parent.useGridObstacleSensitivity ? matrix.obstacleSensitivityRange : _parent.customSensitivity);

                var bounds = GrowBoundsByVelocity(_collider.bounds, velocity);

                _newCoverage = matrix.GetMatrixBounds(bounds, sensitivity, true);

                return MatrixBounds.Combine(_lastCoverage, _newCoverage);
            }
コード例 #19
0
ファイル: MatrixBounds.cs プロジェクト: Hengle/UnityApex
 public bool Contains(MatrixBounds other)
 {
     return((other.maxRow <= this.maxRow) && (other.minRow >= this.minRow) && (other.maxColumn <= this.maxColumn) && (other.minColumn >= this.minColumn));
 }
コード例 #20
0
 /// <summary>
 /// Gets a range of items
 /// </summary>
 /// <param name="bounds">The bounds specifying the index range.</param>
 /// <returns>The range of items that lie inside the index range given by the parameter.</returns>
 public IEnumerable <T> GetRange(MatrixBounds bounds)
 {
     return(GetRange(bounds.minColumn, bounds.maxColumn, bounds.minRow, bounds.maxRow));
 }
コード例 #21
0
ファイル: HeightQuadTree.cs プロジェクト: Hengle/UnityApex
        private UpdatingHeightTree GetUpdateTree(HeightQuadTree parent, int parentIdx, MatrixBounds suggestedBounds)
        {
            if (_subTrees != null)
            {
                for (int i = 0; i < 4; i++)
                {
                    if (_subTrees[i]._bounds.Contains(suggestedBounds))
                    {
                        return(_subTrees[i].GetUpdateTree(this, i, suggestedBounds));
                    }
                }
            }

            if (parent != null)
            {
                var freshStart = new HeightQuadTree(_bounds, _depth, _maxDepth);
                return(new UpdatingHeightTree(freshStart, parent, parentIdx));
            }

            return(null);
        }
コード例 #22
0
ファイル: HeightQuadTree.cs プロジェクト: andrewstarnes/wwtd2
 IHeightLookup IHeightLookup.PrepareForUpdate(MatrixBounds suggestedBounds, out MatrixBounds requiredBounds)
 {
     throw new InvalidOperationException("This is a temporary construct used for dynamic updates only.");
 }
コード例 #23
0
        internal IGrid Initialize(PortalCell partner, Bounds portalBounds)
        {
            var grid = GridManager.instance.GetGrid(portalBounds.center);
            if (grid == null)
            {
                return null;
            }

            _partner = partner;
            this.parent = grid.cellMatrix;
            this.position = portalBounds.center;

            _matrixBounds = grid.cellMatrix.GetMatrixBounds(portalBounds, 0.0f, true);
            _neighbourNodes = grid.cellMatrix.GetRange(_matrixBounds).ToArray();

            return grid;
        }
コード例 #24
0
ファイル: Matrix.cs プロジェクト: xwf20050250/Apex-Game-Tools
 /// <summary>
 /// Gets a range of items
 /// </summary>
 /// <param name="bounds">The bounds specifying the index range.</param>
 /// <param name="predicate">A filter predicate, only those elements that match the predicate will be included in the result.</param>
 /// <param name="result">The result to be populated by the range of items that lie inside the index range given by the parameter.</param>
 public void GetRange(MatrixBounds bounds, Func <T, bool> predicate, ICollection <T> result)
 {
     GetRange(bounds.minColumn, bounds.maxColumn, bounds.minRow, bounds.maxRow, predicate, result);
 }
コード例 #25
0
ファイル: HeightDictionary.cs プロジェクト: forwolk/UnityApex
 public IHeightLookup PrepareForUpdate(MatrixBounds suggestedBounds, out MatrixBounds requiredBounds)
 {
     requiredBounds = suggestedBounds;
     return this;
 }
コード例 #26
0
ファイル: DynamicObstacle.cs プロジェクト: forwolk/UnityApex
 public AxisBounds(Collider collider, DynamicObstacle parent)
 {
     _collider = collider;
     _parent = parent;
     _lastCoverage = _newCoverage = MatrixBounds.nullBounds;
 }
コード例 #27
0
 /// <summary>
 /// Gets a range of items
 /// </summary>
 /// <param name="bounds">The bounds specifying the index range.</param>
 /// <param name="result">The result to be populated by the range of items that lie inside the index range given by the parameter.</param>
 public void GetRange(MatrixBounds bounds, ICollection <T> result)
 {
     GetRange(bounds.minColumn, bounds.maxColumn, bounds.minRow, bounds.maxRow, result);
 }
        /// <summary>
        /// Assigns height settings to a portion of the matrix.
        /// </summary>
        /// <param name="bounds">The portion of the matrix to update.</param>
        /// <returns>
        /// An enumerator which once enumerated will do the update.
        /// </returns>
        public override IEnumerator AssignHeightSettings(MatrixBounds bounds)
        {
            if (_maxWalkableSlopeAngle >= 90f)
            {
                yield break;
            }

            var ledgeThreshold = Mathf.Tan(GameServices.heightStrategy.ledgeThreshold * Mathf.Deg2Rad) * _matrix.granularity;
            var maxHeightDiff = Mathf.Tan(_maxWalkableSlopeAngle * Mathf.Deg2Rad) * _granularity;
            var maxHeightDiffDiag = maxHeightDiff * Consts.SquareRootTwo;

            var maxColumn = bounds.maxColumn;
            var maxRow = bounds.maxRow;
            bool isPartial = (maxColumn - bounds.minColumn < _matrix.columns - 1) || (maxRow - bounds.minRow < _matrix.rows - 1);

            var rawMatrix = _matrix.rawMatrix;
            for (int x = bounds.minColumn; x <= maxColumn; x++)
            {
                for (int z = bounds.minRow; z <= maxRow; z++)
                {
                    var c = rawMatrix[x, z] as StandardCell;
                    if (c.isPermanentlyBlocked)
                    {
                        continue;
                    }

                    //Process neighbours
                    for (int dz = -1; dz <= 1; dz++)
                    {
                        for (int dx = -1; dx <= 1; dx++)
                        {
                            if (dx == 0 && dz == 0)
                            {
                                continue;
                            }

                            var n = _matrix[x + dx, z + dz] as StandardCell;
                            if (n == null || n.isPermanentlyBlocked)
                            {
                                continue;
                            }

                            var pos = n.GetRelativePositionTo(c);
                            if (!isPartial && (c.heightIntializedFrom & pos) > 0)
                            {
                                continue;
                            }

                            //If doing a partial update we need to remove the blocked flag from the neighbour first since he may not be processed on his own.
                            if (isPartial)
                            {
                                c.heightBlockedFrom &= ~pos;
                                n.heightBlockedFrom &= ~c.GetRelativePositionTo(n);
                            }

                            switch (pos)
                            {
                                //Straight neighbours
                                case NeighbourPosition.Bottom:
                                case NeighbourPosition.Top:
                                case NeighbourPosition.Left:
                                case NeighbourPosition.Right:
                                {
                                    UpdateCellHeightData(c, n, pos, maxHeightDiff, ledgeThreshold, true);
                                    break;
                                }

                                //diagonals
                                default:
                                {
                                    UpdateCellHeightData(c, n, pos, maxHeightDiffDiag, ledgeThreshold, false);
                                    break;
                                }
                            }

                            yield return null;
                        }
                    } /* end neighbour loop */
                }
            }

            if (!isPartial)
            {
                yield break;
            }

            //Update corner diagonals, this is only relevant for partial updates
            //Since the cells being updated only update their own relation to neighbours, there will potentially be 4 connections not updated,
            //those are the diagonals between the cells surround each corner of the bounds, e.g. bottom left corner the connection between the cell to the left and the cell below that corner.
            //since updates also update the involved neighbour, we only have to update 4 additional cells, and only on a specific diagonal.
            var bll = _matrix[bounds.minColumn - 1, bounds.minRow] as StandardCell;
            var blb = _matrix[bounds.minColumn, bounds.minRow - 1] as StandardCell;

            var tll = _matrix[bounds.minColumn - 1, bounds.maxRow] as StandardCell;
            var tlt = _matrix[bounds.minColumn, bounds.maxRow + 1] as StandardCell;

            var brr = _matrix[bounds.maxColumn + 1, bounds.minRow] as StandardCell;
            var brb = _matrix[bounds.maxColumn, bounds.minRow - 1] as StandardCell;

            var trr = _matrix[bounds.maxColumn + 1, bounds.maxRow] as StandardCell;
            var trt = _matrix[bounds.maxColumn, bounds.maxRow + 1] as StandardCell;

            if (bll != null && blb != null)
            {
                bll.heightBlockedFrom &= ~NeighbourPosition.BottomRight;
                blb.heightBlockedFrom &= ~NeighbourPosition.TopLeft;
                UpdateCellHeightData(bll, blb, NeighbourPosition.BottomRight, maxHeightDiffDiag, ledgeThreshold, false);
                yield return null;
            }

            if (tll != null && tlt != null)
            {
                tll.heightBlockedFrom &= ~NeighbourPosition.TopRight;
                tlt.heightBlockedFrom &= ~NeighbourPosition.BottomLeft;
                UpdateCellHeightData(tll, tlt, NeighbourPosition.TopRight, maxHeightDiffDiag, ledgeThreshold, false);
                yield return null;
            }

            if (brr != null && brb != null)
            {
                brr.heightBlockedFrom &= ~NeighbourPosition.BottomLeft;
                brb.heightBlockedFrom &= ~NeighbourPosition.TopRight;
                UpdateCellHeightData(brr, brb, NeighbourPosition.BottomLeft, maxHeightDiffDiag, ledgeThreshold, false);
                yield return null;
            }

            if (trr != null && trt != null)
            {
                trr.heightBlockedFrom &= ~NeighbourPosition.TopLeft;
                trt.heightBlockedFrom &= ~NeighbourPosition.BottomRight;
                UpdateCellHeightData(trr, trt, NeighbourPosition.TopLeft, maxHeightDiffDiag, ledgeThreshold, false);
                yield return null;
            }
        }
 /// <summary>
 /// Assigns height settings to a portion of the matrix.
 /// </summary>
 /// <param name="bounds">The portion of the matrix to update.</param>
 /// <returns>An enumerator which once enumerated will do the update.</returns>
 public abstract IEnumerator AssignHeightSettings(MatrixBounds bounds);