Пример #1
0
        /// <summary>
        /// Creates a grid configuration based on the property values of this instance.
        /// </summary>
        /// <returns>The grid configuration</returns>
        public IGrid Create()
        {
            var cellMatrix  = CellMatrix.Create(this);
            var subSections = CreateSubSections(cellMatrix.start);

            return(Grid.Create(cellMatrix, subSections));
        }
Пример #2
0
        internal IGrid CreateForEditor(CellMatrixData data)
        {
            var cellMatrix  = CellMatrix.CreateForEditor(this, data);
            var subSections = CreateSubSections(cellMatrix.start);

            return(Grid.Create(cellMatrix, subSections));
        }
Пример #3
0
            public MatrixBounds Prepare(CellMatrix matrix, bool block)
            {
                MatrixBounds combinedCoverage;

                //The bounds used last check
                _oldBounds.Mirror(_actualBounds);

                if (!block)
                {
                    //Only unblock is required, so the affected area is the most recent coverage
                    combinedCoverage = _cellCoverage;
                    _actualBounds.Reset();
                    _cellCoverage = MatrixBounds.nullBounds;

                    return(combinedCoverage);
                }

                var velocity = _parent.GetVelocity();

                var obstacleSensitivityRange = _parent.useGridObstacleSensitivity ? matrix.obstacleSensitivityRange : _parent.customSensitivity;

                PrepareHull(velocity, obstacleSensitivityRange);

                //Get the axis-aligned bounding box
                var bounds = _actualBounds.CalculateBounds();

                //Get the new coverage, combine it with the old for coverage of both those to unblock and block
                var newCoverage = matrix.GetMatrixBounds(bounds, matrix.cellSize / 2f, true);

                combinedCoverage = MatrixBounds.Combine(_cellCoverage, newCoverage);
                _cellCoverage    = newCoverage;

                return(combinedCoverage);
            }
Пример #4
0
        /// <summary>
        /// Creates a grid.
        /// </summary>
        /// <param name="matrix">The cell matrix.</param>
        /// <param name="gridSections">The grid sections array</param>
        /// <returns>The grid</returns>
        public static Grid Create(CellMatrix matrix, GridSection[] gridSections)
        {
            var g = new Grid();

            g.Initialize(matrix, gridSections);

            return(g);
        }
