Beispiel #1
0
        void CacheTileData(ITerrainSampler terrainSampler, ref MapPixelData mapData)
        {
            // Create array if required
            int dim = MapsFile.WorldMapTileDim + 1;

            if (tileData == null)
            {
                tileData = new int[dim, dim];
            }

            // Populate array with tile metadata
            for (int y = 0; y < dim; y++)
            {
                for (int x = 0; x < dim; x++)
                {
                    // Height sample for ocean and beach tiles
                    float height = TerrainHelper.GetClampedHeight(
                        ref mapData,
                        terrainSampler.HeightmapDimension,
                        (float)x / (float)dim,
                        (float)y / (float)dim) * terrainSampler.MaxTerrainHeight;

                    // Ocean texture
                    if (height <= terrainSampler.OceanElevation)
                    {
                        tileData[x, y] = water;
                        continue;
                    }

                    // Get latitude and longitude of this tile
                    int latitude  = (int)(mapData.mapPixelX * MapsFile.WorldMapTileDim + x);
                    int longitude = (int)(MapsFile.MaxWorldTileCoordZ - mapData.mapPixelY * MapsFile.WorldMapTileDim + y);

                    // Beach texture
                    // Adds a little +/- randomness to threshold so beach line isn't too regular
                    if (height <= terrainSampler.BeachElevation + UnityEngine.Random.Range(-1.5f, 1.5f))
                    {
                        tileData[x, y] = dirt;
                        continue;
                    }

                    // Set texture tile using weighted noise
                    float weight = 0;
                    weight += NoiseWeight(latitude, longitude);
                    // TODO: Add other weights to influence texture tile generation
                    tileData[x, y] = GetWeightedRecord(weight);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Works exactly like the default TerrainTexturer, except that it skips the GenerateTileDataJob
        /// and uses the tileData generated during terrain sampling instead.
        /// Use the mod messaging system to obtain tileData for a map pixel in a custom TerrainTexturer.
        /// </summary>
        ///
        /// To access tileData in a separate mod, you can use this code:
        /// <code>
        /// byte[] tData = null;
        /// ModManager.Instance.SendModMessage("Interesting Terrains", "getTileData", new int[] { mapData.mapPixelX, mapData.mapPixelY }, (string message, object data) =>
        /// {
        ///    if (message == "error")
        ///        Debug.LogError(data as string);
        ///    else
        ///        tData = data as byte[];
        /// });
        /// </code>
        public override JobHandle ScheduleAssignTilesJob(ITerrainSampler terrainSampler, ref MapPixelData mapData, JobHandle dependencies, bool march = true)
        {
            // Load tile data generated by the Terrain Sampler
            var tData = InterestingTerrains.tileDataCache.Get(mapData.mapPixelX, mapData.mapPixelY);
            NativeArray <byte> tileData = new NativeArray <byte>(tData, Allocator.TempJob);

            // Schedule the paint roads jobs if basic roads mod is enabled
            JobHandle preAssignTilesHandle = dependencies;

            if (CompatibilityUtils.BasicRoadsLoaded)
            {
                ModManager.Instance.SendModMessage("BasicRoads", "scheduleRoadsJob", new object[] { mapData, tileData, dependencies },
                                                   (string message, object data) =>
                {
                    if (message == "error")
                    {
                        Debug.LogError(data as string);
                    }
                    else
                    {
                        preAssignTilesHandle = (JobHandle)data;
                    }
                });
            }

            // Assign tile data to terrain
            NativeArray <byte> lookupData     = new NativeArray <byte>(lookupTable, Allocator.TempJob);
            AssignTilesJob     assignTilesJob = new AssignTilesJob
            {
                lookupTable  = lookupData,
                tileData     = tileData,
                tilemapData  = mapData.tilemapData,
                tdDim        = tileDataDim,
                tDim         = assignTilesDim,
                march        = march,
                locationRect = mapData.locationRect,
            };
            JobHandle assignTilesHandle = assignTilesJob.Schedule(assignTilesDim * assignTilesDim, 64, preAssignTilesHandle);

            // Add both working native arrays to disposal list.
            mapData.nativeArrayList.Add(tileData);
            mapData.nativeArrayList.Add(lookupData);

            return(assignTilesHandle);
        }
Beispiel #3
0
        // Very basic marching squares for water > dirt > grass > stone transitions.
        // Cannot handle water > grass or water > stone, etc.
        // Will improve this at later date to use a wider range of transitions.
        public void AssignTiles(ITerrainSampler terrainSampler, ref MapPixelData mapData, bool march = true)
        {
            // Cache tile data to minimise noise sampling
            CacheTileData(terrainSampler, ref mapData);

            // Assign tile data to terrain
            int dim = TerrainHelper.terrainSampleDim;

            for (int y = 0; y < dim; y++)
            {
                for (int x = 0; x < dim; x++)
                {
                    int offset = y * dim + x;

                    // Do nothing if location tile as texture already set
                    if (mapData.samples[offset].location)
                    {
                        continue;
                    }

                    // Assign tile texture
                    if (march)
                    {
                        // Get sample points
                        int b0 = tileData[x, y];
                        int b1 = tileData[x + 1, y];
                        int b2 = tileData[x, y + 1];
                        int b3 = tileData[x + 1, y + 1];

                        int shape  = (b0 & 1) | (b1 & 1) << 1 | (b2 & 1) << 2 | (b3 & 1) << 3;
                        int ring   = (b0 + b1 + b2 + b3) >> 2;
                        int tileID = shape | ring << 4;

                        byte val = lookupTable[tileID];
                        mapData.samples[offset].record = val & 63;
                        mapData.samples[offset].rotate = ((val & 64) == 64);
                        mapData.samples[offset].flip   = ((val & 128) == 128);
                    }
                    else
                    {
                        mapData.samples[offset].record = tileData[x, y];
                    }
                }
            }
        }
        // Very basic marching squares for water > dirt > grass > stone transitions.
        // Cannot handle water > grass or water > stone, etc.
        // Will improve this at later date to use a wider range of transitions.
        public void AssignTiles(ITerrainSampler terrainSampler, ref MapPixelData mapData, bool march = true)
        {
            // Cache tile data to minimise noise sampling
            CacheTileData(terrainSampler, ref mapData);

            // Assign tile data to terrain
            int dim = TerrainHelper.terrainSampleDim;
            for (int y = 0; y < dim; y++)
            {
                for (int x = 0; x < dim; x++)
                {
                    int offset = y * dim + x;

                    // Do nothing if location tile as texture already set
                    if (mapData.samples[offset].location)
                        continue;

                    // Assign tile texture
                    if (march)
                    {
                        // Get sample points
                        int b0 = tileData[x, y];
                        int b1 = tileData[x + 1, y];
                        int b2 = tileData[x, y + 1];
                        int b3 = tileData[x + 1, y + 1];

                        int shape = (b0 & 1) | (b1 & 1) << 1 | (b2 & 1) << 2 | (b3 & 1) << 3;
                        int ring = (b0 + b1 + b2 + b3) >> 2;
                        int tileID = shape | ring << 4;

                        byte val = lookupTable[tileID];
                        mapData.samples[offset].record = val & 63;
                        mapData.samples[offset].rotate = ((val & 64) == 64);
                        mapData.samples[offset].flip = ((val & 128) == 128);
                    }
                    else
                    {
                        mapData.samples[offset].record = tileData[x, y];
                    }
                }
            }
        }
        public override JobHandle ScheduleAssignTilesJob(ITerrainSampler terrainSampler, ref MapPixelData mapData, JobHandle dependencies, bool march = true)
        {
            // Cache tile data to minimise noise sampling during march (using default job)
            NativeArray <byte>  tileData    = new NativeArray <byte>(tileDataDim * tileDataDim, Allocator.TempJob);
            GenerateTileDataJob tileDataJob = new GenerateTileDataJob
            {
                heightmapData    = mapData.heightmapData,
                tileData         = tileData,
                tdDim            = tileDataDim,
                hDim             = terrainSampler.HeightmapDimension,
                maxTerrainHeight = terrainSampler.MaxTerrainHeight,
                oceanElevation   = terrainSampler.OceanElevation,
                beachElevation   = terrainSampler.BeachElevation,
                mapPixelX        = mapData.mapPixelX,
                mapPixelY        = mapData.mapPixelY,
            };
            JobHandle tileDataHandle = tileDataJob.Schedule(tileDataDim * tileDataDim, 64, dependencies);

            // Schedule painting of roads, including smoothing if enabled
            JobHandle paintRoadsHandle = SchedulePaintRoadsJob(ref mapData, ref tileData, tileDataHandle);

            // Assign tile data to terrain (using default job)
            NativeArray <byte> lookupData     = new NativeArray <byte>(lookupTable, Allocator.TempJob);
            AssignTilesJob     assignTilesJob = new AssignTilesJob
            {
                lookupTable  = lookupData,
                tileData     = tileData,
                tilemapData  = mapData.tilemapData,
                tdDim        = tileDataDim,
                tDim         = assignTilesDim,
                march        = march,
                locationRect = mapData.locationRect,
            };
            JobHandle assignTilesHandle = assignTilesJob.Schedule(assignTilesDim * assignTilesDim, 64, paintRoadsHandle);

            // Add both working native arrays to disposal list.
            mapData.nativeArrayList.Add(tileData);
            mapData.nativeArrayList.Add(lookupData);

            return(assignTilesHandle);
        }
        void CacheTileData(ITerrainSampler terrainSampler, ref MapPixelData mapData)
        {
            // Create array if required
            int dim = MapsFile.WorldMapTileDim + 1;
            if (tileData == null)
                tileData = new int[dim, dim];

            // Populate array with tile metadata
            for (int y = 0; y < dim; y++)
            {
                for (int x = 0; x < dim; x++)
                {
                    // Height sample for ocean and beach tiles
                    float height = TerrainHelper.GetClampedHeight(
                        ref mapData,
                        terrainSampler.HeightmapDimension,
                        (float)x / (float)dim,
                        (float)y / (float)dim) * terrainSampler.MaxTerrainHeight;

                    // Ocean texture
                    if (height <= terrainSampler.OceanElevation)
                    {
                        tileData[x, y] = water;
                        continue;
                    }

                    // Get latitude and longitude of this tile
                    int latitude = (int)(mapData.mapPixelX * MapsFile.WorldMapTileDim + x);
                    int longitude = (int)(MapsFile.MaxWorldTileCoordZ - mapData.mapPixelY * MapsFile.WorldMapTileDim + y);

                    // Beach texture
                    // Adds a little +/- randomness to threshold so beach line isn't too regular
                    if (height <= terrainSampler.BeachElevation + UnityEngine.Random.Range(-1.5f, 1.5f))
                    {
                        tileData[x, y] = dirt;
                        continue;
                    }

                    // Set texture tile using weighted noise
                    float weight = 0;
                    weight += NoiseWeight(latitude, longitude);
                    // TODO: Add other weights to influence texture tile generation
                    tileData[x, y] = GetWeightedRecord(weight);
                }
            }
        }
Beispiel #7
0
        public override JobHandle ScheduleAssignTilesJob(ITerrainSampler terrainSampler, ref MapPixelData mapData, JobHandle dependencies, bool march = true)
        {
            // Cache tile data to minimise noise sampling during march.
            NativeArray <byte>  tileData    = new NativeArray <byte>(tileDataDim * tileDataDim, Allocator.TempJob);
            GenerateTileDataJob tileDataJob = new GenerateTileDataJob
            {
                heightmapData    = mapData.heightmapData,
                tileData         = tileData,
                tdDim            = tileDataDim,
                hDim             = terrainSampler.HeightmapDimension,
                maxTerrainHeight = terrainSampler.MaxTerrainHeight,
                oceanElevation   = terrainSampler.OceanElevation,
                beachElevation   = terrainSampler.BeachElevation,
                mapPixelX        = mapData.mapPixelX,
                mapPixelY        = mapData.mapPixelY,
            };
            JobHandle tileDataHandle = tileDataJob.Schedule(tileDataDim * tileDataDim, 64, dependencies);

            // Assign tile data to terrain, painting paths in the process
            int  pathsIndex   = mapData.mapPixelX + (mapData.mapPixelY * MapsFile.MaxMapPixelX);
            byte roadDataPt   = pathsData[roads][pathsIndex];
            byte roadCorners  = (byte)(InRange(pathsIndex) ? (pathsData[roads][pathsIndex + 1] & 0x5) | (pathsData[roads][pathsIndex - 1] & 0x50) : 0);
            byte trackDataPt  = pathsData[tracks][pathsIndex];
            byte trackCorners = (byte)(InRange(pathsIndex) ? (pathsData[tracks][pathsIndex + 1] & 0x5) | (pathsData[tracks][pathsIndex - 1] & 0x50) : 0);

            if (editorEnabled)
            {
                roadDataPt   = BasicRoadsPathEditor.pathsData[roads][pathsIndex];
                roadCorners  = (byte)(InRange(pathsIndex) ? (BasicRoadsPathEditor.pathsData[roads][pathsIndex + 1] & 0x5) | (BasicRoadsPathEditor.pathsData[roads][pathsIndex - 1] & 0x50) : 0);
                trackDataPt  = BasicRoadsPathEditor.pathsData[tracks][pathsIndex];
                trackCorners = (byte)(InRange(pathsIndex) ? (BasicRoadsPathEditor.pathsData[tracks][pathsIndex + 1] & 0x5) | (BasicRoadsPathEditor.pathsData[tracks][pathsIndex - 1] & 0x50) : 0);
            }

            NativeArray <byte>      lookupData     = new NativeArray <byte>(lookupTable, Allocator.TempJob);
            AssignTilesWithRoadsJob assignTilesJob = new AssignTilesWithRoadsJob
            {
                lookupTable  = lookupData,
                tileData     = tileData,
                tilemapData  = mapData.tilemapData,
                tdDim        = tileDataDim,
                tDim         = assignTilesDim,
                hDim         = terrainSampler.HeightmapDimension,
                march        = march,
                locationRect = mapData.locationRect,
                midLo        = (assignTilesDim / 2) - 1,
                midHi        = assignTilesDim / 2,
                roadDataPt   = roadDataPt,
                roadCorners  = roadCorners,
                trackDataPt  = trackDataPt,
                trackCorners = trackCorners,
            };
            JobHandle assignTilesHandle = assignTilesJob.Schedule(assignTilesDim * assignTilesDim, 64, tileDataHandle);

            JobHandle returnHandle = assignTilesHandle;

            if (smoothPaths)
            {
                SmoothRoadsTerrainJob smoothRoadTerrainJob = new SmoothRoadsTerrainJob()
                {
                    heightmapData = mapData.heightmapData,
                    tilemapData   = mapData.tilemapData,
                    hDim          = DaggerfallUnity.Instance.TerrainSampler.HeightmapDimension,
                    tDim          = assignTilesDim,
                    locationRect  = mapData.locationRect,
                };
                JobHandle smoothRoadHandle = smoothRoadTerrainJob.Schedule(assignTilesHandle);
                returnHandle = smoothRoadHandle;
            }

            // Add both working native arrays to disposal list.
            mapData.nativeArrayList.Add(tileData);
            mapData.nativeArrayList.Add(lookupData);

            return(returnHandle);
        }
Beispiel #8
0
        public virtual JobHandle ScheduleAssignTilesJob(ITerrainSampler terrainSampler, ref MapPixelData mapData, JobHandle dependencies, bool march = true)
        {
            // Cache tile data to minimise noise sampling during march.
            NativeArray <byte> tileData = new NativeArray <byte>(tileDataDim * tileDataDim, Allocator.TempJob);

            currentMapData = mapData;

            GenerateTileDataJob tileDataJob = new GenerateTileDataJob
            {
                heightmapData    = mapData.heightmapData,
                tileData         = tileData,
                tdDim            = tileDataDim,
                hDim             = terrainSampler.HeightmapDimension,
                maxTerrainHeight = terrainSampler.MaxTerrainHeight,
                oceanElevation   = terrainSampler.OceanElevation,
                beachElevation   = terrainSampler.BeachElevation,
                mapPixelX        = mapData.mapPixelX,
                mapPixelY        = mapData.mapPixelY,
                worldClimate     = mapData.worldClimate,
            };
            JobHandle tileDataHandle = tileDataJob.Schedule(tileDataDim * tileDataDim, 64, dependencies);

            // Schedule the paint roads jobs if basic roads mod is enabled
            JobHandle preAssignTilesHandle = tileDataHandle;

            if (basicRoadsEnabled)
            {
                ModManager.Instance.SendModMessage("BasicRoads", "scheduleRoadsJob", new object[] { mapData, tileData, tileDataHandle },
                                                   (string message, object data) =>
                {
                    if (message == "error")
                    {
                        Debug.LogError(data as string);
                    }
                    else
                    {
                        preAssignTilesHandle = (JobHandle)data;
                    }
                });
            }

            // Assign tile data to terrain
            NativeArray <byte> lookupData     = new NativeArray <byte>(lookupTable, Allocator.TempJob);
            AssignTilesJob     assignTilesJob = new AssignTilesJob
            {
                lookupTable  = lookupData,
                tileData     = tileData,
                tilemapData  = mapData.tilemapData,
                tdDim        = tileDataDim,
                tDim         = assignTilesDim,
                march        = march,
                locationRect = mapData.locationRect,
            };
            JobHandle assignTilesHandle = assignTilesJob.Schedule(assignTilesDim * assignTilesDim, 64, preAssignTilesHandle);

            // Add both working native arrays to disposal list.
            mapData.nativeArrayList.Add(tileData);
            mapData.nativeArrayList.Add(lookupData);

            return(assignTilesHandle);
        }