Exemple #1
0
    private void DownScaleHeightmap(TerrainQualityManagerQuery query)
    {
        TerrainData terrainData = query.terrainData;

        if (query.data == null)
        {
            object[] data = new object[3];
            data[0]    = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight);
            data[1]    = new float[heightmapResolution, heightmapResolution];
            data[2]    = (terrainData.heightmapResolution - 1) / (heightmapResolution - 1);
            query.data = data;
        }

        object[] queryData = query.data as object[];

        float[,] heights    = queryData[0] as float[, ];
        float[,] newHeights = queryData[1] as float[, ];
        int step     = (int)queryData[2];
        int halfStep = step / 2;

        long startTime = DateTime.Now.Ticks;

        for (int y = activeQueryIndex; y < heightmapResolution; y++)
        {
            query.progress   = (float)y / heightmapResolution;
            activeQueryIndex = y;
            if (DateTime.Now.Ticks - startTime > maxExecutionTime)
            {
                return;
            }

            int sy = (y == 0) ? 0 : y * step - halfStep;
            int ly = (y > 0 && y < heightmapResolution - 1) ? step : halfStep;

            for (int x = 0; x < heightmapResolution; x++)
            {
                int sx = (x == 0) ? 0 : x * step - halfStep;
                int lx = (x > 0 && x < heightmapResolution - 1) ? step : halfStep;

                float v = 0;

                for (int py = 0; py < ly; py++)
                {
                    for (int px = 0; px < lx; px++)
                    {
                        v += heights[sy + py, sx + px];
                    }
                }

                newHeights[y, x] = v / (lx * ly);
            }
        }

        ApplyNewHeightmap(query.terrainData, newHeights);

        NextQuery();
    }
Exemple #2
0
    private TerrainQualityManagerQuery AddQuery(string name, TerrainData terrainData = null)
    {
        if (queries == null)
        {
            queries = new List <TerrainQualityManagerQuery>();
        }
        TerrainQualityManagerQuery query = new TerrainQualityManagerQuery(terrainData, name);

        queries.Add(query);
        return(query);
    }
Exemple #3
0
    private void UpdateNeighbors(TerrainQualityManagerQuery query)
    {
        Terrain[] terrains = FindObjectsOfType <Terrain>();
        if (terrains == null || terrains.Length == 0)
        {
            return;
        }

        foreach (Terrain t in terrains)
        {
            TerrainData terrainData            = t.terrainData;
            Vector3     rightNeighborPosition  = t.transform.position + new Vector3(terrainData.size.x, 0, 0);
            Vector3     bottomNeighborPosition = t.transform.position + new Vector3(0, 0, terrainData.size.z);

            Terrain rightNeighbor  = terrains.FirstOrDefault(tr => (tr.transform.position - rightNeighborPosition).magnitude < 10);
            Terrain bottomNeighbor = terrains.FirstOrDefault(tr => (tr.transform.position - bottomNeighborPosition).magnitude < 10);

            if (rightNeighbor != null)
            {
                float[,] th = terrainData.GetHeights(heightmapResolution - 1, 0, 1, heightmapResolution);
                float[,] rh = rightNeighbor.terrainData.GetHeights(0, 0, 1, heightmapResolution);

                for (int y = 0; y < heightmapResolution; y++)
                {
                    th[y, 0] = (th[y, 0] + rh[y, 0]) / 2;
                }

                terrainData.SetHeights(heightmapResolution - 1, 0, th);
                rightNeighbor.terrainData.SetHeights(0, 0, th);
            }

            if (bottomNeighbor != null)
            {
                float[,] th = terrainData.GetHeights(0, heightmapResolution - 1, heightmapResolution, 1);
                float[,] rh = bottomNeighbor.terrainData.GetHeights(0, 0, heightmapResolution, 1);

                for (int x = 0; x < heightmapResolution; x++)
                {
                    th[0, x] = (th[0, x] + rh[0, x]) / 2;
                }

                terrainData.SetHeights(0, heightmapResolution - 1, th);
                bottomNeighbor.terrainData.SetHeights(0, 0, th);
            }
        }

        NextQuery();
    }
Exemple #4
0
    private void UpScaleHeightmap(TerrainQualityManagerQuery query)
    {
        if (query.data == null)
        {
            object[] data = new object[1];
            data[0]    = new float[heightmapResolution, heightmapResolution];
            query.data = data;
        }

        object[] queryData = query.data as object[];
        float[,] newHeights = queryData[0] as float[, ];
        TerrainData terrainData = query.terrainData;

        long startTime = DateTime.Now.Ticks;

        for (int x = activeQueryIndex; x < heightmapResolution; x++)
        {
            query.progress   = (float)x / heightmapResolution;
            activeQueryIndex = x;
            if (DateTime.Now.Ticks - startTime > maxExecutionTime)
            {
                return;
            }

            float rx = (float)x / (heightmapResolution - 1);
            for (int y = 0; y < heightmapResolution; y++)
            {
                float ry = (float)y / (heightmapResolution - 1);
                newHeights[y, x] = terrainData.GetInterpolatedHeight(rx, ry) / terrainData.size.y;
            }
        }

        ApplyNewHeightmap(query.terrainData, newHeights);

        NextQuery();
    }
