Пример #1
0
        bool GetCityUnderMouse(int countryIndex, Vector3 localPoint, out int cityIndex)
        {
            cityIndex = -1;
            if (visibleCities == null)
            {
                return(false);
            }
            float hitPrecision    = CITY_HIT_PRECISION * _cityIconSize * 5.0f;
            float hitPrecisionSqr = hitPrecision * hitPrecision;

            for (int c = 0; c < visibleCities.Length; c++)
            {
                City city = visibleCities [c];
                if (city.countryIndex == countryIndex && city.isShown)
                {
//																				if ((city.unitySphereLocation - localPoint).sqrMagnitude < hitPrecisionSqr) {
                    if (FastVector.SqrDistance(ref city.unitySphereLocation, ref localPoint) < hitPrecisionSqr)
                    {
                        cityIndex = GetCityIndex(city, false);
                        return(true);
                    }
                }
            }
            return(false);
        }
Пример #2
0
        /// <summary>
        /// Returns the nearest city to a point specified in sphere coordinates.
        /// </summary>
        /// <returns>The city near point.</returns>
        /// <param name="localPoint">Local point in sphere coordinates.</param>
        /// <param name="cityIndexToExclude">Optional city index which will be excluded. Useful for getting the nearest city to a given one.</param>
        public int GetCityIndex(Vector2 latlon, int cityIndexToExclude = -1)
        {
            if (visibleCities == null)
            {
                return(-1);
            }

            int   nearest   = -1;
            float minDist   = float.MaxValue;
            int   cityCount = cities.Count;

            for (int c = 0; c < cityCount; c++)
            {
                if (c == cityIndexToExclude)
                {
                    continue;
                }
                City city = cities [c];
                if (!city.isShown)
                {
                    continue;
                }
                Vector2 cityLoc = city.latlon;
                float   dist    = FastVector.SqrDistance(ref cityLoc, ref latlon);
                if (dist < minDist)
                {
                    minDist = dist;
                    nearest = c;
                }
            }
            return(nearest);
        }
Пример #3
0
        /// <summary>
        /// Returns any city near the point specified in sphere coordinates. Must be closer than CITY_HIT_PRECISION constant, usually when pointer clicks over a city icon.
        /// Optimized method for mouse hitting.
        /// </summary>
        /// <returns>The city near point.</returns>
        /// <param name="localPoint">Local point in sphere coordinates.</param>
        public int GetCityNearPointFast(Vector3 localPoint)
        {
            if (visibleCities == null)
            {
                return(-1);
            }
            float   hitPrecision    = CITY_HIT_PRECISION * _cityIconSize * 5.0f;
            float   hitPrecisionSqr = hitPrecision * hitPrecision;
            Vector2 latlon          = Conversion.GetLatLonFromSpherePoint(localPoint);

            for (int c = 0; c < countries.Length; c++)
            {
                Country country = countries [c];
                if (country.regionsRect2D.Contains(latlon))
                {
                    for (int t = 0; t < visibleCities.Length; t++)
                    {
                        City city = visibleCities [t];
                        if (city.countryIndex != c)
                        {
                            continue;
                        }
                        float dist = FastVector.SqrDistance(ref city.unitySphereLocation, ref localPoint);                          // (city.unitySphereLocation - localPoint).sqrMagnitude;
                        if (dist < hitPrecisionSqr)
                        {
                            return(GetCityIndex(city, false));
                        }
                    }
                }
            }
            return(-1);
        }
