public ChunkOrientationData MakeOrientationRequestForChunk(IMapChunk chunk)
        {
            var newData = new ChunkOrientationData(chunk);

            UnrenderedOrientationData.Add(newData);

            return(newData);
        }
        public void ReleaseOrientationData(ChunkOrientationData data)
        {
            FreeBakerTriplets.Enqueue(data.BakerTriplet);

            data.BakerTriplet = null;
        }
예제 #3
0
        private IEnumerator RefreshAlphamap(ChunkOrientationData orientationData)
        {
            var terrainData = Terrain.terrainData;

            var unsafeOrientationTexture = new AsyncTextureUnsafe <Color32>(orientationData.OrientationTexture);
            var unsafeWeightsTexture     = new AsyncTextureUnsafe <Color32>(orientationData.WeightsTexture);
            var unsafeDuckTexture        = new AsyncTextureUnsafe <Color32>(orientationData.DuckTexture);

            Vector3 terrainSize = terrainData.size;

            int mapWidth  = terrainData.alphamapWidth;
            int mapHeight = terrainData.alphamapHeight;

            int alphamapLength = RenderConfig.MapTextures.Count();

            float[,,] alphaMaps = terrainData.GetAlphamaps(0, 0, mapWidth, mapHeight);

            float maxTextureNormalX = Width / RenderConfig.ChunkWidth;
            float maxTextureNormalZ = Height / RenderConfig.ChunkHeight;

            float indexToNormalX = 1f / (mapHeight - 1f);
            float indexToNormalZ = 1f / (mapWidth - 1f);

            Vector3 chunkPosition = transform.position;

            var columnTasks = new Task[mapHeight];

            for (int height = 0; height < mapHeight; height++)
            {
                int cachedHeight = height;

                var indexBytes = new byte[2];

                PointOrientationData pointOrientation = new PointOrientationData();

                float[] returnMap       = new float[RenderConfig.MapTextures.Count()];
                float[] intermediateMap = new float[RenderConfig.MapTextures.Count()];

                var columnTask = new Task(() => {
                    for (int width = 0; width < mapWidth; width++)
                    {
                        float terrainNormalX, terrainNormalZ, textureNormalX, textureNormalZ, worldX, worldZ;

                        Color32 orientationColor;
                        Color weightsColor, duckColor;

                        //For some reason, terrainData seems to index its points
                        //as (y, x) rather than the more traditional (x, y), so
                        //we need to sample our texture accordingly
                        terrainNormalX = cachedHeight * indexToNormalX;
                        terrainNormalZ = width * indexToNormalZ;

                        worldX = chunkPosition.x + terrainNormalX * terrainSize.x;
                        worldZ = chunkPosition.z + terrainNormalZ * terrainSize.z;

                        textureNormalX = maxTextureNormalX * terrainNormalX;
                        textureNormalZ = maxTextureNormalZ * terrainNormalZ;

                        orientationColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeOrientationTexture));
                        weightsColor     = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeWeightsTexture));
                        duckColor        = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeDuckTexture));

                        PointOrientationLogic.GetOrientationDataFromColors(
                            pointOrientation, indexBytes, orientationColor, weightsColor, duckColor
                            );

                        AlphamapLogic.GetAlphamapFromOrientation(returnMap, intermediateMap, pointOrientation);

                        for (int alphaIndex = 0; alphaIndex < alphamapLength; alphaIndex++)
                        {
                            alphaMaps[width, cachedHeight, alphaIndex] = returnMap[alphaIndex];
                        }
                    }
                });

                columnTask.Start();

                columnTasks[cachedHeight] = columnTask;
            }

            while (columnTasks.Any(task => !task.IsCompleted))
            {
                yield return(SkipFrame);
            }

            terrainData.SetAlphamaps(0, 0, alphaMaps);
        }