Exemple #5
0
    private void DownScaleAlphamap(TerrainQualityManagerQuery query)
    {
        TerrainData terrainData = query.terrainData;
        int         splatCount  = terrainData.splatPrototypes.Length;

        if (query.data == null)
        {
            object[] data = new object[3];
            data[0]    = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
            data[1]    = new float[alphamapResolution, alphamapResolution, splatCount];
            query.data = data;
        }

        object[] queryData = query.data as object[];
        float[,,] alphamaps    = queryData[0] as float[, , ];
        float[,,] newAlphamaps = queryData[1] as float[, , ];

        int step     = terrainData.alphamapResolution / alphamapResolution;
        int halfStep = step / 2;

        long startTime = DateTime.Now.Ticks;

        for (int sp = activeQueryIndex; sp < splatCount; sp++)
        {
            query.progress   = (float)sp / splatCount;
            activeQueryIndex = sp;
            if (DateTime.Now.Ticks - startTime > maxExecutionTime)
            {
                return;
            }

            for (int y = 0; y < alphamapResolution; y++)
            {
                int sy = (y == 0) ? 0 : y * step - halfStep;
                int ly = (y > 0 && y < alphamapResolution - 1) ? step : halfStep;

                for (int x = 0; x < alphamapResolution; x++)
                {
                    int sx = (x == 0) ? 0 : x * step - halfStep;
                    int lx = (x > 0 && x < alphamapResolution - 1) ? step : halfStep;

                    float v = 0;

                    for (int py = 0; py < ly; py++)
                    {
                        for (int px = 0; px < lx; px++)
                        {
                            v += alphamaps[sx + px, sy + py, sp];
                        }
                    }

                    newAlphamaps[x, y, sp] = v / (lx * ly);
                }
            }
        }

        query.terrainData.alphamapResolution = alphamapResolution;
        query.terrainData.SetAlphamaps(0, 0, newAlphamaps);

        NextQuery();
    }
Exemple #6
0
    private void UpScaleAlphamap(TerrainQualityManagerQuery query)
    {
        TerrainData terrainData = query.terrainData;
        int         splatCount  = terrainData.splatPrototypes.Length;

        if (query.data == null)
        {
            object[] data = new object[2];
            data[0]    = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
            data[1]    = new float[alphamapResolution, alphamapResolution, splatCount];
            query.data = data;
        }

        object[] queryData = query.data as object[];
        float[, ,] alphamaps    = queryData[0] as float[, , ];
        float[, ,] newAlphamaps = queryData[1] as float[, , ];

        long startTime = DateTime.Now.Ticks;

        for (int sp = activeQueryIndex; sp < splatCount; sp++)
        {
            query.progress   = (float)sp / splatCount;
            activeQueryIndex = sp;
            if (DateTime.Now.Ticks - startTime > maxExecutionTime)
            {
                return;
            }

            for (int y = 0; y < alphamapResolution; y++)
            {
                float ry = (float)y / alphamapResolution * terrainData.alphamapResolution;

                int y1 = (int)ry;
                int y2 = y1 + 1;
                if (y2 >= terrainData.alphamapResolution)
                {
                    y2 = terrainData.alphamapResolution - 1;
                }

                for (int x = 0; x < alphamapResolution; x++)
                {
                    float rx = (float)x / alphamapResolution * terrainData.alphamapResolution;

                    int x1 = (int)rx;
                    int x2 = x1 + 1;
                    if (x2 >= terrainData.alphamapResolution)
                    {
                        x2 = terrainData.alphamapResolution - 1;
                    }

                    float p1 = Mathf.Lerp(alphamaps[x1, y1, sp], alphamaps[x2, y1, sp], rx - x1);
                    float p2 = Mathf.Lerp(alphamaps[x1, y2, sp], alphamaps[x2, y2, sp], rx - x1);

                    newAlphamaps[x, y, sp] = Mathf.Lerp(p1, p2, ry - y1);
                }
            }
        }

        query.terrainData.alphamapResolution = alphamapResolution;
        query.terrainData.SetAlphamaps(0, 0, newAlphamaps);

        NextQuery();
    }