Пример #4
0
        bool GetProvinceUnderMouse(int countryIndex, Vector3 spherePoint, out int provinceIndex, out int regionIndex)
        {
            float startingDistance = 0;

            provinceIndex = regionIndex = -1;
            Country country = countries [countryIndex];

            if (country.provinces == null && _provinces == null)
            {
                ReadProvincesPackedString();
            }
            if (country.provinces == null)
            {
                return(false);
            }
            int provincesCount = country.provinces.Length;

            if (provincesCount == 0)
            {
                return(false);
            }

            Vector2 mousePos;

            Conversion.GetLatLonFromSpherePoint(spherePoint, out mousePos);
            float maxArea = float.MaxValue;

            // Is this the same province currently selected?
            if (_provinceHighlightedIndex >= 0 && _provinceRegionHighlightedIndex >= 0 && _provinceHighlighted.countryIndex == countryIndex && !_provinceHighlighted.hidden)
            {
                if (_provinceRegionHighlighted.Contains(mousePos))
                {
                    maxArea = _provinceHighlighted.mainRegionArea;
                    // cannot return yet - need to check if any other province (smaller than this) could be highlighted
                }
            }

            // Check other provinces
            for (int tries = 0; tries < 75; tries++)
            {
                float minDist = float.MaxValue;
                for (int p = 0; p < provincesCount; p++)
                {
                    Province province = country.provinces [p];
                    if (province.regions == null || province.mainRegionArea > maxArea || province.hidden)
                    {
                        continue;
                    }
                    for (int pr = 0; pr < province.regions.Count; pr++)
                    {
                        Vector3 regionCenter = province.regions [pr].sphereCenter;
                        float   dist         = FastVector.SqrDistance(ref regionCenter, ref spherePoint);                // (regionCenter - spherePoint).sqrMagnitude;
                        if (dist > startingDistance && dist < minDist)
                        {
                            minDist       = dist;
                            provinceIndex = GetProvinceIndex(province);
                            regionIndex   = pr;
                        }
                    }
                }

                // Check if this region is visible and the mouse is inside
                if (provinceIndex >= 0)
                {
                    Region region = provinces [provinceIndex].regions [regionIndex];
                    if (region.Contains(mousePos))
                    {
                        return(true);
                    }
                }

                // Continue searching but farther centers
                startingDistance = minDist;
            }
            return(false);
        }
Пример #5
0
        /// <summary>
        /// Used internally by the Map Editor. It will recalculate de boundaries and optimize frontiers based on new data of provinces array
        /// </summary>
        public void RefreshProvinceGeometry(int provinceIndex)
        {
            if (provinceIndex < 0 || provinceIndex >= provinces.Length)
            {
                return;
            }
            lastProvinceLookupCount = -1;
            float    maxVol   = 0;
            Province province = provinces [provinceIndex];

            if (province.regions == null)
            {
                ReadProvincePackedString(province);
            }
            int     regionCount = province.regions.Count;
            Vector2 minProvince = Misc.Vector2one * 1000;
            Vector2 maxProvince = -minProvince;

            for (int r = 0; r < regionCount; r++)
            {
                Region provinceRegion = province.regions [r];
                provinceRegion.entity      = province;                  // just in case one country has been deleted
                provinceRegion.regionIndex = r;                         // just in case a region has been deleted
                int     coorCount = provinceRegion.latlon.Length;
                Vector2 min       = Misc.Vector2one * 1000;
                Vector2 max       = -min;
                for (int c = 0; c < coorCount; c++)
                {
                    float x = provinceRegion.latlon [c].x;
                    float y = provinceRegion.latlon [c].y;
                    if (x < min.x)
                    {
                        min.x = x;
                    }
                    if (x > max.x)
                    {
                        max.x = x;
                    }
                    if (y < min.y)
                    {
                        min.y = y;
                    }
                    if (y > max.y)
                    {
                        max.y = y;
                    }
                }
                Vector3 normRegionCenter = (min + max) * 0.5f;
                provinceRegion.latlonCenter = normRegionCenter;

                if (min.x < minProvince.x)
                {
                    minProvince.x = min.x;
                }
                if (min.y < minProvince.y)
                {
                    minProvince.y = min.y;
                }
                if (max.x > maxProvince.x)
                {
                    maxProvince.x = max.x;
                }
                if (max.y > maxProvince.y)
                {
                    maxProvince.y = max.y;
                }
                provinceRegion.latlonRect2D = new Rect(min.x, min.y, Math.Abs(max.x - min.x), Mathf.Abs(max.y - min.y));
                provinceRegion.rect2DArea   = provinceRegion.latlonRect2D.width * provinceRegion.latlonRect2D.height;
                float vol = FastVector.SqrDistance(ref min, ref max);                  // (max - min).sqrMagnitude;
                if (vol > maxVol)
                {
                    maxVol = vol;
                    province.mainRegionIndex = r;
                    province.latlonCenter    = provinceRegion.latlonCenter;
                }
            }
            province.regionsRect2D = new Rect(minProvince.x, minProvince.y, Math.Abs(maxProvince.x - minProvince.x), Mathf.Abs(maxProvince.y - minProvince.y));
        }
