/// <summary> /// Updates the region rect2D. Needed if points is updated manually. /// </summary> /// <param name="newPoints">New points.</param> /// <param name="inflate">If set to <c>true</c> points will be slightly displaced to prevent polygon clipping floating point issues.</param> public void UpdatePointsAndRect(Vector2[] newPoints, bool inflate = false) { sanitized = false; points = newPoints; ComputeBounds(); if (inflate) { Vector2 tmp = Misc.Vector2zero; for (int k = 0; k < points.Length; k++) { FastVector.NormalizedDirection(ref center, ref points [k], ref tmp); FastVector.Add(ref points [k], ref tmp, 0.00001f); } } }
/// <summary> /// Returns an optimal route from startPosition to endPosition with options. /// </summary> /// <returns>The route.</returns> /// <param name="startPosition">Start position in map coordinates (-0.5...0.5)</param> /// <param name="endPosition">End position in map coordinates (-0.5...0.5)</param> /// <param name="totalCost">The total cost of traversing the path</param> /// <param name="terrainCapability">Type of terrain that the unit can pass through</param> /// <param name="minAltitude">Minimum altitude (0..1)</param> /// <param name="maxAltitude">Maximum altutude (0..1)</param> /// <param name="maxSearchCost">Maximum search cost for the path finding algorithm. A value of -1 will use the global default defined by pathFindingMaxCost</param> public List <Vector2> FindRoute(Vector2 startPosition, Vector2 endPosition, out int totalCost, TERRAIN_CAPABILITY terrainCapability = TERRAIN_CAPABILITY.Any, float minAltitude = 0, float maxAltitude = 1f, int maxSearchCost = -1, int maxSearchSteps = -1) { ComputeRouteMatrix(terrainCapability, minAltitude, maxAltitude); totalCost = 0; Point startingPoint = new Point((int)((startPosition.x + 0.5f) * EARTH_ROUTE_SPACE_WIDTH), (int)((startPosition.y + 0.5f) * EARTH_ROUTE_SPACE_HEIGHT)); Point endingPoint = new Point((int)((endPosition.x + 0.5f + 0.5f / EARTH_ROUTE_SPACE_WIDTH) * EARTH_ROUTE_SPACE_WIDTH), (int)((endPosition.y + 0.5f + 0.5f / EARTH_ROUTE_SPACE_HEIGHT) * EARTH_ROUTE_SPACE_HEIGHT)); endingPoint.X = Mathf.Clamp(endingPoint.X, 0, EARTH_ROUTE_SPACE_WIDTH - 1); endingPoint.Y = Mathf.Clamp(endingPoint.Y, 0, EARTH_ROUTE_SPACE_HEIGHT - 1); // Helper to find a minimum path in case the destination position is on a different terrain type if (terrainCapability == TERRAIN_CAPABILITY.OnlyWater) { int arrayIndex = endingPoint.Y * EARTH_ROUTE_SPACE_WIDTH + endingPoint.X; if ((earthRouteMatrix [arrayIndex] & 4) == 0) { int regionIndex = -1; int countryIndex = GetCountryIndex(endPosition, out regionIndex); if (countryIndex >= 0 && regionIndex >= 0) { List <Vector2> coastPositions = GetCountryCoastalPoints(countryIndex, regionIndex, 0.001f); float minDist = float.MaxValue; Vector2 bestPosition = Misc.Vector2zero; int coastPositionsCount = coastPositions.Count; // Get nearest position to the ship which is on water for (int k = 0; k < coastPositionsCount; k++) { Vector2 waterPosition; if (ContainsWater(coastPositions [k], 0.001f, out waterPosition)) { float dist = FastVector.SqrDistance(ref endPosition, ref waterPosition); // (endPosition - waterPosition).sqrMagnitude; if (dist < minDist) { minDist = dist; bestPosition = waterPosition; } } } if (minDist < float.MaxValue) { endPosition = bestPosition; } endingPoint = new Point((int)((endPosition.x + 0.5f + 0.5f / EARTH_ROUTE_SPACE_WIDTH) * EARTH_ROUTE_SPACE_WIDTH), (int)((endPosition.y + 0.5f + 0.5f / EARTH_ROUTE_SPACE_HEIGHT) * EARTH_ROUTE_SPACE_HEIGHT)); arrayIndex = endingPoint.Y * EARTH_ROUTE_SPACE_WIDTH + endingPoint.X; if ((earthRouteMatrix [arrayIndex] & 4) == 0) { Vector2 direction = Misc.Vector2zero; for (int k = 1; k <= 10; k++) { if (k == 10 || startPosition == endPosition) { return(null); } FastVector.NormalizedDirection(ref endPosition, ref startPosition, ref direction); Vector2 p = endPosition + direction * (float)k / EARTH_ROUTE_SPACE_WIDTH; endingPoint = new Point((int)((p.x + 0.5f + 0.5f / EARTH_ROUTE_SPACE_WIDTH) * EARTH_ROUTE_SPACE_WIDTH), (int)((p.y + 0.5f + 0.5f / EARTH_ROUTE_SPACE_HEIGHT) * EARTH_ROUTE_SPACE_HEIGHT)); arrayIndex = endingPoint.Y * EARTH_ROUTE_SPACE_WIDTH + endingPoint.X; if ((earthRouteMatrix [arrayIndex] & 4) > 0) { break; } } } } } } List <Vector2> routePoints = null; // Minimum distance for routing? if (Mathf.Abs(endingPoint.X - startingPoint.X) > 0 || Mathf.Abs(endingPoint.Y - startingPoint.Y) > 0) { finder.Formula = _pathFindingHeuristicFormula; finder.MaxSearchCost = maxSearchCost < 0 ? _pathFindingMaxCost : maxSearchCost; finder.MaxSteps = maxSearchSteps < 0 ? _pathFindingMaxSteps : maxSearchSteps; if (_pathFindingEnableCustomRouteMatrix) { finder.OnCellCross = FindRoutePositionValidator; } else { finder.OnCellCross = null; } List <PathFinderNode> route = finder.FindPath(startingPoint, endingPoint, out totalCost); if (route != null) { routePoints = new List <Vector2> (route.Count); routePoints.Add(startPosition); for (int r = route.Count - 1; r >= 0; r--) { float x = (float)route [r].X / EARTH_ROUTE_SPACE_WIDTH - 0.5f; float y = (float)route [r].Y / EARTH_ROUTE_SPACE_HEIGHT - 0.5f; Vector2 stepPos = new Vector2(x, y); // due to grid effect the first step may be farther than the current position, so we skip it in that case. if (r == route.Count - 1 && (endPosition - startPosition).sqrMagnitude < (endPosition - stepPos).sqrMagnitude) { continue; } routePoints.Add(stepPos); } } else { return(null); // no route available } } // Add final step if it's appropiate bool hasWater = ContainsWater(endPosition); if (terrainCapability == TERRAIN_CAPABILITY.Any || (terrainCapability == TERRAIN_CAPABILITY.OnlyWater && hasWater) || (terrainCapability == TERRAIN_CAPABILITY.OnlyGround && !hasWater)) { if (routePoints == null) { routePoints = new List <Vector2> (); routePoints.Add(startPosition); routePoints.Add(endPosition); } else { routePoints [routePoints.Count - 1] = endPosition; } } // Check that ground units ends in a position where GetCountryIndex returns a valid index if (terrainCapability == TERRAIN_CAPABILITY.OnlyGround) { int rr = routePoints.Count - 1; Vector2 dd = routePoints [rr - 1] - routePoints [rr]; dd *= 0.1f; while (GetCountryIndex(routePoints [rr]) < 0) { routePoints [rr] += dd; } } return(routePoints); }
public static void UpdateDashedLine(MeshFilter meshFilter, List <Vector3> points, float thickness, bool worldSpace, ref Vector3[] meshPoints, ref int[] triPoints, ref Vector2[] uv) { int max = (points.Count / 2) * 2; if (max == 0) { return; } int numPoints = 8 * 3 * max / 2; if (numPoints > 65000) { return; } Mesh mesh = meshFilter.sharedMesh; bool reassignMesh = false; if (mesh == null || meshPoints == null || mesh.vertexCount != numPoints) { meshPoints = new Vector3[numPoints]; triPoints = new int[numPoints]; uv = new Vector2[numPoints]; reassignMesh = true; } int mp = 0; thickness *= 0.5f; float y0 = 0f; //Mathf.Sin (0.0f * Mathf.Deg2Rad); float x0 = 1f; //Mathf.Cos (0.0f * Mathf.Deg2Rad); float y1 = 0.8660254f; //Mathf.Sin (120.0f * Mathf.Deg2Rad); float x1 = -0.5f; //Mathf.Cos (120.0f * Mathf.Deg2Rad); float y2 = -0.8660254f; //Mathf.Sin (240.0f * Mathf.Deg2Rad); float x2 = -0.5f; //Mathf.Cos (240.0f * Mathf.Deg2Rad); Vector3 up = WMSK.instance.currentCamera.transform.forward; Vector3 axis = Misc.Vector3zero; float scaleX = worldSpace ? 1f : 0.5f; Vector3 tmp = Misc.Vector3zero; for (int p = 0; p < max; p += 2) { Vector3 p0 = points [p]; Vector3 p1 = points [p + 1]; FastVector.NormalizedDirection(ref p0, ref p1, ref tmp); // Front triangle Vector3 right = Vector3.Cross(up, tmp); // Vector3 axis = (up * y0 + right * x0).normalized; FastVector.CombineAndNormalize(ref up, y0, ref right, x0, ref axis); axis.x *= scaleX; meshPoints [mp + 0] = p0 + axis * thickness; // axis = (up * y2 + right * x2).normalized; FastVector.CombineAndNormalize(ref up, y2, ref right, x2, ref axis); axis.x *= scaleX; meshPoints [mp + 1] = p0 + axis * thickness; // axis = (up * y1 + right * x1).normalized; FastVector.CombineAndNormalize(ref up, y1, ref right, x1, ref axis); axis.x *= scaleX; meshPoints [mp + 2] = p0 + axis * thickness; triPoints [mp + 0] = mp + 0; triPoints [mp + 1] = mp + 1; triPoints [mp + 2] = mp + 2; uv [mp + 0] = Misc.Vector2zero; uv [mp + 1] = Misc.Vector2right; uv [mp + 2] = Misc.Vector2up; // Back triangle // axis = (up * y0 + right * x0).normalized; FastVector.CombineAndNormalize(ref up, y0, ref right, x0, ref axis); axis.x *= scaleX; meshPoints [mp + 3] = p1 + axis * thickness; // axis = (up * y1 + right * x1).normalized; FastVector.CombineAndNormalize(ref up, y1, ref right, x1, ref axis); axis.x *= scaleX; meshPoints [mp + 4] = p1 + axis * thickness; // axis = (up * y2 + right * x2).normalized; FastVector.CombineAndNormalize(ref up, y2, ref right, x2, ref axis); axis.x *= scaleX; meshPoints [mp + 5] = p1 + axis * thickness; triPoints [mp + 3] = mp + 3; triPoints [mp + 4] = mp + 4; triPoints [mp + 5] = mp + 5; uv [mp + 3] = Misc.Vector2zero; uv [mp + 4] = Misc.Vector2one; uv [mp + 5] = Misc.Vector2right; // One side meshPoints [mp + 6] = meshPoints [mp + 0]; triPoints [mp + 6] = mp + 6; uv [mp + 6] = Misc.Vector2up; meshPoints [mp + 7] = meshPoints [mp + 3]; triPoints [mp + 7] = mp + 7; uv [mp + 7] = Misc.Vector2one; meshPoints [mp + 8] = meshPoints [mp + 1]; triPoints [mp + 8] = mp + 8; uv [mp + 8] = Misc.Vector2zero; meshPoints [mp + 9] = meshPoints [mp + 1]; triPoints [mp + 9] = mp + 9; uv [mp + 9] = Misc.Vector2zero; meshPoints [mp + 10] = meshPoints [mp + 3]; triPoints [mp + 10] = mp + 10; uv [mp + 10] = Misc.Vector2one; meshPoints [mp + 11] = meshPoints [mp + 5]; triPoints [mp + 11] = mp + 11; uv [mp + 11] = Misc.Vector2zero; // Second side meshPoints [mp + 12] = meshPoints [mp + 1]; triPoints [mp + 12] = mp + 12; uv [mp + 12] = Misc.Vector2zero; meshPoints [mp + 13] = meshPoints [mp + 5]; triPoints [mp + 13] = mp + 13; uv [mp + 13] = Misc.Vector2right; meshPoints [mp + 14] = meshPoints [mp + 2]; triPoints [mp + 14] = mp + 14; uv [mp + 14] = Misc.Vector2up; meshPoints [mp + 15] = meshPoints [mp + 2]; triPoints [mp + 15] = mp + 15; uv [mp + 15] = Misc.Vector2up; meshPoints [mp + 16] = meshPoints [mp + 5]; triPoints [mp + 16] = mp + 16; uv [mp + 16] = Misc.Vector2right; meshPoints [mp + 17] = meshPoints [mp + 4]; triPoints [mp + 17] = mp + 17; uv [mp + 17] = Misc.Vector2up; // Third side meshPoints [mp + 18] = meshPoints [mp + 0]; triPoints [mp + 18] = mp + 18; uv [mp + 18] = Misc.Vector2right; meshPoints [mp + 19] = meshPoints [mp + 4]; triPoints [mp + 19] = mp + 19; uv [mp + 19] = Misc.Vector2up; meshPoints [mp + 20] = meshPoints [mp + 3]; triPoints [mp + 20] = mp + 20; uv [mp + 20] = Misc.Vector2zero; meshPoints [mp + 21] = meshPoints [mp + 0]; triPoints [mp + 21] = mp + 21; uv [mp + 21] = Misc.Vector2zero; meshPoints [mp + 22] = meshPoints [mp + 2]; triPoints [mp + 22] = mp + 22; uv [mp + 22] = Misc.Vector2one; meshPoints [mp + 23] = meshPoints [mp + 4]; triPoints [mp + 23] = mp + 23; uv [mp + 23] = Misc.Vector2up; mp += 24; } if (mesh == null) { mesh = new Mesh(); mesh.hideFlags = HideFlags.DontSave; } if (reassignMesh) { mesh.Clear(); } mesh.vertices = meshPoints; mesh.uv = uv; mesh.triangles = triPoints; mesh.RecalculateNormals(); mesh.RecalculateBounds(); if (reassignMesh) { meshFilter.sharedMesh = mesh; } }
void UpdateArrowCap(ref GameObject placeholder, ref GameObject obj, GameObject cap, bool flipDirection, Vector3 arrowBasePos, Vector3 arrowTipPos, Vector3 scale, float offset, Material capMaterial) { if (obj == null) { placeholder = new GameObject("CapPlaceholder"); placeholder.transform.SetParent(transform, false); if (!usesViewport) { placeholder.transform.localScale = new Vector3(1f / transform.lossyScale.x, 1f / transform.lossyScale.y, 1f); } obj = Instantiate <GameObject>(cap); capSpriteRenderer = obj.GetComponent <SpriteRenderer>(); if (capSpriteRenderer != null) { capSpriteRenderer.color = lineMaterial.color; capStartColor = capSpriteRenderer.color; } capMeshRenderer = obj.GetComponent <MeshRenderer>(); if (capMeshRenderer != null) { capMeshRenderer.sharedMaterial = capMaterial != null ? capMaterial : lineMaterial; capStartColor = capMeshRenderer.sharedMaterial.color; } obj.transform.SetParent(placeholder.transform); obj.SetActive(false); } // set position Vector3 pos = Misc.Vector3zero; if (!usesViewport) { arrowBasePos = map.transform.TransformPoint(arrowBasePos); arrowTipPos = map.transform.TransformPoint(arrowTipPos); } // Length of cap based on size if (arrowBasePos != arrowTipPos) { Vector3 dir = Misc.Vector3zero; FastVector.NormalizedDirection(ref arrowBasePos, ref arrowTipPos, ref dir); pos = arrowTipPos - dir * offset; if (!obj.activeSelf) { obj.SetActive(true); } obj.transform.position = pos; // look to camera if (usesViewport) { Vector3 camDir = pos - map.cameraMain.transform.position; obj.transform.LookAt(arrowTipPos + dir * 100f, camDir); } else { Vector3 prdir = Vector3.ProjectOnPlane(dir, map.transform.forward); obj.transform.LookAt(pos + map.transform.forward, prdir); obj.transform.Rotate(obj.transform.forward, 90, Space.Self); } if (flipDirection) { obj.transform.Rotate(180, 0, 0, Space.Self); } } obj.transform.localScale = scale; }