Пример #5
0
        /// <summary>
        /// Creates a grid configuration based on the prebaked data
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns>The grid.</returns>
        public IGrid Create(CellMatrixData data)
        {
            Ensure.ArgumentNotNull(data, "data");

            var cellMatrix  = CellMatrix.Create(this, data);
            var subSections = CreateSubSections(cellMatrix.start);

            return(Grid.Create(cellMatrix, subSections));
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="StandardCellHeightSettingsProvider"/> class.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        public StandardCellHeightSettingsProvider(CellMatrix matrix)
            : base(matrix)
        {
            var settings = GameServices.heightStrategy.unitsHeightNavigationCapability;

            _maxWalkableSlopeAngle = settings.maxSlopeAngle;
            _maxClimbHeight        = settings.maxClimbHeight;
            _maxDropHeight         = settings.maxDropHeight;
            _granularity           = GameServices.heightStrategy.sampleGranularity;
        }
Пример #7
0
            public InnerProvider(CellMatrix matrix, StandardCellHeightSettingsProvider parent)
            {
                _matrix = matrix;
                _maxWalkableSlopeAngle = parent._maxWalkableSlopeAngle;
                _maxClimbHeight        = parent._maxClimbHeight;
                _maxDropHeight         = parent._maxDropHeight;
                _granularity           = parent._granularity;

                _offsets       = new Vector3[3];
                _heightSampler = (GameServices.heightStrategy.heightMode == HeightSamplingMode.HeightMap) ? (ISampleHeightsSimple)matrix : GameServices.heightStrategy.heightSampler;
            }
Пример #8
0
        /// <summary>
        /// Creates a cell matrix based on the given configuration and stored data.
        /// </summary>
        /// <param name="cfg">The configuration.</param>
        /// <param name="data">The data.</param>
        /// <returns>The matrix</returns>
        public static CellMatrix Create(ICellMatrixConfiguration cfg, CellMatrixData data)
        {
            var matrix = new CellMatrix(cfg);

            var iter = matrix.Populate(data);

            while (iter.MoveNext())
            {
                /* NOOP, we just iterate over all */
            }

            return(matrix);
        }
Пример #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RichCell"/> class.
        /// </summary>
        /// <param name="parent">The cell matrix that owns this cell.</param>
        /// <param name="position">The position.</param>
        /// <param name="matrixPosX">The matrix position x.</param>
        /// <param name="matrixPosZ">The matrix position z.</param>
        /// <param name="blocked">if set to <c>true</c> the cell will appear permanently blocked.</param>
        public RichCell(CellMatrix parent, Vector3 position, int matrixPosX, int matrixPosZ, bool blocked)
            : base(parent, position, matrixPosX, matrixPosZ, blocked)
        {
            //While a bit redundant (e.g. index 4 being self) it makes it faster to index
            _heightData = new HeightData[9];
            for (int i = 0; i < 9; i++)
            {
                //We use this to indicate an uninitialized state
                _heightData[i].slope = 100f;
            }

            //Worst case scenario for checking all directions
            _worstCase = new HeightData();
        }
Пример #10
0
        internal static CellMatrix CreateForEditor(ICellMatrixConfiguration cfg, CellMatrixData data)
        {
            var matrix = new CellMatrix(cfg);

            if (data == null)
            {
                matrix._heightLookup = matrix.CreateHeightLookup(0);
            }
            else
            {
                matrix.InitHeightMapForEditor(data);
            }

            return(matrix);
        }
Пример #11
0
        float ISampleHeightsSimple.SampleHeight(Vector3 position, CellMatrix matrix)
        {
            var fx = (position.x - _start.x) / _granularity;
            var fz = (position.z - _start.z) / _granularity;

            var x = Mathf.RoundToInt(fx);
            var z = Mathf.RoundToInt(fz);

            float height;

            if (_heightLookup.TryGetHeight(x, z, out height))
            {
                return(height);
            }

            return(this.origin.y);
        }
        /// <summary>
        /// Resets the clearance in the matrix.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns></returns>
        public IEnumerator Reset(CellMatrix matrix)
        {
            var rows      = matrix.rows;
            var columns   = matrix.columns;
            var rawMatrix = matrix.rawMatrix;

            for (int x = 1; x < columns - 1; x++)
            {
                for (int z = 1; z < rows - 1; z++)
                {
                    var cc = rawMatrix[x, z] as IHaveClearance;
                    cc.clearance = float.MaxValue;
                }

                yield return(null);
            }
        }
Пример #13
0
        private IEnumerator CreateIncrementally(Action <IGrid> callback)
        {
            var cellMatrixInitializer = CellMatrix.CreateIncrementally(this);

            while (cellMatrixInitializer.isInitializing)
            {
                yield return(null);
            }

            var cellMatrix = cellMatrixInitializer.matrix;

            var subSections = CreateSubSections(cellMatrix.start);

            yield return(null);

            var grid = Grid.Create(cellMatrix, subSections);

            callback(grid);
        }
Пример #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Cell"/> class.
        /// </summary>
        /// <param name="parent">The cell matrix that owns this cell.</param>
        /// <param name="position">The position.</param>
        /// <param name="matrixPosX">The matrix position x.</param>
        /// <param name="matrixPosZ">The matrix position z.</param>
        /// <param name="blocked">if set to <c>true</c> the cell will appear permanently blocked.</param>
        public Cell(CellMatrix parent, Vector3 position, int matrixPosX, int matrixPosZ, bool blocked)
        {
            Ensure.ArgumentNotNull(parent, "parent");

            this.position   = position;
            this.matrixPosX = matrixPosX;
            this.matrixPosZ = matrixPosZ;

            _parent             = parent;
            _permanentlyBlocked = blocked;

            _neighbours = NeighbourPosition.None;

            if (matrixPosX < (parent.columns - 1))
            {
                _neighbours |= NeighbourPosition.Right;

                if (matrixPosZ < (parent.rows - 1))
                {
                    _neighbours |= (NeighbourPosition.Top | NeighbourPosition.TopRight);
                }

                if (matrixPosZ > 0)
                {
                    _neighbours |= (NeighbourPosition.Bottom | NeighbourPosition.BottomRight);
                }
            }

            if (matrixPosX > 0)
            {
                _neighbours |= NeighbourPosition.Left;

                if (matrixPosZ < (parent.rows - 1))
                {
                    _neighbours |= (NeighbourPosition.Top | NeighbourPosition.TopLeft);
                }

                if (matrixPosZ > 0)
                {
                    _neighbours |= (NeighbourPosition.Bottom | NeighbourPosition.BottomLeft);
                }
            }
        }
Пример #15
0
            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));
            }