Exemple #7
0
    private void ScaleDetailmap(TerrainQualityManagerQuery query)
    {
        TerrainData terrainData = query.terrainData;

        if (query.data == null)
        {
            query.data = new List <int[, ]>();
        }

        List <int[, ]> detailLayers = query.data as List <int[, ]>;

        int countProts   = terrainData.detailPrototypes.Length;
        int detailWidth  = terrainData.detailWidth;
        int detailHeight = terrainData.detailHeight;

        long startTime = DateTime.Now.Ticks;

        for (int p = activeQueryIndex; p < countProts; p++)
        {
            query.progress   = (float)p / countProts;
            activeQueryIndex = p;
            if (DateTime.Now.Ticks - startTime > maxExecutionTime)
            {
                return;
            }

            int[,] detailLayer    = terrainData.GetDetailLayer(0, 0, detailWidth, detailHeight, p);
            int[,] newDetailLayer = new int[detailResolution, detailResolution];

            for (int x = 0; x < detailResolution; x++)
            {
                float rx = (float)x / detailResolution * terrainData.detailResolution;
                int   x1 = (int)rx;
                int   x2 = x1 + 1;
                if (x2 >= terrainData.detailResolution)
                {
                    x2 = terrainData.detailResolution - 1;
                }

                for (int y = 0; y < detailResolution; y++)
                {
                    float ry = (float)y / detailResolution * terrainData.detailResolution;

                    int y1 = (int)ry;
                    int y2 = y1 + 1;
                    if (y2 >= terrainData.detailResolution)
                    {
                        y2 = terrainData.detailResolution - 1;
                    }

                    float p1 = Mathf.RoundToInt(Mathf.Lerp(detailLayer[x1, y1], detailLayer[x2, y1], rx - x1));
                    float p2 = Mathf.RoundToInt(Mathf.Lerp(detailLayer[x1, y2], detailLayer[x2, y2], rx - x1));

                    newDetailLayer[x, y] = Mathf.RoundToInt(Mathf.Lerp(p1, p2, ry - y1));
                }
            }

            detailLayers.Add(newDetailLayer);
        }

        terrainData.SetDetailResolution(detailResolution, resolutionPerPatch);

        for (int i = 0; i < detailLayers.Count; i++)
        {
            terrainData.SetDetailLayer(0, 0, i, detailLayers[i]);
        }

        NextQuery();
    }
Exemple #8
0
    private void Prepare()
    {
        TerrainData[] terrainDatas = null;
        if (mode == TerrainQualityManagerModes.singleTerrain)
        {
            if (terrain == null)
            {
                EditorUtility.DisplayDialog("Error", "Terrain not selected.", "OK");
                state = TerrainQualityManagerState.idle;
                return;
            }
            terrainDatas = new[] { terrain.terrainData };
        }
        else if (mode == TerrainQualityManagerModes.allTerrainsInScene)
        {
            Terrain[] terrains = FindObjectsOfType(typeof(Terrain)) as Terrain[];
            if (terrains != null)
            {
                terrainDatas = terrains.Select(t => t.terrainData).ToArray();
            }
        }
        else if (mode == TerrainQualityManagerModes.allTerrainsInProject)
        {
            string[] terrainsGUID = AssetDatabase.FindAssets("t:terrain");
            terrainDatas = new TerrainData[terrainsGUID.Length];
            for (int i = 0; i < terrainsGUID.Length; i++)
            {
                string assetPath = AssetDatabase.GUIDToAssetPath(terrainsGUID[i]);
                terrainDatas[i] = AssetDatabase.LoadMainAssetAtPath(assetPath) as TerrainData;
            }
        }

        if (terrainDatas == null)
        {
            state = TerrainQualityManagerState.idle;
            return;
        }

        bool changeHeightmap = false;

        foreach (TerrainData t in terrainDatas)
        {
            if (t.heightmapResolution != heightmapResolution)
            {
                changeHeightmap = true;
                TerrainQualityManagerQuery query = AddQuery("Resize heightmap.", t);
                if (t.heightmapResolution > heightmapResolution)
                {
                    query.method = DownScaleHeightmap;
                }
                else
                {
                    query.method = UpScaleHeightmap;
                }
            }
            if (t.alphamapResolution != alphamapResolution)
            {
                TerrainQualityManagerQuery query = AddQuery("Resize alphamap.", t);
                if (t.alphamapResolution > alphamapResolution)
                {
                    query.method = DownScaleAlphamap;
                }
                else
                {
                    query.method = UpScaleAlphamap;
                }
            }
            if (t.detailResolution != detailResolution)
            {
                AddQuery("Resize detailmap.", t).method = ScaleDetailmap;
            }
            if (t.baseMapResolution != baseMapResolution)
            {
                t.baseMapResolution = baseMapResolution;
            }
        }

        if (queries == null || queries.Count == 0)
        {
            EditorUtility.DisplayDialog("Error", "Nothing to do.", "OK");
            Finish();
            return;
        }

        Undo.RegisterCompleteObjectUndo(terrainDatas, "Change Terrain Maps Resolution");

        if (changeHeightmap && mode == TerrainQualityManagerModes.allTerrainsInScene)
        {
            AddQuery("Update Neighbors").method = UpdateNeighbors;
        }

        activeQueryIndex = 0;
        queryIndex       = 0;
        state            = TerrainQualityManagerState.working;
    }