/// <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)); }
internal IGrid CreateForEditor(CellMatrixData data) { var cellMatrix = CellMatrix.CreateForEditor(this, data); var subSections = CreateSubSections(cellMatrix.start); return(Grid.Create(cellMatrix, subSections)); }
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); }
/// <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); }
/// <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)); }
/// <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; }
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; }
/// <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); }
/// <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(); }
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); }
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); } }
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); }
/// <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); } } }
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)); }
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); }
/// <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 }); }
/// <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); }
public Cell Create(CellMatrix parent, Vector3 position, int matrixPosX, int matrixPosZ, bool blocked) { return(new FlatCell(parent, position, matrixPosX, matrixPosZ, blocked)); }
/// <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) { }
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); } }
/// <summary> /// Initializes a new instance of the <see cref="HeightSettingsProviderBase"/> class. /// </summary> /// <param name="matrix">The matrix.</param> protected HeightSettingsProviderBase(CellMatrix matrix) { _matrix = matrix; }
internal MatrixIncrementalInitializer(ICellMatrixConfiguration cfg) { _matrix = new CellMatrix(cfg); _iter = _matrix.Populate(); }
/// <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); } }
/// <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); } }
protected override void PrepareForInitialization(CellMatrix matrix) { /* NOOP */ }
protected abstract void PrepareForInitialization(CellMatrix matrix);