Example #1
0
        /// <summary>
        /// Returns terrain names of terrains that intersect with the given bounds object
        /// </summary>
        /// <param name="bounds">A bounds object to check against the terrains. Needs to be in absolute world space position, mind the current origin offset!</param>
        /// <returns></returns>
        public static string[] GetTerrainsIntersectingBounds(BoundsDouble bounds)
        {
            //Reduce the bounds size a bit to prevent selecting terrains that are perfectly aligned with the bounds border
            //-this leads to too many terrains being logged as affected by an operation otherwise.
            Bounds intersectingBounds = new BoundsDouble();

            intersectingBounds.center = bounds.center;
            intersectingBounds.size   = bounds.size - new Vector3Double(0.001f, 0.001f, 0.001f);

            if (GaiaUtils.HasDynamicLoadedTerrains())
            {
                GaiaSessionManager sessionManager = GaiaSessionManager.GetSessionManager();
                if (sessionManager == null)
                {
                    Debug.LogError("Trying to get terrains that intersect with bounds, but there is no session manager in scene.");
                    return(null);
                }
                return(TerrainLoaderManager.TerrainScenes.Where(x => x.m_bounds.Intersects(intersectingBounds)).Select(x => x.GetTerrainName()).ToArray());
            }
            else
            {
                List <string> affectedTerrainNames = new List <string>();
                foreach (Terrain t in Terrain.activeTerrains)
                {
                    if (intersectingBounds.Intersects(TerrainHelper.GetWorldSpaceBounds(t)))
                    {
                        affectedTerrainNames.Add(t.name);
                    }
                }
                return(affectedTerrainNames.ToArray());
            }
        }
Example #2
0
        public static Vector3 GetWorldCenter(bool sampleHeight = false)
        {
            BoundsDouble bounds = new BoundsDouble();

            GetTerrainBounds(ref bounds);

            if (sampleHeight)
            {
                Terrain t = GetTerrain(bounds.center);
                if (t != null)
                {
                    Vector3 centerOnTerrain = t.transform.position + new Vector3(t.terrainData.size.x / 2f, 0f, t.terrainData.size.z / 2f);
                    float   height          = t.SampleHeight(centerOnTerrain);
                    return(new Vector3(centerOnTerrain.x, height, centerOnTerrain.z));
                }
                else
                {
                    //No terrain? The user might be using mesh terrains then. Send out a raycast at the center to determine height
                    RaycastHit raycastHit = new RaycastHit();
                    if (Physics.Raycast(new Vector3Double(bounds.center.x, 1000000f, bounds.center.z), Vector3.down, out raycastHit))
                    {
                        return(raycastHit.point);
                    }
                    else
                    {
                        return(bounds.center);
                    }
                }
            }
            else
            {
                return(new Vector3((float)bounds.center.x, (float)bounds.center.y, (float)bounds.center.z));
            }
        }
Example #3
0
        public void OnWorldMapCreate()
        {
            m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain();
            GaiaSettings gaiaSettings    = GaiaUtils.GetGaiaSettings();
            GaiaDefaults currentDefaults = gaiaSettings.m_currentDefaults;

            TerrainLoaderManager.Instance.TerrainSceneStorage.m_hasWorldMap = true;

            float worldheightmapRes = m_worldMapTerrain.terrainData.heightmapResolution / m_worldMapTerrain.terrainData.size.x;

            BoundsDouble bounds = new BoundsDouble();

            TerrainHelper.GetTerrainBounds(ref bounds);
            if (bounds.size.x > 0)
            {
                TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize            = (float)m_currentWorldCreationSettings.m_tileSize / (float)bounds.size.x;
                TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMapRelativeHeightmapPixels = (((float)bounds.size.x / m_localTileSize) * m_localHeightmapRes / m_localHeightmapRes);
            }
            else
            {
                //no bounds size means no real terrains (yet) - set these parameters according to the current settings/defaults then
                TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize            = (float)m_currentWorldCreationSettings.m_tileSize / (gaiaSettings.m_tilesX * currentDefaults.m_terrainSize);
                TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMapRelativeHeightmapPixels = ((gaiaSettings.m_tilesX * currentDefaults.m_terrainSize) / currentDefaults.m_terrainSize) * currentDefaults.m_heightmapResolution / currentDefaults.m_heightmapResolution;
            }
            SyncLocalMapToWorldMap();
            ShowWorldMapStampSpawner();
            GaiaSessionManager.OnWorldCreated -= OnWorldMapCreate;
        }
Example #4
0
        private void CopyLocalMapToWorldMap(BoundsDouble bounds, Terrain t)
        {
            RenderTextureDescriptor rtDesc = t.terrainData.heightmapTexture.descriptor;

            rtDesc.width  = Mathf.CeilToInt(m_worldMapTerrain.terrainData.heightmapResolution / ((float)bounds.size.x / t.terrainData.bounds.size.x));
            rtDesc.height = rtDesc.width;

            RenderTexture chunkContent = RenderTexture.GetTemporary(rtDesc);
            float         res          = t.terrainData.heightmapResolution / rtDesc.width;

            Bounds worldSpaceBounds = t.terrainData.bounds;

            worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + t.transform.position.x, worldSpaceBounds.center.y + t.transform.position.y, worldSpaceBounds.center.z + t.transform.position.z);
            Vector2 pos = new Vector2(Mathf.InverseLerp(0, (float)bounds.size.x, Mathf.Abs((float)bounds.min.x - worldSpaceBounds.min.x)), Mathf.InverseLerp(0, (float)bounds.size.z, Mathf.Abs((float)bounds.min.z - worldSpaceBounds.min.z)));

            Graphics.Blit(t.terrainData.heightmapTexture, chunkContent, new Vector2(1, 1), new Vector2(0, 0));

            RenderTexture previousRT = RenderTexture.active;

            RenderTexture.active = chunkContent;
            m_worldMapTerrain.terrainData.CopyActiveRenderTextureToHeightmap(new RectInt(0, 0, rtDesc.width, rtDesc.height), new Vector2Int(Mathf.FloorToInt(pos.x * m_worldMapTerrain.terrainData.heightmapResolution), Mathf.FloorToInt(pos.y * m_worldMapTerrain.terrainData.heightmapResolution)), t.drawInstanced ? TerrainHeightmapSyncControl.None : TerrainHeightmapSyncControl.HeightOnly);
            RenderTexture.active = previousRT;
            m_worldMapTerrain.terrainData.SyncHeightmap();
            m_worldMapTerrain.editorRenderFlags = TerrainRenderFlags.All;

            RenderTexture.ReleaseTemporary(chunkContent);
            chunkContent = null;
        }