Пример #16
0
        private void Initialize(CellMatrix matrix, GridSection[] gridSections)
        {
            //Setup the basic state
            _cellMatrix   = matrix;
            _gridSections = gridSections;
            _origin       = _cellMatrix.origin;
            _cellSize     = _cellMatrix.cellSize;
            _sizeX        = _cellMatrix.columns;
            _sizeZ        = _cellMatrix.rows;

            //Perimeters
            _left   = new Perimeter(Vector3.left, GetPerimeterEdge(Vector3.left, false), GetPerimeterEdge(Vector3.left, true));
            _right  = new Perimeter(Vector3.right, GetPerimeterEdge(Vector3.right, false), GetPerimeterEdge(Vector3.right, true));
            _top    = new Perimeter(Vector3.forward, GetPerimeterEdge(Vector3.forward, false), GetPerimeterEdge(Vector3.forward, true));
            _bottom = new Perimeter(Vector3.back, GetPerimeterEdge(Vector3.back, false), GetPerimeterEdge(Vector3.back, true));

            _left.SetPerpendiculars(_top, _bottom, _cellSize);
            _right.SetPerpendiculars(_bottom, _top, _cellSize);
            _top.SetPerpendiculars(_right, _left, _cellSize);
            _bottom.SetPerpendiculars(_left, _right, _cellSize);
        }
Пример #17
0
        /// <summary>
        /// Gets the perpendicular offsets.
        /// </summary>
        /// <param name="matrix">The matrix to update.</param>
        /// <param name="dx">The x delta.</param>
        /// <param name="dz">The z delta.</param>
        /// <returns>An array with 3 entries, representing left side offset, no offset and right side offset.</returns>
        protected Vector3[] GetPerpendicularOffsets(CellMatrix matrix, int dx, int dz)
        {
            Vector3 ppd;
            var     obstacleSensitivityRange = Mathf.Min(matrix.cellSize / 2f, matrix.obstacleSensitivityRange);

            if (dx != 0 && dz != 0)
            {
                var offSet = obstacleSensitivityRange / Consts.SquareRootTwo;
                ppd = new Vector3(offSet * -dx, 0.0f, offSet * dz);
            }
            else
            {
                ppd = new Vector3(obstacleSensitivityRange * dz, 0.0f, obstacleSensitivityRange * dx);
            }

            return(new Vector3[]
            {
                Vector3.zero,
                ppd,
                ppd * -1
            });
        }
