Example #1
0
    void Apply(bool createAssets)
    {
        heightsFile = EditorUtility.OpenFilePanel("Select heights definitions file", Application.dataPath, "");
        PathReader path = new PathReader(heightsFile);

        float pathLength = path.GetMaxValue();

        chunksCount = ((int)(pathLength + 1)) / chunkSize;


        if (createAssets)
        {
            GenerateTerrains(chunksCount);
        }


        /************
         * GET TERRAINS
         ********/
        sceneTerrains = FindObjectsOfType(typeof(Terrain)) as Terrain[];
        if (sceneTerrains.Length == 0 || chunksCount != sceneTerrains.Length)
        {
            EditorUtility.DisplayDialog("Error", "The number of terrains does not match input file", "Ok");
            return;
        }
        //ORDER BY Z
        System.Array.Sort(sceneTerrains, zComparator);



        /****************************
         * Your track is between 25% and 75% of the terrain height
         * *************************/
        int   maxHeight      = path.GetMaxHeight();
        int   terrainsHeight = maxHeight * 2;
        float groundOffset   = 1f / 4f;

        //SET TERRAINS NEW HEIGHT
        for (int i = 0; i < sceneTerrains.Length; i++)
        {
            sceneTerrains[i].terrainData.size = new Vector3(chunkSize, terrainsHeight, chunkSize);
        }



        /****************
        * Use an extend heightmap for the coherent noise (not chunked)
        * **************/
        int extendedHeightmapLength = chunkSize /*heightmapResolution*/ * chunksCount;     //NEEDS FIX

        float[,] extendedHeightmap = new float[heightmapResolution, extendedHeightmapLength];



        float value           = 0f;
        int   projectionStart = 0;
        int   projectionEnd   = 0;

        /*****************
         * If the height definition does not start from 0,
         * the terrain is set to the height of the first point
         * **************/
        int firstPosition = RealPositionToHeightmap(path.points [0].positionProjection);

        for (int z = 0; z < firstPosition; z++)
        {
            for (int x = 0; x < heightmapResolution; x++)
            {
                extendedHeightmap[x, z] = path.points [0].height / terrainsHeight + groundOffset;
            }
        }


        /******************************
         * Set the slopes according to the heights definition
         * ***************************/
        for (int p = 0; p < path.points.Count - 1; p++)
        {
            PathReader.Point s = path.points[p];
            PathReader.Point e = path.points[p + 1];

            projectionStart = RealPositionToHeightmap(s.positionProjection);
            projectionEnd   = RealPositionToHeightmap(e.positionProjection);

            float segmentLength = projectionEnd - projectionStart;
            for (int z = projectionStart; z < projectionEnd; z++)
            {
                value = Mathf.Lerp(s.height, e.height, (float)(z - projectionStart) / segmentLength);
                for (int x = 0; x < heightmapResolution; x++)
                {
                    extendedHeightmap[x, z] = value / terrainsHeight + groundOffset;
                }
            }
        }

        /****************************
         * The segment from the last point and the end of the terrain
         * is set to the last height
         * *************************/
        for (int z = projectionEnd; z < extendedHeightmapLength; z++)
        {
            for (int x = 0; x < heightmapResolution; x++)
            {
                extendedHeightmap[x, z] = value / terrainsHeight + groundOffset;
            }
        }



        //APPLY NOISE
        float[,] noiseMap = generatePerlin(seed, heightmapResolution, extendedHeightmapLength);



        //APPLY THE COMPUTED HEIGHTMAP TO THE TERRAINS
        for (int i = 0; i < sceneTerrains.Length; i++)
        {
            float[,] slopes = getTerrainHeightmap(extendedHeightmap, i);
            float[,] noise  = getTerrainHeightmap(noiseMap, i);

            float[,] mergedHeightMap = new float[heightmapResolution, heightmapResolution];
            for (int w = 0; w < heightmapResolution; w++)
            {
                int leftPathBorder  = (heightmapResolution / 2) - pathWidth;
                int rightPathBorder = (heightmapResolution / 2) + pathWidth;
                for (int h = 0; h < leftPathBorder; h++)
                {
                    float ratio      = leftHeight * Mathf.SmoothStep(1, /*1-leftHeight*/ 0, (float)h / (float)leftPathBorder);
                    float noiseValue = (noise[w, h]) * noiseAmount;
                    mergedHeightMap[w, h] = slopes[w, h] + ratio * noiseValue;

                    /*float ratio = Mathf.SmoothStep(0.7f,0,(float)h/(float)leftPathBorder);
                     * float noiseValue = noise[w,h];
                     * float cliff = Mathf.SmoothStep(0.25f, slopes[w,h],(float)h/(float)leftPathBorder);
                     * mergedHeightMap[w,h] = cliff-ratio*noiseValue;*/
                }
                for (int h = rightPathBorder; h < heightmapResolution; h++)
                {
                    float ratio      = rightHeight * Mathf.SmoothStep(0, /*rightHeight*/ 1, (float)(h - pathWidth - leftPathBorder) / (float)(leftPathBorder));
                    float noiseValue = (noise[w, h]) * noiseAmount;
                    mergedHeightMap[w, h] = slopes[w, h] + ratio * noiseValue;
                }


                for (int h = leftPathBorder; h < rightPathBorder; h++)
                {
                    mergedHeightMap[w, h] = slopes[w, h];
                }
            }

            sceneTerrains[i].terrainData.SetHeights(0, 0, mergedHeightMap);
        }

        if (createAssets)
        {
            CreateLight();
        }
    }