Example #5
0
        void OnDrawGizmosSelected()
        {
#if UNITY_EDITOR
            if (Selection.activeObject == gameObject)
            {
                if (m_showBoundingBox)
                {
                    Gizmos.color = Color.red;
                    Gizmos.DrawWireCube(transform.position, new Vector3(m_settings.m_range * 2f, m_settings.m_range * 2f, m_settings.m_range * 2f));
                }

                //Water
                if (m_showSeaLevelPlane && PWS_WaterSystem.Instance == null)
                {
                    BoundsDouble bounds = new BoundsDouble();
                    if (TerrainHelper.GetTerrainBounds(ref bounds) == true)
                    {
                        bounds.center = new Vector3Double(bounds.center.x, SessionManager.GetSeaLevel(), bounds.center.z);
                        bounds.size   = new Vector3Double(bounds.size.x, 0.05f, bounds.size.z);
                        Gizmos.color  = new Color(Color.blue.r, Color.blue.g, Color.blue.b, Color.blue.a / 4f);
                        Gizmos.DrawCube(bounds.center, bounds.size);
                    }
                }
            }
#endif
        }
Example #6
0
        private void CopyWorldMapToLocalMap(BoundsDouble bounds, Terrain t)
        {
            //make sure we have a world map terrain first
            if (m_worldMapTerrain == null)
            {
                m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain();
            }

            if (m_worldMapTerrain == null)
            {
                Debug.LogError("Can't export world map to local terrains - world map terrain is missing!");
                return;
            }

            RenderTexture chunkContent = RenderTexture.GetTemporary(t.terrainData.heightmapTexture.descriptor);
            //FilterMode oldFilterMode = m_worldMapTerrain.terrainData.heightmapTexture.filterMode;
            //m_worldMapTerrain.terrainData.heightmapTexture.filterMode = FilterMode.Trilinear;
            //t.terrainData.heightmapTexture.filterMode = FilterMode.Trilinear;
            //chunkContent.filterMode = FilterMode.Trilinear;
            int   maxTilesX    = Mathf.RoundToInt((float)bounds.size.x / t.terrainData.size.x);
            int   maxTilesZ    = Mathf.RoundToInt((float)bounds.size.z / t.terrainData.size.z);
            int   currentTileX = Mathf.RoundToInt((t.transform.position.x - (float)bounds.min.x) / t.terrainData.size.x);
            int   currentTileZ = Mathf.RoundToInt((t.transform.position.z - (float)bounds.min.z) / t.terrainData.size.z);
            float res          = (t.terrainData.heightmapResolution) / ((float)bounds.size.x / t.terrainData.bounds.size.x * (t.terrainData.heightmapResolution - 1));


            Bounds worldSpaceBounds = t.terrainData.bounds;

            worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + t.transform.position.x, worldSpaceBounds.center.y + t.transform.position.y, worldSpaceBounds.center.z + t.transform.position.z);
            float   xPos = ((float)currentTileX * t.terrainData.heightmapResolution) / (maxTilesX * t.terrainData.heightmapResolution);
            float   zPos = ((float)currentTileZ * t.terrainData.heightmapResolution) / (maxTilesZ * t.terrainData.heightmapResolution);
            Vector2 pos  = new Vector2(xPos, zPos);



            Graphics.Blit(m_worldMapTerrain.terrainData.heightmapTexture, chunkContent, new Vector2(res, res), pos);
            //m_worldMapTerrain.terrainData.heightmapTexture.filterMode = oldFilterMode;
            RenderTexture previousRT = RenderTexture.active;

            RenderTexture.active = chunkContent;
            t.terrainData.CopyActiveRenderTextureToHeightmap(new RectInt(0, 0, t.terrainData.heightmapResolution, t.terrainData.heightmapResolution), new Vector2Int(0, 0), t.drawInstanced ? TerrainHeightmapSyncControl.None : TerrainHeightmapSyncControl.HeightOnly);
            RenderTexture.active = previousRT;
            t.terrainData.SyncHeightmap();
            t.editorRenderFlags = TerrainRenderFlags.All;

            RenderTexture.ReleaseTemporary(chunkContent);
            chunkContent = null;
        }
Example #7
0
        private Vector3 GetLocalStamperPosition()
        {
            BoundsDouble b = new BoundsDouble();

            TerrainHelper.GetTerrainBounds(ref b);
            Transform worldmapTransform = transform.parent.parent;
            Terrain   worldMapTerrain   = worldmapTransform.GetComponent <Terrain>();
            float     relativeX         = (transform.position.x - worldmapTransform.position.x) / worldMapTerrain.terrainData.size.x;
            float     relativeZ         = (transform.position.z - worldmapTransform.position.z) / worldMapTerrain.terrainData.size.z;
            float     relativeY         = transform.position.y / TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize;

            //TODO: Check if double precision required
            float newX = (float)b.min.x + (float)b.size.x * relativeX;
            float newZ = (float)b.min.z + (float)b.size.z * relativeZ;

            return(new Vector3(newX, relativeY, newZ));
        }