Пример #18
0
        /// <summary>
        /// Creates a data instance from the specified configuration.
        /// </summary>
        /// <param name="matrix">The matrix to store.</param>
        /// <returns>The data instance</returns>
        public static CellMatrixData Create(CellMatrix matrix)
        {
            CellMatrixData data;

            var c = matrix[0, 0];

            if (c is RichCell)
            {
                data = ScriptableObject.CreateInstance <RichCellData>();
            }
            else if (c is FlatCell)
            {
                data = ScriptableObject.CreateInstance <FlatCellData>();
            }
            else
            {
                data = ScriptableObject.CreateInstance <StandardCellData>();
            }

            data.Initialize(matrix);

            return(data);
        }
Пример #19
0
 public Cell Create(CellMatrix parent, Vector3 position, int matrixPosX, int matrixPosZ, bool blocked)
 {
     return(new FlatCell(parent, position, matrixPosX, matrixPosZ, blocked));
 }
Пример #20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FlatCell"/> class.
 /// </summary>
 /// <param name="parent">The cell matrix that owns this cell.</param>
 /// <param name="position">The position.</param>
 /// <param name="matrixPosX">The matrix position x.</param>
 /// <param name="matrixPosZ">The matrix position z.</param>
 /// <param name="blocked">if set to <c>true</c> the cell will appear permanently blocked.</param>
 public FlatCell(CellMatrix parent, Vector3 position, int matrixPosX, int matrixPosZ, bool blocked)
     : base(parent, position, matrixPosX, matrixPosZ, blocked)
 {
 }
Пример #21
0
        private void Initialize(CellMatrix cellMatrix)
        {
            var sizeX = cellMatrix.columns;
            var sizeZ = cellMatrix.rows;

            var matrix = cellMatrix.rawMatrix;

            PrepareForInitialization(cellMatrix);

            var blockedIndexsList = new List <int>();

            for (int x = 0; x < sizeX; x++)
            {
                for (int z = 0; z < sizeZ; z++)
                {
                    var arrIdx = (z * sizeX) + x;

                    var cell = matrix[x, z];

                    if (!cell.IsWalkableToAny())
                    {
                        blockedIndexsList.Add(arrIdx);
                    }

                    RecordCellData(cell, arrIdx);
                }
            }

            FinalizeInitialization();

            _blockedIndexes = blockedIndexsList.ToArray();

            if (GameServices.heightStrategy.heightMode == HeightSamplingMode.HeightMap)
            {
                var heightSize = cellMatrix.heightMapSize;
                var heightX    = heightSize.x;
                var heightZ    = heightSize.z;

                _heightEntries = cellMatrix.heightMapEntries;
                _heights       = new float[heightX * heightZ];
                _heightIndices = new int[heightX * heightZ];

                int   indicesCount = 0;
                float lastHeight   = float.NegativeInfinity;
                for (int x = 0; x < heightX; x++)
                {
                    for (int z = 0; z < heightZ; z++)
                    {
                        var arrIdx = (x * heightZ) + z;

                        var curHeight = cellMatrix.SampleHeight(x, z);
                        if (curHeight != lastHeight)
                        {
                            lastHeight                     = curHeight;
                            _heights[indicesCount]         = curHeight;
                            _heightIndices[indicesCount++] = arrIdx;
                        }
                    }
                }

                _heights[indicesCount]         = 0f;
                _heightIndices[indicesCount++] = (heightZ * heightX);

                _heights       = Shrink(_heights, indicesCount);
                _heightIndices = Shrink(_heightIndices, indicesCount);
            }
        }
Пример #22
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HeightSettingsProviderBase"/> class.
 /// </summary>
 /// <param name="matrix">The matrix.</param>
 protected HeightSettingsProviderBase(CellMatrix matrix)
 {
     _matrix = matrix;
 }
Пример #23
0
 internal MatrixIncrementalInitializer(ICellMatrixConfiguration cfg)
 {
     _matrix = new CellMatrix(cfg);
     _iter   = _matrix.Populate();
 }