예제 #4
0
        private IEnumerator RefreshHeightmap(ChunkOrientationData chunkOrientation)
        {
            var terrainData = Terrain.terrainData;

            var unsafeOrientationTexture = new AsyncTextureUnsafe <Color32>(chunkOrientation.OrientationTexture);
            var unsafeWeightsTexture     = new AsyncTextureUnsafe <Color32>(chunkOrientation.WeightsTexture);
            var unsafeDuckTexture        = new AsyncTextureUnsafe <Color32>(chunkOrientation.DuckTexture);

            var unsafeFlatlandsNoise = new AsyncTextureUnsafe <Color32>(RenderConfig.FlatlandsElevationNoiseSource);
            var unsafeHillsNoise     = new AsyncTextureUnsafe <Color32>(RenderConfig.HillsElevationNoiseSource);

            Vector3 terrainSize = terrainData.size;

            int mapWidth  = terrainData.heightmapWidth;
            int mapHeight = terrainData.heightmapHeight;

            float[,] heights = terrainData.GetHeights(0, 0, mapWidth, mapHeight);

            float maxTextureNormalX = Width / RenderConfig.ChunkWidth;
            float maxTextureNormalZ = Height / RenderConfig.ChunkHeight;

            float indexToNormalX = 1f / (mapHeight - 1f);
            float indexToNormalZ = 1f / (mapWidth - 1f);

            Vector3 chunkPosition = transform.position;

            var columnTasks = new Task[mapHeight];

            for (int height = 0; height < mapHeight; height++)
            {
                int cachedHeight = height;

                var indexBytes = new byte[2];

                PointOrientationData pointOrientation = new PointOrientationData();

                var columnTask = new Task(() => {
                    for (int width = 0; width < mapWidth; width++)
                    {
                        float terrainNormalX, terrainNormalZ, textureNormalX, textureNormalZ, worldX, worldZ;

                        Color32 orientationColor;
                        Color weightsColor, duckColor;

                        //For some reason, terrainData seems to index its points
                        //as (y, x) rather than the more traditional (x, y), so
                        //we need to sample our texture accordingly
                        terrainNormalX = cachedHeight * indexToNormalX;
                        terrainNormalZ = width * indexToNormalZ;

                        worldX = chunkPosition.x + terrainNormalX * terrainSize.x;
                        worldZ = chunkPosition.z + terrainNormalZ * terrainSize.z;

                        textureNormalX = maxTextureNormalX * terrainNormalX;
                        textureNormalZ = maxTextureNormalZ * terrainNormalZ;

                        orientationColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeOrientationTexture));
                        weightsColor     = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeWeightsTexture));
                        duckColor        = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeDuckTexture));

                        PointOrientationLogic.GetOrientationDataFromColors(
                            pointOrientation, indexBytes, orientationColor, weightsColor, duckColor
                            );

                        heights[width, cachedHeight] = HeightLogic.GetHeightForPoint(
                            new Vector2(worldX, worldZ), pointOrientation, unsafeFlatlandsNoise, unsafeHillsNoise
                            );
                    }
                });

                columnTask.Start();

                columnTasks[cachedHeight] = columnTask;
            }

            while (columnTasks.Any(task => !task.IsCompleted))
            {
                yield return(SkipFrame);
            }

            terrainData.SetHeights(0, 0, heights);
        }
예제 #5
0
        private IEnumerator Refresh_Perform()
        {
            MapRenderingSignals.ChunkStartingToRefresh.OnNext(this);

            yield return(SkipFrame);

            while (FullMapRefresher.IsRefreshingRivers)
            {
                yield return(SkipFrame);
            }

            yield return(SkipFrame);

            bool flushTerrain = false;

            if ((RefreshFlags & TerrainRefreshType.RequiresOrientation) != 0)
            {
                ChunkOrientationData orientationData = OrientationBaker.MakeOrientationRequestForChunk(this);

                while (!orientationData.IsReady)
                {
                    yield return(SkipFrame);
                }

                if (((RefreshFlags & TerrainRefreshType.Alphamap) == TerrainRefreshType.Alphamap))
                {
                    yield return(StartCoroutine(RefreshAlphamap(orientationData)));

                    flushTerrain = true;
                }

                if (((RefreshFlags & TerrainRefreshType.Heightmap) == TerrainRefreshType.Heightmap))
                {
                    yield return(StartCoroutine(RefreshHeightmap(orientationData)));

                    flushTerrain = true;
                }

                OrientationBaker.ReleaseOrientationData(orientationData);
            }

            if (((RefreshFlags & TerrainRefreshType.Water) == TerrainRefreshType.Water))
            {
                RefreshWater();
            }

            if (flushTerrain)
            {
                Terrain.Flush();

                if (Terrain.topNeighbor != null)
                {
                    Terrain.topNeighbor.Flush();
                }
                if (Terrain.rightNeighbor != null)
                {
                    Terrain.rightNeighbor.Flush();
                }
                if (Terrain.bottomNeighbor != null)
                {
                    Terrain.bottomNeighbor.Flush();
                }
                if (Terrain.leftNeighbor != null)
                {
                    Terrain.leftNeighbor.Flush();
                }

                yield return(SkipFrame);
            }

            if (((RefreshFlags & TerrainRefreshType.Culture) == TerrainRefreshType.Culture))
            {
                RefreshCulture();
            }

            if (((RefreshFlags & TerrainRefreshType.Features) == TerrainRefreshType.Features))
            {
                RefreshFeatures();
            }

            if (((RefreshFlags & TerrainRefreshType.Roads) == TerrainRefreshType.Roads))
            {
                RefreshRoads();
            }

            if (((RefreshFlags & TerrainRefreshType.Marshes) == TerrainRefreshType.Marshes))
            {
                RefreshMarshes();
            }

            if (((RefreshFlags & TerrainRefreshType.Oases) == TerrainRefreshType.Oases))
            {
                RefreshOases();
            }

            if (((RefreshFlags & TerrainRefreshType.Visibility) == TerrainRefreshType.Visibility))
            {
                RefreshVisibility();
            }

            RefreshFlags = TerrainRefreshType.None;

            RefreshCoroutine = null;

            MapRenderingSignals.ChunkFinishedRefreshing.OnNext(this);
        }