Example #8
0
        public void SetLoadingRange(Double regularLoadingRange, Double impostorLoadingRange)
        {
#if UNITY_EDITOR
            if (regularLoadingRange > 0 || impostorLoadingRange > 0)
            {
                Vector3Double targetLoadingExtentsRegular  = new Vector3Double(regularLoadingRange, regularLoadingRange, regularLoadingRange);
                Vector3Double targetLoadingExtentsImpostor = new Vector3Double(impostorLoadingRange, impostorLoadingRange, impostorLoadingRange);

                BoundsDouble loadingBounds = m_sceneViewOriginLoadingBounds;
                if (m_centerSceneViewLoadingOn == CenterSceneViewLoadingOn.SceneViewCamera)
                {
                    var allCameras = SceneView.GetAllSceneCameras();
                    if (allCameras.Length > 0)
                    {
                        if (m_sceneViewCameraLoadingBounds.center.Equals((Vector3Double)allCameras[0].transform.position) && m_sceneViewCameraLoadingBounds.extents.Equals(targetLoadingExtentsRegular) && m_sceneViewImpostorLoadingBounds.extents.Equals(targetLoadingExtentsImpostor))
                        {
                            //this exact setup is what is already currently loaded, skip the rest of processing
                            return;
                        }

                        m_sceneViewCameraLoadingBounds.center = (Vector3Double)allCameras[0].transform.position;
                    }
                    loadingBounds = m_sceneViewCameraLoadingBounds;
                }
                loadingBounds.extents = targetLoadingExtentsRegular;
                m_sceneViewOriginLoadingBounds.extents   = loadingBounds.extents;
                m_sceneViewImpostorLoadingBounds.center  = loadingBounds.center;
                m_sceneViewImpostorLoadingBounds.extents = targetLoadingExtentsImpostor;

                EditorUtility.SetDirty(this);
                UpdateTerrainLoadState(loadingBounds, m_sceneViewImpostorLoadingBounds, gameObject);
            }
            else
            {
                m_sceneViewOriginLoadingBounds.extents   = Vector3.zero;
                m_sceneViewImpostorLoadingBounds.extents = Vector3.zero;
                foreach (TerrainScene ts in m_terrainSceneStorage.m_terrainScenes)
                {
                    ts.RemoveRegularReference(gameObject);
                    ts.RemoveImpostorReference(gameObject);
                }
            }
#endif
        }
Example #9
0
        public void SyncLocalMapToWorldMap()
        {
            BoundsDouble bounds = new BoundsDouble();

            TerrainHelper.GetTerrainBounds(ref bounds);
            if (GaiaUtils.HasDynamicLoadedTerrains())
            {
                Action <Terrain> act = (t) => CopyLocalMapToWorldMap(bounds, t);
                GaiaUtils.CallFunctionOnDynamicLoadedTerrains(act, false);
            }
            else
            {
                foreach (Terrain t in Terrain.activeTerrains)
                {
                    if (t != m_worldMapTerrain)
                    {
                        CopyLocalMapToWorldMap(bounds, t);
                    }
                }
            }
        }
Example #10
0
        public void SyncLocationFromStamperSettings()
        {
            BoundsDouble b = new BoundsDouble();

            TerrainHelper.GetTerrainBounds(ref b);
            Transform worldmapTransform = transform.parent.parent;
            Terrain   worldMapTerrain   = worldmapTransform.GetComponent <Terrain>();
            //TODO: review if this needs to be in double precision

            Vector3Double origin = TerrainLoaderManager.Instance.GetOrigin();

            float relativeX = (float)(m_connectedStamperSettings.m_x - b.min.x + origin.x / TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize) / (float)b.size.x;
            float relativeY = (float)m_connectedStamperSettings.m_y * TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize;
            float relativeZ = (float)(m_connectedStamperSettings.m_z - b.min.z + origin.z / TerrainLoaderManager.Instance.TerrainSceneStorage.m_worldMaprelativeSize) / (float)b.size.z;

            //float relativeX = (float)(m_connectedStamperSettings.m_x - b.min.x) / (float)b.size.x;
            //float relativeY = (float) m_connectedStamperSettings.m_y * SessionManager.m_session.m_worldMaprelativeSize;
            //float relativeZ = (float)(m_connectedStamperSettings.m_z - b.min.z) / (float)b.size.z;

            float newX = worldmapTransform.position.x + worldMapTerrain.terrainData.size.x * relativeX;
            float newZ = worldmapTransform.position.z + worldMapTerrain.terrainData.size.z * relativeZ;

            transform.position = new Vector3(newX, relativeY, newZ);
        }
Example #11
0
        /// <summary>
        /// Syncs the heightmap of the world map to the local terrain tiles, preserving correct height scale, heightmap resolution, etc.
        /// </summary>
        /// <param name="validLocalTerrainNames">A list of local terrain tile names that are valid to change for the sync operation. If the list is null, all tiles will be assumed valid.</param>
        public void SyncWorldMapToLocalMap(List <string> validLocalTerrainNames = null)
        {
            BoundsDouble bounds = new BoundsDouble();

            TerrainHelper.GetTerrainBounds(ref bounds);
            if (GaiaUtils.HasDynamicLoadedTerrains())
            {
                Action <Terrain> act = (t) => CopyWorldMapToLocalMap(bounds, t);
                GaiaUtils.CallFunctionOnDynamicLoadedTerrains(act, false, validLocalTerrainNames);
            }
            else
            {
                foreach (Terrain t in Terrain.activeTerrains)
                {
                    if (t != m_worldMapTerrain)
                    {
                        if (validLocalTerrainNames == null || validLocalTerrainNames.Contains(t.name))
                        {
                            CopyWorldMapToLocalMap(bounds, t);
                        }
                    }
                }
            }
        }