Пример #24
0
 /// <summary>
 /// Updates the data with the new state of the matrix.
 /// </summary>
 /// <param name="matrix">The matrix.</param>
 public void Refresh(CellMatrix matrix)
 {
     Initialize(matrix);
 }
 public InnerProvider(CellMatrix matrix)
 {
     _matrix        = matrix;
     _offsets       = new Vector3[3];
     _heightSampler = (GameServices.heightStrategy.heightMode == HeightSamplingMode.HeightMap) ? (ISampleHeightsSimple)_matrix : GameServices.heightStrategy.heightSampler;
 }
        /// <summary>
        /// Assigns height settings to a portion of the _matrix.
        /// </summary>
        /// <param name="matrix">The matrix to update.</param>
        /// <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(CellMatrix matrix, MatrixBounds bounds)
        {
            var inner = new InnerProvider(matrix);

            return(inner.AssignHeightSettings(bounds));
        }
        /// <summary>
        /// Sets the clearance values for all cells in the matrix.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns></returns>
        public IEnumerator SetClearance(CellMatrix matrix)
        {
            var rows      = matrix.rows;
            var columns   = matrix.columns;
            var cellSize  = matrix.cellSize;
            var halfCell  = cellSize * 0.5f;
            var rawMatrix = matrix.rawMatrix;

            //First set the perimeter which is always 0 or ½ cell size. This allows us to use the raw matrix for the rest, skipping index range checks.
            for (int x = 0; x < columns; x++)
            {
                var c  = rawMatrix[x, 0];
                var cc = c as IHaveClearance;
                cc.clearance = c.isPermanentlyBlocked ? 0f : halfCell;

                c            = rawMatrix[x, rows - 1];
                cc           = c as IHaveClearance;
                cc.clearance = c.isPermanentlyBlocked ? 0f : halfCell;
            }

            yield return(null);

            for (int z = 1; z < rows - 1; z++)
            {
                var c  = rawMatrix[0, z];
                var cc = c as IHaveClearance;
                cc.clearance = c.isPermanentlyBlocked ? 0f : halfCell;

                c            = rawMatrix[columns - 1, z];
                cc           = c as IHaveClearance;
                cc.clearance = c.isPermanentlyBlocked ? 0f : halfCell;
            }

            yield return(null);

            //Do the rest. First from left to right and the reversed
            for (int x = 1; x < columns - 1; x++)
            {
                for (int z = 1; z < rows - 1; z++)
                {
                    var c  = rawMatrix[x, z];
                    var cc = c as IHaveClearance;
                    if (c.isPermanentlyBlocked)
                    {
                        cc.clearance = 0f;
                        continue;
                    }

                    var cy       = c.position.y;
                    var minClear = float.MaxValue;
                    for (int nx = -1; nx < 2; nx++)
                    {
                        for (int nz = -1; nz < 2; nz++)
                        {
                            var n  = rawMatrix[x + nx, z + nz];
                            var nc = n as IHaveClearance;

                            //Height is only blocking if the neighbour is higher. Lower neighbours do not affect clearance, e..g the unit is allowed to hover partly in open air.
                            if (n.isPermanentlyBlocked || (n.position.y - cy) > _heightDiffThreshold)
                            {
                                minClear = -halfCell;
                                nz       = nx = 2;
                            }
                            else if (nc.clearance < float.MaxValue)
                            {
                                minClear = Mathf.Min(minClear, nc.clearance);
                            }
                        }
                    }

                    cc.clearance = minClear + cellSize;
                }

                yield return(null);
            }

            for (int x = columns - 2; x >= 1; x--)
            {
                for (int z = 1; z < rows - 1; z++)
                {
                    var c  = rawMatrix[x, z];
                    var cc = c as IHaveClearance;
                    if (c.isPermanentlyBlocked)
                    {
                        cc.clearance = 0f;
                        continue;
                    }

                    var cy       = c.position.y;
                    var minClear = float.MaxValue;
                    for (int nx = -1; nx < 2; nx++)
                    {
                        for (int nz = -1; nz < 2; nz++)
                        {
                            var n  = rawMatrix[x + nx, z + nz];
                            var nc = n as IHaveClearance;

                            if (n.isPermanentlyBlocked || (n.position.y - cy) > _heightDiffThreshold)
                            {
                                minClear = -halfCell;
                                nz       = nx = 2;
                            }
                            else if (nc.clearance < float.MaxValue)
                            {
                                minClear = Mathf.Min(minClear, nc.clearance);
                            }
                        }
                    }

                    cc.clearance = minClear + cellSize;
                }

                yield return(null);
            }
        }
