/// <summary> /// Initializes a new instance of the <see cref="CrossGridVectorField"/> class. /// </summary> /// <param name="group">The group.</param> /// <param name="path">The path.</param> /// <param name="options">The options.</param> public CrossGridVectorField(TransientGroup <IUnitFacade> group, Path path, VectorFieldOptions options) { Ensure.ArgumentNotNull(group, "group"); this.group = group; _currentPath = path; var modelUnit = group.modelUnit; _unitProperties = modelUnit; var pathOptions = modelUnit.pathFinderOptions; // cache options locally _allowCornerCutting = pathOptions.allowCornerCutting; _allowDiagonals = !pathOptions.preventDiagonalMoves; _announceAllNodes = modelUnit.pathNavigationOptions.announceAllNodes; _obstacleStrengthFactor = options.obstacleStrengthFactor; _builtInContainment = options.builtInContainment; _updateInterval = options.updateInterval; _paddingIncrease = options.paddingIncrease; _maxExtraPadding = options.maxExtraPadding; _boundsPadding = options.boundsPadding; _boundsRecalculateThreshold = options.boundsRecalculateThreshold; _expectedGroupGrowthFactor = 1f + options.expectedGroupGrowthFactor; // pre-allocate lists _openSet = new SimpleQueue <Cell>(31); _tempWalkableNeighbours = new DynamicArray <Cell>(8); _extraTempWalkableNeighbours = new DynamicArray <Cell>(8); _groupBounds = new RectangleXZ(group.centerOfGravity, _boundsPadding, _boundsPadding); _grids = new List <IGrid>(4); }
private GridSection[] CreateSubSections(Vector3 start) { var subSectionsX = Math.Max(this.subSectionsX, 1); var subSectionsZ = Math.Max(this.subSectionsZ, 1); var overLap = this.subSectionsCellOverlap * this.cellSize; var subSectionWidth = ((this.sizeX + ((subSectionsX - 1) * this.subSectionsCellOverlap)) * this.cellSize) / (subSectionsX * 1.0f); var subSectionDepth = ((this.sizeZ + ((subSectionsZ - 1) * this.subSectionsCellOverlap)) * this.cellSize) / (subSectionsZ * 1.0f); var subSectionCount = subSectionsX * subSectionsZ; var gridSections = new GridSection[subSectionCount]; int idx = 0; for (int i = 0; i < subSectionsX; i++) { for (int j = 0; j < subSectionsZ; j++) { var rect = new RectangleXZ( start.x + (subSectionWidth * i) - (overLap * i), start.z + (subSectionDepth * j) - (overLap * j), subSectionWidth, subSectionDepth); gridSections[idx++] = new GridSection(rect); } } return(gridSections); }
/// <summary> /// Touches the sections overlapping with the specified bounds, marking them as changed. /// </summary> /// <param name="b">The bounds.</param> public void TouchSections(MatrixBounds b) { var rect = new RectangleXZ( _cellMatrix.start.x + (b.minColumn * _cellSize), _cellMatrix.start.z + (b.minRow * _cellSize), b.maxColumn * _cellSize, b.minRow * _cellSize); for (int i = 0; i < _gridSections.Length; i++) { if (_gridSections[i].bounds.Overlaps(rect)) { _gridSections[i].Touch(); } } }
private bool ConstructGroupBounds(bool forceConstruction = false) { int membersCount = group.count; if (membersCount == 0) { return(false); } // find minimum and maximum coordinates for the group float minX = float.MaxValue, minZ = float.MaxValue, maxX = float.MinValue, maxZ = float.MinValue; Vector3 groupCog = Vector3.zero; for (int i = 0; i < membersCount; i++) { var member = group[i]; if (member == null) { continue; } var pos = member.position; if (pos.x < minX) { minX = pos.x; } if (pos.z < minZ) { minZ = pos.z; } if (pos.x > maxX) { maxX = pos.x; } if (pos.z > maxZ) { maxZ = pos.z; } // sum up all unit positions groupCog += pos; } // divide the summed up unit positions by the unit count, in order to get the "average group position" or center of gravity groupCog /= membersCount; if (!forceConstruction && ((groupCog - _groupBounds.center).sqrMagnitude < (_boundsRecalculateThreshold * _boundsRecalculateThreshold))) { // if not forcing the construction, check whether the group has moved from its last group bounds center enough return(false); } // first grid is the one where the group center is var grid = GridManager.instance.GetGrid(groupCog); if (grid == null) { return(false); } if (_portalNewGroupThreshold <= 0f) { // if we have not set our portal new group threshold yet, then do it (based on diagonal cell size) _portalNewGroupThreshold = (grid.cellSize * Consts.SquareRootTwo) + 0.1f; } _grids.Clear(); AddGrid(grid); // push the minimum and maximum values by the bounds padding and the potential extra padding resultant from growing bounds var padding = _boundsPadding + _extraPadding; minX -= padding; minZ -= padding; maxX += padding; maxZ += padding; float yPos = groupCog.y; // find minimum and maximum cells, in order to construct the group bounds "cell-aligned" and in order to add all relevant grids Vector3 vecMinXZ = new Vector3(minX, yPos, minZ); var gridMinXZ = GridManager.instance.GetGrid(vecMinXZ); // bottom left corner grid if (gridMinXZ != null) { AddGrid(gridMinXZ); Cell minXZ = gridMinXZ.GetCell(vecMinXZ, true); minX = minXZ.position.x; minZ = minXZ.position.z; } Vector3 vecMaxXZ = new Vector3(maxX, yPos, maxZ); var gridMaxXZ = GridManager.instance.GetGrid(vecMaxXZ); // top right corner grid if (gridMaxXZ != null) { AddGrid(gridMaxXZ); Cell maxXZ = gridMaxXZ.GetCell(vecMaxXZ, true); maxX = maxXZ.position.x; maxZ = maxXZ.position.z; } // top left corner grid var gridMinXMaxZ = GridManager.instance.GetGrid(new Vector3(minX, yPos, maxZ)); AddGrid(gridMinXMaxZ); // bottom right corner grid var gridMaxXMinZ = GridManager.instance.GetGrid(new Vector3(maxX, yPos, minZ)); AddGrid(gridMaxXMinZ); // finally, actually instantiate the new group bounds _groupBounds = new RectangleXZ(minX, minZ, (maxX - minX), (maxZ - minZ)); return(true); }
private bool ConstructGroupBounds(bool forceConstruction = false) { int membersCount = group.count; if (membersCount == 0) { return(false); } // find minimum and maximum coordinates for the group float minX = float.MaxValue, minZ = float.MaxValue, maxX = float.MinValue, maxZ = float.MinValue; Vector3 groupCog = Vector3.zero; for (int i = 0; i < membersCount; i++) { var member = group[i]; if (member == null) { continue; } var pos = member.position; if (pos.x < minX) { minX = pos.x; } if (pos.z < minZ) { minZ = pos.z; } if (pos.x > maxX) { maxX = pos.x; } if (pos.z > maxZ) { maxZ = pos.z; } // sum up all unit positions groupCog += pos; } // divide the summed up unit positions by the unit count, in order to get the "average group position" or center of gravity groupCog /= membersCount; if (!forceConstruction && ((groupCog - _groupBounds.center).sqrMagnitude < (_boundsRecalculateThreshold * _boundsRecalculateThreshold))) { // if not forcing the construction, check whether the group has moved from its last group bounds center enough return(false); } // push the minimum and maximum values by the bounds padding and the potential extra padding resultant from growing bounds var padding = _boundsPadding + _extraPadding; minX -= padding; minZ -= padding; maxX += padding; maxZ += padding; float yPos = groupCog.y; // find minimum and maximum cells, in order to construct the group bounds "cell-aligned" Vector3 vecMinXZ = new Vector3(minX, yPos, minZ); Cell minXZ = _grid.GetCell(vecMinXZ, true); minX = minXZ.position.x; minZ = minXZ.position.z; Vector3 vecMaxXZ = new Vector3(maxX, yPos, maxZ); Cell maxXZ = _grid.GetCell(vecMaxXZ, true); maxX = maxXZ.position.x; maxZ = maxXZ.position.z; // finally, actually instantiate the new group bounds _groupBounds = new RectangleXZ(minX, minZ, (maxX - minX), (maxZ - minZ)); return(true); }
/// <summary> /// Initializes a new instance of the <see cref="GridSection"/> class. /// </summary> /// <param name="rect">The rectangle defining the section.</param> public GridSection(RectangleXZ rect) { this.bounds = rect; this.lastChanged = -1f; }