Example #12
0
        public RenderTexture BakeTerrainWorldBiomeMask(Terrain terrain, string worldBiomeMaskGUID)
        {
            if (m_gaiaSessionManager == null)
            {
                m_gaiaSessionManager = GaiaSessionManager.GetSessionManager(false);
            }
            if (m_worldMapTerrain == null)
            {
                m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain();
            }
            if (m_worldMapTerrain == null)
            {
                Debug.LogWarning("Found no world map terrain for baking a world biome mask.");
                return(null);
            }
            if (String.IsNullOrEmpty(worldBiomeMaskGUID))
            {
                return(null);
            }

            if (m_gaiaSessionManager.m_session == null)
            {
                Debug.LogWarning("Found no session for baking a world biome mask.");
                return(null);
            }

            if (m_gaiaSessionManager.m_session.m_worldBiomeMaskSettings == null)
            {
                Debug.LogWarning("Found no world designer settings in the session for baking a world biome mask.");
                return(null);
            }

            //we need to apply the mask stack for this biome mask on the world map to get the result, then copy the appropiate rectangle for the queried terrain into the cache & return it.
            bool worldMapActiveState = m_worldMapTerrain.gameObject.activeInHierarchy;

            m_worldMapTerrain.gameObject.SetActive(true);
            GameObject emptyGO = new GameObject();

            emptyGO.transform.position = new Vector3(m_worldMapTerrain.transform.position.x + m_worldMapTerrain.terrainData.size.x / 2f, m_worldMapTerrain.transform.position.y, m_worldMapTerrain.transform.position.z + +m_worldMapTerrain.terrainData.size.z / 2f);
            GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(m_worldMapTerrain, emptyGO.transform, m_worldMapTerrain.terrainData.size.x);

            operation.m_isWorldMapOperation = true;
            operation.GetHeightmap();
            operation.GetNormalmap();
            operation.CollectTerrainBakedMasks();
            RenderTextureDescriptor rtDescriptor = operation.RTbakedMask.descriptor;

            RenderTexture inputTexture = RenderTexture.GetTemporary(rtDescriptor);

            RenderTexture currentRT = RenderTexture.active;

            RenderTexture.active = inputTexture;
            GL.Clear(true, true, Color.white);
            RenderTexture.active = currentRT;
            RenderTexture ruleOutputTexture = RenderTexture.GetTemporary(rtDescriptor);

            ImageMask[] maskStack = m_gaiaSessionManager.m_session.m_worldBiomeMaskSettings.m_spawnerRules.Find(x => x.GUID == worldBiomeMaskGUID).m_imageMasks;

            //Calculate Target position &/ resolution
            BoundsDouble bounds = new BoundsDouble();

            TerrainHelper.GetTerrainBounds(ref bounds);
            bounds.center -= TerrainLoaderManager.Instance.GetOrigin();
            RenderTexture chunkContent = new RenderTexture(terrain.terrainData.heightmapTexture.descriptor);
            int           maxTilesX    = Mathf.RoundToInt((float)bounds.size.x / terrain.terrainData.size.x);
            int           maxTilesZ    = Mathf.RoundToInt((float)bounds.size.z / terrain.terrainData.size.z);
            int           currentTileX = Mathf.RoundToInt((terrain.transform.position.x - (float)bounds.min.x) / terrain.terrainData.size.x);
            int           currentTileZ = Mathf.RoundToInt((terrain.transform.position.z - (float)bounds.min.z) / terrain.terrainData.size.z);
            float         res          = (terrain.terrainData.heightmapResolution) / ((float)bounds.size.x / terrain.terrainData.bounds.size.x * (terrain.terrainData.heightmapResolution - 1));


            Bounds worldSpaceBounds = terrain.terrainData.bounds;

            worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + terrain.transform.position.x, worldSpaceBounds.center.y + terrain.transform.position.y, worldSpaceBounds.center.z + terrain.transform.position.z);
            float   xPos = ((float)currentTileX * terrain.terrainData.heightmapResolution) / (maxTilesX * terrain.terrainData.heightmapResolution);
            float   zPos = ((float)currentTileZ * terrain.terrainData.heightmapResolution) / (maxTilesZ * terrain.terrainData.heightmapResolution);
            Vector2 pos  = new Vector2(xPos, zPos);

            //If we have a mask stack, we need to process it
            if (maskStack != null && maskStack.Length > 0)
            {
                //We start from a white texture, so we need the first mask action in the stack to always be "Multiply", otherwise there will be no result.
                maskStack[0].m_blendMode = ImageMaskBlendMode.Multiply;

                float maxWorldHeight = 0f;
                float minWorldHeight = 0f;
                m_gaiaSessionManager.GetWorldMinMax(ref minWorldHeight, ref maxWorldHeight, true);

                //Iterate through all image masks and set up the current paint context in case the shader uses heightmap data
                foreach (ImageMask mask in maskStack)
                {
                    mask.m_multiTerrainOperation = operation;
                    mask.m_seaLevel       = m_gaiaSessionManager.GetSeaLevel(true);
                    mask.m_maxWorldHeight = maxWorldHeight;
                    mask.m_minWorldHeight = minWorldHeight;
                }

                Graphics.Blit(ImageProcessing.ApplyMaskStack(inputTexture, ruleOutputTexture, maskStack, ImageMaskInfluence.Local), ruleOutputTexture);
            }
            else
            {
                //no mask stack -> just blit the white input texture over as the output
                Graphics.Blit(inputTexture, ruleOutputTexture);
            }
            operation.CloseOperation();
            DestroyImmediate(emptyGO);
            RenderTexture.ReleaseTemporary(inputTexture);
            m_worldMapTerrain.gameObject.SetActive(worldMapActiveState);

            //copy the rule output into the right size for the requested terrain chunk
            Graphics.Blit(ruleOutputTexture, chunkContent, new Vector2(res, res), pos);

            string filename = GetWorldBiomeMaskFilename(terrain, worldBiomeMaskGUID);

            SaveBakedMaskInCache(chunkContent, terrain, filename);

            RenderTexture.ReleaseTemporary(ruleOutputTexture);

            return(chunkContent);
        }