Пример #28
0
        /// <summary>
        /// Sets the clearance values for all cells in the matrix.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns></returns>
        public IEnumerator SetClearance(CellMatrix matrix)
        {
            var rows      = matrix.rows;
            var columns   = matrix.columns;
            var cellSize  = matrix.cellSize;
            var halfCell  = cellSize * 0.5f;
            var rawMatrix = matrix.rawMatrix;

            //First set the perimeter which is always 0 or ½ cell size. This allows us to use the raw matrix for the rest, skipping index range checks.
            for (int x = 0; x < columns; x++)
            {
                var c = rawMatrix[x, 0] as FlatClearanceCell;
                c.clearance = c.isPermanentlyBlocked ? 0f : halfCell;

                c           = rawMatrix[x, rows - 1] as FlatClearanceCell;
                c.clearance = c.isPermanentlyBlocked ? 0f : halfCell;
            }

            yield return(null);

            for (int z = 1; z < rows - 1; z++)
            {
                var c = rawMatrix[0, z] as FlatClearanceCell;
                c.clearance = c.isPermanentlyBlocked ? 0f : halfCell;

                c           = rawMatrix[columns - 1, z] as FlatClearanceCell;
                c.clearance = c.isPermanentlyBlocked ? 0f : halfCell;
            }

            yield return(null);

            //Do the rest. First from left to right and the reversed
            for (int x = 1; x < columns - 1; x++)
            {
                for (int z = 1; z < rows - 1; z++)
                {
                    var c = rawMatrix[x, z] as FlatClearanceCell;
                    if (c.isPermanentlyBlocked)
                    {
                        c.clearance = 0f;
                        continue;
                    }

                    var minClear = float.MaxValue;
                    for (int nx = -1; nx < 2; nx++)
                    {
                        for (int nz = -1; nz < 2; nz++)
                        {
                            var n = rawMatrix[x + nx, z + nz] as FlatClearanceCell;

                            if (n.isPermanentlyBlocked)
                            {
                                minClear = -halfCell;
                                nz       = nx = 2;
                            }
                            else if (n.clearance < float.MaxValue)
                            {
                                minClear = Mathf.Min(minClear, n.clearance);
                            }
                        }
                    }

                    c.clearance = minClear + cellSize;
                }

                yield return(null);
            }

            for (int x = columns - 2; x >= 1; x--)
            {
                for (int z = 1; z < rows - 1; z++)
                {
                    var c = rawMatrix[x, z] as FlatClearanceCell;
                    if (c.isPermanentlyBlocked)
                    {
                        c.clearance = 0f;
                        continue;
                    }

                    var minClear = float.MaxValue;
                    for (int nx = -1; nx < 2; nx++)
                    {
                        for (int nz = -1; nz < 2; nz++)
                        {
                            var n = rawMatrix[x + nx, z + nz] as FlatClearanceCell;

                            if (n.isPermanentlyBlocked)
                            {
                                minClear = -halfCell;
                                nz       = nx = 2;
                            }
                            else if (n.clearance < float.MaxValue)
                            {
                                minClear = Mathf.Min(minClear, n.clearance);
                            }
                        }
                    }

                    c.clearance = minClear + cellSize;
                }

                yield return(null);
            }
        }
Пример #29
0
 protected override void PrepareForInitialization(CellMatrix matrix)
 {
     /* NOOP */
 }
Пример #30
0
 protected abstract void PrepareForInitialization(CellMatrix matrix);