Пример #6
0
        public void ReadProvincePackedString(Province province)
        {
            string[] regions     = province.packedRegions.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
            int      regionCount = regions.Length;

            province.regions = new List <Region> (regionCount);
            float   maxVol       = float.MinValue;
            Vector2 minProvince  = Misc.Vector2one * 1000;
            Vector2 maxProvince  = -minProvince;
            Vector2 min          = Misc.Vector2one * 1000;
            Vector2 max          = -min;
            Vector2 latlonCenter = new Vector2();

            for (int r = 0; r < regionCount; r++)
            {
                string[] coordinates = regions [r].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                int      coorCount   = coordinates.Length;
                min.x = min.y = 1000;
                max.x = max.y = -1000;
                Region    provinceRegion = new Region(province, province.regions.Count);
                Vector2[] latlon         = new Vector2[coorCount];
                for (int c = 0; c < coorCount; c++)
                {
                    float lat, lon;
                    GetPointFromPackedString(coordinates [c], out lat, out lon);
                    if (lat < min.x)
                    {
                        min.x = lat;
                    }
                    if (lat > max.x)
                    {
                        max.x = lat;
                    }
                    if (lon < min.y)
                    {
                        min.y = lon;
                    }
                    if (lon > max.y)
                    {
                        max.y = lon;
                    }
                    latlon [c] = new Vector2(lat, lon);
                }
                provinceRegion.latlon = latlon;
                FastVector.Average(ref min, ref max, ref latlonCenter);                  //  (min + max) * 0.5f;
                provinceRegion.latlonCenter = latlonCenter;

                province.regions.Add(provinceRegion);

                // Calculate province bounding rect
                if (min.x < minProvince.x)
                {
                    minProvince.x = min.x;
                }
                if (min.y < minProvince.y)
                {
                    minProvince.y = min.y;
                }
                if (max.x > maxProvince.x)
                {
                    maxProvince.x = max.x;
                }
                if (max.y > maxProvince.y)
                {
                    maxProvince.y = max.y;
                }
                provinceRegion.latlonRect2D = new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
                provinceRegion.rect2DArea   = provinceRegion.latlonRect2D.width * provinceRegion.latlonRect2D.height;
                float vol = FastVector.SqrDistance(ref min, ref max);                  // (max - min).sqrMagnitude;
                if (vol > maxVol)
                {
                    maxVol = vol;
                    province.mainRegionIndex = r;
                    province.latlonCenter    = provinceRegion.latlonCenter;
                }
            }
            province.regionsRect2D = new Rect(minProvince.x, minProvince.y, maxProvince.x - minProvince.x, maxProvince.y - minProvince.y);
        }