Example #13
0
        /// <summary>
        /// Get the bounds of the terrain at this location or fail with a null
        /// </summary>
        /// <param name="locationWU">Location to check and get terrain for</param>
        /// <returns>Bounds of selected terrain or null if invalid for some reason</returns>
        public static bool GetTerrainBounds(ref BoundsDouble bounds, bool activeTerrainsOnly = false)
        {
            //Terrain terrain = GetTerrain(locationWU);
            //if (terrain == null)
            //{
            //    return false;
            //}
            //bounds.center = terrain.transform.position;
            //bounds.size = terrain.terrainData.size;
            //bounds.center += bounds.extents;

            Vector3Double accumulatedCenter = new Vector3Double();

            //Do we use dynamic loaded terrains in the scene?
            if (GaiaUtils.HasDynamicLoadedTerrains() && !activeTerrainsOnly)
            {
#if GAIA_PRO_PRESENT
                //we do have dynamic terrains -> calculate the bounds according to the terrain scene data in the session
                GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(false);

                foreach (TerrainScene t in TerrainLoaderManager.TerrainScenes)
                {
                    accumulatedCenter += t.m_bounds.center;
                }

                bounds.center = accumulatedCenter / TerrainLoaderManager.TerrainScenes.Count;

                foreach (TerrainScene t in TerrainLoaderManager.TerrainScenes)
                {
                    bounds.Encapsulate(t.m_bounds);
                }
#endif
            }
            else
            {
                //no placeholder -> calculate bounds according to the active terrains in the scene
                if (Terrain.activeTerrains.Length > 0)
                {
                    foreach (Terrain t in Terrain.activeTerrains)
                    {
                        if (!TerrainHelper.IsWorldMapTerrain(t))
                        {
                            if (t.terrainData != null)
                            {
                                accumulatedCenter += new Vector3Double(t.transform.position) + new Vector3Double(t.terrainData.bounds.extents);
                            }
                            else
                            {
                                Debug.LogWarning("Terrain " + t.name + " in the scene is missing the terrain data object!");
                            }
                        }
                    }
                    bounds.center = accumulatedCenter / Terrain.activeTerrains.Length;

                    foreach (Terrain t in Terrain.activeTerrains)
                    {
                        if (!TerrainHelper.IsWorldMapTerrain(t))
                        {
                            if (t.terrainData != null)
                            {
                                Bounds newBounds = new Bounds();
                                newBounds.center  = t.transform.position;
                                newBounds.size    = t.terrainData.size;
                                newBounds.center += t.terrainData.bounds.extents;
                                bounds.Encapsulate(newBounds);
                            }
                        }
                    }
                }
                else
                {
                    bounds = new BoundsDouble(Vector3Double.zero, Vector3Double.zero);
                    //No active terrains? There might be mesh terrains we can use then
                    GameObject meshTerrainExportObject = GaiaUtils.GetTerrainExportObject(false);
                    if (meshTerrainExportObject != null)
                    {
                        foreach (Transform t in meshTerrainExportObject.transform)
                        {
                            MeshRenderer mr = t.GetComponent <MeshRenderer>();
                            if (mr != null)
                            {
                                bounds.Encapsulate(mr.bounds);
                            }
                        }
                    }
                }
            }


            return(true);
        }
Example #14
0
        /// <summary>
        /// Load and unload the terrain scenes stored in the current session for a certain object
        /// </summary>
        public void UpdateTerrainLoadState(BoundsDouble loadingBoundsRegular = null, BoundsDouble loadingBoundsImpostor = null, GameObject requestingObject = null, float minDistance = 0, float maxDistance = 0, float minThresholdMS = 0, float maxThresholdMS = 0)
        {
            //Do not accept changes to load state during runtime when there was no runtime init yet
            if (Application.isPlaying && !m_runtimeInitialized)
            {
                return;
            }

            //Do not perform any updates when terrain loading is disabled per default
#if GAIA_PRO_PRESENT
            if (TerrainLoaderManager.Instance.m_terrainSceneStorage == null || !TerrainLoaderManager.Instance.m_terrainSceneStorage.m_terrainLoadingEnabled)
            {
                return;
            }
#endif


            if (requestingObject == null)
            {
                requestingObject = gameObject;
            }

            long currentTimeStamp = GaiaUtils.GetUnixTimestamp();

            m_terrainSceneActionQueue.Clear();

            foreach (TerrainScene terrainScene in TerrainLoaderManager.TerrainScenes)
            {
                if (terrainScene.m_nextUpdateTimestamp > currentTimeStamp)
                {
                    continue;
                }
                float distance = Vector3.Distance(terrainScene.m_bounds.center - terrainScene.m_currentOriginOffset, requestingObject.transform.position);
                terrainScene.m_currentOriginOffset = m_sceneViewOriginLoadingBounds.center;
                bool wasChanged = false;
                //only evaluate load state if local terrain is supposed to be displayed
                if (m_showLocalTerrain)
                {
                    if (loadingBoundsImpostor != null && loadingBoundsImpostor.extents.magnitude > 0 && loadingBoundsImpostor.extents.magnitude > loadingBoundsRegular.extents.magnitude)
                    {
                        if (terrainScene.m_bounds.Intersects(loadingBoundsImpostor) && !TerrainSceneStorage.m_colliderOnlyLoading)
                        {
                            if (!terrainScene.HasImpostorReference(requestingObject) || terrainScene.m_impostorLoadState == LoadState.Unloaded)
                            {
                                //terrainScene.AddImpostorReference(requestingObject);
                                AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.AddImpostorReference, distance);
                                terrainScene.m_useFloatingPointFix = m_terrainSceneStorage.m_useFloatingPointFix;
                                wasChanged = true;
                            }
                        }
                        else
                        {
                            if (terrainScene.HasImpostorReference(requestingObject) || terrainScene.m_impostorLoadState == LoadState.Loaded)
                            {
                                //terrainScene.RemoveImpostorReference(requestingObject, m_cacheMemoryThreshold);
                                AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.RemoveImpostorReference, distance);
                                wasChanged = true;
                            }
                            if (terrainScene.m_impostorLoadState == LoadState.Cached && (!CachingAllowed() || terrainScene.m_impostorCachedTimestamp + m_cacheKeepAliveTime < currentTimeStamp))
                            {
                                //terrainScene.RemoveImpostorReference(requestingObject, m_cacheMemoryThreshold, true);
                                AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.RemoveImpostorReference, distance, true);
                            }
                        }
                    }
                    else
                    {
                        if (terrainScene.HasImpostorReference(requestingObject))
                        {
                            //terrainScene.RemoveImpostorReference(requestingObject, m_cacheMemoryThreshold);
                            AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.RemoveImpostorReference, distance);
                            wasChanged = true;
                        }
                    }

                    if (loadingBoundsRegular != null && loadingBoundsRegular.extents.magnitude > 0)
                    {
                        if (terrainScene.m_bounds.Intersects(loadingBoundsRegular))
                        {
                            if (!terrainScene.HasRegularReference(requestingObject) || terrainScene.m_regularLoadState == LoadState.Unloaded)
                            {
                                //terrainScene.AddRegularReference(requestingObject);
                                AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.AddRegularReference, distance);
                                terrainScene.m_useFloatingPointFix = m_terrainSceneStorage.m_useFloatingPointFix;
                                wasChanged = true;
                            }
                        }
                        else
                        {
                            if (terrainScene.HasRegularReference(requestingObject) || terrainScene.m_regularLoadState == LoadState.Loaded)
                            {
                                //terrainScene.RemoveRegularReference(requestingObject, m_cacheMemoryThreshold);
                                AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.RemoveRegularReference, distance);
                                wasChanged = true;
                            }
                            if (terrainScene.m_regularLoadState == LoadState.Cached && (!CachingAllowed() || terrainScene.m_regularCachedTimestamp + m_cacheKeepAliveTime < currentTimeStamp))
                            {
                                //terrainScene.RemoveRegularReference(requestingObject, m_cacheMemoryThreshold, true);
                                AddToTerrainSceneActionQueue(terrainScene, ReferenceChange.RemoveRegularReference, distance, true);
                            }
                        }
                    }
                }
                terrainScene.ShiftLoadedTerrain();

                if (Application.isPlaying && !wasChanged)
                {
                    long threshold = +(long)Mathf.Lerp(minThresholdMS, maxThresholdMS, Mathf.InverseLerp(minDistance, maxDistance, Vector3.Distance(loadingBoundsRegular.center, terrainScene.m_bounds.center))) + UnityEngine.Random.Range(10, 50);
                    terrainScene.m_nextUpdateTimestamp = currentTimeStamp + threshold;
                }
                else
                {
                    terrainScene.m_nextUpdateTimestamp = 0;
                }
            }
            for (int i = 0; i < m_terrainSceneActionQueue.Count; i++)
            {
                switch (m_terrainSceneActionQueue[i].m_referenceChange)
                {
                case ReferenceChange.AddImpostorReference:
                    m_terrainSceneActionQueue[i].m_terrainScene.AddImpostorReference(requestingObject);
                    break;

                case ReferenceChange.AddRegularReference:
                    m_terrainSceneActionQueue[i].m_terrainScene.AddRegularReference(requestingObject);
                    break;

                case ReferenceChange.RemoveImpostorReference:
                    m_terrainSceneActionQueue[i].m_terrainScene.RemoveImpostorReference(requestingObject, m_cacheMemoryThreshold, m_terrainSceneActionQueue[i].m_forced);
                    break;

                case ReferenceChange.RemoveRegularReference:
                    m_terrainSceneActionQueue[i].m_terrainScene.RemoveRegularReference(requestingObject, m_cacheMemoryThreshold, m_terrainSceneActionQueue[i].m_forced);
                    break;
                }
            }
        }