Пример #7
0
        void CheckTiles(TileInfo parent, int currentZoomLevel, int xTile, int yTile, int zoomLevel, int subquadIndex)
        {
            // Is this tile visible?
            TileInfo ti;
            int      tileCode = GetTileHashCode(xTile, yTile, zoomLevel);

            if (!cachedTiles.TryGetValue(tileCode, out ti))
            {
                ti        = new TileInfo(xTile, yTile, zoomLevel, subquadIndex, currentEarthTexture);
                ti.parent = parent;
                if (parent != null)
                {
                    if (parent.children == null)
                    {
                        parent.children = new List <TileInfo> ();
                    }
                    parent.children.Add(ti);
                }
                for (int k = 0; k < 4; k++)
                {
                    Vector2 latlon = Conversion.GetLatLonFromTile(xTile + offsets [k].x, yTile + offsets [k].y, zoomLevel);
                    ti.latlons [k] = latlon;
                    Vector3 spherePos = Conversion.GetSpherePointFromLatLon(latlon);
                    ti.spherePos [k] = spherePos;
                }
                cachedTiles [tileCode] = ti;
            }
            // Check if any tile corner is visible
            // Phase I
#if DEBUG_TILES
            if (ti.gameObject != null && ti.gameObject.GetComponent <TileInfoEx> ().debug)
            {
                Debug.Log("this");
            }
#endif

            bool    cornersOccluded = true;
            Vector3 minWorldPos     = Misc.Vector3Max;
            Vector3 maxWorldPos     = Misc.Vector3Min;
            Vector3 tmp             = Misc.Vector3zero;
            for (int c = 0; c < 4; c++)
            {
                Vector3 wpos = transform.TransformPoint(ti.spherePos [c]);
                ti.cornerWorldPos [c] = wpos;
                if (wpos.x < minWorldPos.x)
                {
                    minWorldPos.x = wpos.x;
                }
                if (wpos.y < minWorldPos.y)
                {
                    minWorldPos.y = wpos.y;
                }
                if (wpos.z < minWorldPos.z)
                {
                    minWorldPos.z = wpos.z;
                }
                if (wpos.x > maxWorldPos.x)
                {
                    maxWorldPos.x = wpos.x;
                }
                if (wpos.y > maxWorldPos.y)
                {
                    maxWorldPos.y = wpos.y;
                }
                if (wpos.z > maxWorldPos.z)
                {
                    maxWorldPos.z = wpos.z;
                }
                if (cornersOccluded)
                {
                    float radiusSqr = (wpos.x - globePos.x) * (wpos.x - globePos.x) + (wpos.y - globePos.y) * (wpos.y - globePos.y) + (wpos.z - globePos.z) * (wpos.z - globePos.z);                     //  Vector3.SqrMagnitude (wpos - globePos);
//																				Vector3 camDir = (currentCameraPosition - wpos).normalized;
                    FastVector.NormalizedDirection(ref wpos, ref currentCameraPosition, ref tmp);
//																				Vector3 st = wpos + ndir * (0.01f * transform.localScale.x);
                    Vector3 st = wpos;
                    FastVector.Add(ref st, ref tmp, localScaleFactor);
                    float mag = (st.x - globePos.x) * (st.x - globePos.x) + (st.y - globePos.y) * (st.y - globePos.y) + (st.z - globePos.z) * (st.z - globePos.z);
                    if (mag > radiusSqr)
                    {
                        cornersOccluded = false;
                    }
                }
            }

//												Bounds bounds = new Bounds ((minWorldPos + maxWorldPos) * 0.5f, maxWorldPos - minWorldPos);
            FastVector.Average(ref minWorldPos, ref maxWorldPos, ref tmp);
            Bounds  bounds       = new Bounds(tmp, maxWorldPos - minWorldPos);
            Vector3 tileMidPoint = bounds.center;
            // Check center of quad
            if (cornersOccluded)
            {
                float radiusSqr = (tileMidPoint.x - globePos.x) * (tileMidPoint.x - globePos.x) + (tileMidPoint.y - globePos.y) * (tileMidPoint.y - globePos.y) + (tileMidPoint.z - globePos.z) * (tileMidPoint.z - globePos.z);                 // Vector3.SqrMagnitude (tileMidPoint - globePos);
//																Vector3 camDir = (currentCameraPosition - tileMidPoint).normalized;
                FastVector.NormalizedDirection(ref tileMidPoint, ref currentCameraPosition, ref tmp);
//																Vector3 st = tileMidPoint + tmp * (0.01f * transform.localScale.x);
                Vector3 st = tileMidPoint;
                FastVector.Add(ref st, ref tmp, localScaleFactor);
                float mag = (st.x - globePos.x) * (st.x - globePos.x) + (st.y - globePos.y) * (st.y - globePos.y) + (st.z - globePos.z) * (st.z - globePos.z);
                if (mag > radiusSqr)
                {
                    cornersOccluded = false;
                }
            }

#if DEBUG_TILES
            if (root == null)
            {
                root = new GameObject();
                root.transform.SetParent(transform);
                root.transform.localPosition = Vector3.zero;
                root.transform.localRotation = Misc.QuaternionZero;                 //Quaternion.Euler (0, 0, 0);
            }
#endif

            bool  insideViewport = false;
            float minX = currentCamera.pixelWidth * 2f, minY = currentCamera.pixelHeight * 2f;
            float maxX = -minX, maxY = -minY;
            if (!cornersOccluded)
            {
                // Phase II
                for (int c = 0; c < 4; c++)
                {
                    Vector3 scrPos = currentCamera.WorldToScreenPoint(ti.cornerWorldPos [c]);
                    insideViewport = insideViewport || (scrPos.z > 0 && scrPos.x >= 0 && scrPos.x < currentCamera.pixelWidth && scrPos.y >= 0 && scrPos.y < currentCamera.pixelHeight);
                    if (scrPos.x < minX)
                    {
                        minX = scrPos.x;
                    }
                    if (scrPos.x > maxX)
                    {
                        maxX = scrPos.x;
                    }
                    if (scrPos.y < minY)
                    {
                        minY = scrPos.y;
                    }
                    if (scrPos.y > maxY)
                    {
                        maxY = scrPos.y;
                    }
                }
                if (!insideViewport)
                {
                    insideViewport = GeometryUtility.TestPlanesAABB(cameraPlanes, bounds);
                }
            }

            ti.insideViewport = insideViewport;
            ti.visible        = false;
            if (insideViewport)
            {
                if (!ti.created)
                {
                    CreateTile(ti);
                }

                if (!ti.gameObject.activeSelf)
                {
                    ti.gameObject.SetActive(true);
                }

                // Manage hierarchy of tiles
                bool tileIsBig = false;
                FastVector.NormalizedDirection(ref globePos, ref tileMidPoint, ref tmp);
//																float dd = Vector3.Dot (currentCameraForward, (tileMidPoint - globePos).normalized);
                float dd = Vector3.Dot(currentCameraForward, tmp);
                if (dd > -0.8f || currentZoomLevel > 9)                   // prevents big seams on initial zooms
                {
                    float aparentSize = Mathf.Max(maxX - minX, maxY - minY);
                    tileIsBig = aparentSize > currentTileSize;
                }
                else
                {
                    tileIsBig = ti.zoomLevel < currentZoomLevel;
                }

                                #if DEBUG_TILES
                if (ti.gameObject != null)
                {
                    ti.gameObject.GetComponent <TileInfoEx> ().bigTile   = tileIsBig;
                    ti.gameObject.GetComponent <TileInfoEx> ().zoomLevel = ti.zoomLevel;
                }
                                #endif

                if ((tileIsBig || zoomLevel < TILE_MIN_ZOOM_LEVEL) && zoomLevel < _tileMaxZoomLevel)
                {
                    // Load nested tiles
                    CheckTiles(ti, currentZoomLevel, xTile * 2, yTile * 2, zoomLevel + 1, 0);
                    CheckTiles(ti, currentZoomLevel, xTile * 2 + 1, yTile * 2, zoomLevel + 1, 1);
                    CheckTiles(ti, currentZoomLevel, xTile * 2, yTile * 2 + 1, zoomLevel + 1, 2);
                    CheckTiles(ti, currentZoomLevel, xTile * 2 + 1, yTile * 2 + 1, zoomLevel + 1, 3);
                    ti.renderer.enabled = false;
                }
                else
                {
                    ti.visible = true;

                    // Show tile renderer
                    if (!ti.renderer.enabled)
                    {
                        ti.renderer.enabled = true;
                    }

                    // If parent tile is loaded then use that as placeholder texture
                    if (ti.zoomLevel > TILE_MIN_ZOOM_LEVEL && ti.parent.loadStatus == TILE_LOAD_STATUS.Loaded && !ti.placeholderImageSet)
                    {
                        ti.placeholderImageSet = true;
                        ti.parentTextureCoords = placeHolderUV [ti.subquadIndex];
                        ti.SetPlaceholderImage(ti.parent.texture);
                    }

                    if (ti.loadStatus == TILE_LOAD_STATUS.Loaded)
                    {
                        if (!ti.hasAnimated)
                        {
                            ti.hasAnimated = true;
                            ti.Animate(1f, AnimationEnded);
                        }
                    }
                    else if (ti.loadStatus == TILE_LOAD_STATUS.Inactive)
                    {
                        ti.distToCamera = FastVector.SqrDistance(ref ti.cornerWorldPos [0], ref currentCameraPosition) * ti.zoomLevel;
                        ti.loadStatus   = TILE_LOAD_STATUS.InQueue;
                        ti.queueTime    = Time.time;
                        loadQueue.Add(ti);
                    }
                    if (ti.children != null)
                    {
                        for (int k = 0; k < 4; k++)
                        {
                            TileInfo tiChild = ti.children [k];
                            HideTile(tiChild);
                        }
                    }
                }
            }
            else
            {
                HideTile(ti);
            }
        }