Example #15
0
        public void LoadStorageData()
        {
#if UNITY_EDITOR
            //Try to get the terrain scene storage file from the last used GUID first
            if (!String.IsNullOrEmpty(m_lastUsedGUID))
            {
                m_terrainSceneStorage = (TerrainSceneStorage)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(m_lastUsedGUID), typeof(TerrainSceneStorage));
            }

            //No guid / storage object? Then we need to create one in the current session directory
            if (m_terrainSceneStorage == null)
            {
                GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager();
                if (gsm != null && gsm.m_session != null)
                {
                    string path = GaiaDirectories.GetScenePath(gsm.m_session) + "/TerrainScenes.asset";
                    if (File.Exists(path))
                    {
                        m_terrainSceneStorage = (TerrainSceneStorage)AssetDatabase.LoadAssetAtPath(path, typeof(TerrainSceneStorage));
                    }
                    else
                    {
                        m_terrainSceneStorage = ScriptableObject.CreateInstance <TerrainSceneStorage>();
                        if (TerrainHelper.GetWorldMapTerrain() != null)
                        {
                            m_terrainSceneStorage.m_hasWorldMap = true;
                        }
                        AssetDatabase.CreateAsset(m_terrainSceneStorage, path);
                        AssetDatabase.ImportAsset(path);
                    }
                }
                else
                {
                    m_terrainSceneStorage = ScriptableObject.CreateInstance <TerrainSceneStorage>();
                }
            }

            //Check if there are scene files existing already and if they are in the storage data - if not, we should pick them up accordingly
            string directory = GaiaDirectories.GetTerrainScenePathForStorageFile(m_terrainSceneStorage);
            var    dirInfo   = new DirectoryInfo(directory);

            bool madeChanges = false;

            if (dirInfo != null)
            {
                FileInfo[] allFiles = dirInfo.GetFiles();
                foreach (FileInfo fileInfo in allFiles)
                {
                    if (fileInfo.Extension == ".unity")
                    {
                        string path = GaiaDirectories.GetPathStartingAtAssetsFolder(fileInfo.FullName);

                        if (!m_terrainSceneStorage.m_terrainScenes.Exists(x => x.GetTerrainName() == x.GetTerrainName(path)))
                        {
                            string firstSegment = fileInfo.Name.Split('-')[0];
                            int    xCoord = -99;
                            int    zCoord = -99;
                            bool   successX, successZ;
                            try
                            {
                                successX = Int32.TryParse(firstSegment.Substring(firstSegment.IndexOf('_') + 1, firstSegment.LastIndexOf('_') - (firstSegment.IndexOf('_') + 1)), out xCoord);
                                successZ = Int32.TryParse(firstSegment.Substring(firstSegment.LastIndexOf('_') + 1, firstSegment.Length - 1 - firstSegment.LastIndexOf('_')), out zCoord);
                            }
                            catch (Exception ex)
                            {
                                if (ex.Message == "123")
                                {
                                }
                                successX = false;
                                successZ = false;
                            }


                            if (successX && successZ)
                            {
                                //double centerX = (xCoord - (m_terrainSceneStorage.m_terrainTilesX / 2f)) * m_terrainSceneStorage.m_terrainTilesSize + (m_terrainSceneStorage.m_terrainTilesSize /2f);
                                //double centerZ = (zCoord - (m_terrainSceneStorage.m_terrainTilesZ / 2f)) * m_terrainSceneStorage.m_terrainTilesSize + (m_terrainSceneStorage.m_terrainTilesSize / 2f);
                                Vector2       offset   = new Vector2(-m_terrainSceneStorage.m_terrainTilesSize * m_terrainSceneStorage.m_terrainTilesX * 0.5f, -m_terrainSceneStorage.m_terrainTilesSize * m_terrainSceneStorage.m_terrainTilesZ * 0.5f);
                                Vector3Double position = new Vector3(m_terrainSceneStorage.m_terrainTilesSize * xCoord + offset.x, 0, m_terrainSceneStorage.m_terrainTilesSize * zCoord + offset.y);
                                Vector3Double center   = new Vector3Double(position + new Vector3Double(m_terrainSceneStorage.m_terrainTilesSize / 2f, 0f, m_terrainSceneStorage.m_terrainTilesSize / 2f));
                                BoundsDouble  bounds   = new BoundsDouble(center, new Vector3Double(m_terrainSceneStorage.m_terrainTilesSize, m_terrainSceneStorage.m_terrainTilesSize * 4, m_terrainSceneStorage.m_terrainTilesSize));
                                //Use forward slashes in the path - The Unity scene management classes expect it that way
                                path = path.Replace("\\", "/");
                                TerrainScene terrainScene = new TerrainScene()
                                {
                                    m_scenePath           = path,
                                    m_pos                 = position,
                                    m_bounds              = bounds,
                                    m_useFloatingPointFix = m_terrainSceneStorage.m_useFloatingPointFix
                                };

                                if (File.Exists(path.Replace("Terrain", GaiaConstants.ImpostorTerrainName)))
                                {
                                    terrainScene.m_impostorScenePath = path.Replace("Terrain", GaiaConstants.ImpostorTerrainName);
                                }

                                if (File.Exists(path.Replace("Terrain", "Collider")))
                                {
                                    terrainScene.m_colliderScenePath = path.Replace("Terrain", "Collider");
                                }

                                if (File.Exists(path.Replace("Terrain", "Backup")))
                                {
                                    terrainScene.m_backupScenePath = path.Replace("Terrain", "Backup");
                                }

                                m_terrainSceneStorage.m_terrainScenes.Add(terrainScene);
                                madeChanges = true;
                            }
                        }
                    }
                }
                if (madeChanges)
                {
                    EditorUtility.SetDirty(m_terrainSceneStorage);
                    AssetDatabase.SaveAssets();
                }
            }

            m_lastUsedGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_terrainSceneStorage));


            RefreshTerrainsWithCurrentData();

            RefreshSceneViewLoadingRange();

            ////Go over the currently open scene and close the ones that do not seem to have a reference on them
            //for (int i = EditorSceneManager.loadedSceneCount-1; i >= 0; i--)
            //{
            //    Scene scene = EditorSceneManager.GetSceneAt(i);
            //    if (EditorSceneManager.GetActiveScene().Equals(scene))
            //    {
            //        continue;
            //    }
            //      TerrainScene terrainScene = m_terrainSceneStorage.m_terrainScenes.Find(x => x.m_scenePath == scene.path || x.m_impostorScenePath == scene.path || x.m_colliderScenePath == scene.path);
            //      if (terrainScene != null)
            //      {
            //            terrainScene.UpdateWithCurrentData();
            //      }
            //      else
            //      {
            //            EditorSceneManager.UnloadSceneAsync(scene);
            //      }
            //}
#endif
        }
Example #16
0
 public void Encapsulate(BoundsDouble bounds)
 {
     this.Encapsulate(bounds.center - bounds.extents);
     this.Encapsulate(bounds.center + bounds.extents);
 }
Example #17
0
        /// <summary>
        /// Draw gizmos
        /// </summary>
        void OnDrawGizmos()
        {
            if (m_resources == null)
            {
                return;
            }

            if (m_spawner == null)
            {
                return;
            }

            if (m_terrainHeightMap == null)
            {
                return;
            }

            //Lets visualise fitness
            float x, y = transform.position.y, z;
            float xStart   = transform.position.x - m_range;
            float xEnd     = transform.position.x + m_range;
            float zStart   = transform.position.z - m_range;
            float zEnd     = transform.position.z + m_range;
            float ballsize = Mathf.Clamp(m_resolution * 0.25f, 0.5f, 5f);

            m_spawner.m_settings.m_spawnRange = m_range;
            m_spawner.m_spawnerBounds         = new Bounds(transform.position, new Vector3(m_range * 2f, m_range * 20f, m_range * 2f));

            SpawnInfo spawnInfo = new SpawnInfo();
            Vector3   location  = new Vector3();
            float     fitness   = 0f;

            //Create caches
            if ((DateTime.Now - m_lastCacheUpdateDate).TotalSeconds > 5)
            {
                m_lastCacheUpdateDate = DateTime.Now;
                m_spawner.DeleteSpawnCaches();
                m_spawner.CreateSpawnCaches(m_selectedResourceType, m_selectedResourceIdx);

                //Also update the location so make moving it easier
                Terrain terrain = TerrainHelper.GetTerrain(transform.position);
                if (terrain != null)
                {
                    transform.position = new Vector3(transform.position.x, terrain.SampleHeight(transform.position) + 5f, transform.position.z);
                }
            }

            //Set up the texture layer array in spawn info
            spawnInfo.m_textureStrengths = new float[Terrain.activeTerrain.terrainData.alphamapLayers];

            //Now visualise fitness
            for (x = xStart; x < xEnd; x += m_resolution)
            {
                for (z = zStart; z < zEnd; z += m_resolution)
                {
                    location.Set(x, y, z);
                    if (m_spawner.CheckLocation(location, ref spawnInfo))
                    {
                        fitness = GetFitness(ref spawnInfo);
                        if (fitness < m_minimumFitness)
                        {
                            continue;
                        }
                        Gizmos.color = Color.Lerp(m_unfitColour, m_fitColour, fitness);
                        Gizmos.DrawSphere(spawnInfo.m_hitLocationWU, ballsize);
                    }
                }
            }

            //Now draw water
            //Water
            if (m_resources != null)
            {
                BoundsDouble bounds = new BoundsDouble();
                if (TerrainHelper.GetTerrainBounds(ref bounds) == true)
                {
                    bounds.center = new Vector3Double(bounds.center.x, GaiaSessionManager.GetSessionManager().GetSeaLevel(), bounds.center.z);
                    bounds.size   = new Vector3Double(bounds.size.x, 0.05f, bounds.size.z);
                    Gizmos.color  = new Color(Color.blue.r, Color.blue.g, Color.blue.b, Color.blue.a / 4f);
                    Gizmos.DrawCube(bounds.center, bounds.size);
                }
            }
        }
Example #18
0
        public void CreateWorldMapTerrain()
        {
            //Remove old world map terrain, if any
            Terrain oldWMTerrain = TerrainHelper.GetWorldMapTerrain();

            if (oldWMTerrain != null)
            {
#if UNITY_EDITOR
                if (EditorUtility.DisplayDialog("Delete old world map?", "You are about to create a new world map in this scene. This will delete the existing world map and the stamp tokens on it. This will only affect the small world map terrain, the actual full scene terrain tiles will not be removed. Continue?", "Continue", "Cancel"))
                {
                    DestroyImmediate(oldWMTerrain.gameObject);
                }
                else
                {
                    return;
                }
#else
                Destroy(oldWMTerrain.gameObject);
#endif
            }

            GaiaSettings       gaiaSettings    = GaiaUtils.GetGaiaSettings();
            GaiaDefaults       currentDefaults = gaiaSettings.m_currentDefaults;
            GaiaSessionManager gsm             = GaiaSessionManager.GetSessionManager();

            //Collect some info from the existing world, if any.

            //We need the average height from the terrains to create the height of the worldmap accordingly in scale
            double averageHeight = currentDefaults.m_terrainHeight;
            //We need the heightmap resolution and terrain size stored in the session
            //To properly scale between world map and local map even when one of the two is not loaded at the moment

            int count = 0;

            foreach (Terrain t in Terrain.activeTerrains)
            {
                averageHeight += t.terrainData.size.y;
                if (!TerrainHelper.IsWorldMapTerrain(t))
                {
                    m_localHeightmapRes = t.terrainData.heightmapResolution;
                    m_localTileSize     = t.terrainData.size.x;
                }

                count++;
            }
            //}
            //only calculate an average if there is at least one placeholder or terrain
            if (count > 0)
            {
                averageHeight /= count;
            }


            BoundsDouble bounds = new BoundsDouble();
            TerrainHelper.GetTerrainBounds(ref bounds);
            //Collect the new world settings for world creation
            WorldCreationSettings worldCreationSettings = ScriptableObject.CreateInstance <WorldCreationSettings>();
            worldCreationSettings.m_xTiles                = 1;
            worldCreationSettings.m_zTiles                = 1;
            worldCreationSettings.m_tileSize              = (count > 0) ? Mathd.RoundToInt(bounds.size.x) : gaiaSettings.m_tilesX * currentDefaults.m_terrainSize;
            worldCreationSettings.m_tileHeight            = currentDefaults.m_terrainHeight;
            worldCreationSettings.m_createInScene         = false;
            worldCreationSettings.m_autoUnloadScenes      = false;
            worldCreationSettings.m_applyFloatingPointFix = false;
            worldCreationSettings.m_applyFloatingPointFix = false;
            worldCreationSettings.m_centerOffset          = Vector3.zero; //(count > 0) ? new Vector2Double(bounds.center.x + bounds.extents.x + worldCreationSettings.m_tileSize, bounds.center.z) : Vector2Double.zero;
            worldCreationSettings.m_isWorldMap            = true;
            //clone defaults so we can inject our custom heightmap resolution for the worldmap
            GaiaDefaults clonedDefaults = Instantiate(currentDefaults);
            clonedDefaults.m_heightmapResolution = (int)m_heightmapResolution;

            worldCreationSettings.m_gaiaDefaults = clonedDefaults;

            m_currentWorldCreationSettings     = worldCreationSettings;
            GaiaSessionManager.OnWorldCreated -= OnWorldMapCreate;
            GaiaSessionManager.OnWorldCreated += OnWorldMapCreate;
            GaiaSessionManager.CreateWorld(worldCreationSettings);
        }