/// <summary>
        /// Update tile map data based on current map pixel data.
        /// </summary>
        public void UpdateTileMapData()
        {
            // Create tileMap array if not present
            if (tileMap == null)
            {
                tileMap = new Color32[tileMapDim * tileMapDim];
            }

            // Also recreate if not sized appropriately
            if (tileMap.Length != tileMapDim * tileMapDim)
            {
                tileMap = new Color32[tileMapDim * tileMapDim];
            }

            // Assign tile data to tilemap
            Color32 tileColor = new Color32(0, 0, 0, 0);

            for (int y = 0; y < tileMapDim; y++)
            {
                for (int x = 0; x < tileMapDim; x++)
                {
                    // Get sample tile data
                    WorldSample sample = MapData.samples[y * TerrainHelper.terrainSampleDim + x];

                    // Calculate tile index
                    byte record = (byte)(sample.record * 4);
                    if (sample.rotate && !sample.flip)
                    {
                        record += 1;
                    }
                    if (!sample.rotate && sample.flip)
                    {
                        record += 2;
                    }
                    if (sample.rotate && sample.flip)
                    {
                        record += 3;
                    }

                    // Assign to tileMap
                    tileColor.r = record;
                    tileMap[y * tileMapDim + x] = tileColor;
                }
            }
        }
示例#2
0
        // Drops nature flats based on random chance scaled by simple rules
        public static void LayoutNatureBillboards(DaggerfallTerrain dfTerrain, DaggerfallBillboardBatch dfBillboardBatch, float terrainScale)
        {
            const float maxSteepness  = 50f;        // 50
            const float chanceOnDirt  = 0.2f;       // 0.2
            const float chanceOnGrass = 0.9f;       // 0.4
            const float chanceOnStone = 0.05f;      // 0.05

            // Get terrain
            Terrain terrain = dfTerrain.gameObject.GetComponent <Terrain>();

            if (!terrain)
            {
                return;
            }

            // Get terrain data
            TerrainData terrainData = terrain.terrainData;

            if (!terrainData)
            {
                return;
            }

            // Remove exiting billboards
            dfBillboardBatch.Clear();

            // Seed random with terrain key
            UnityEngine.Random.seed = MakeTerrainKey(dfTerrain.MapPixelX, dfTerrain.MapPixelY);

            // Just layout some random flats spread evenly across entire map pixel area
            // Flats are aligned with tiles, max 127x127 in billboard batch
            Vector2 tilePos = Vector2.zero;
            float   scale   = terrainData.heightmapScale.x;
            int     dim     = TerrainHelper.terrainTileDim - 1;

            for (int y = 0; y < dim; y++)
            {
                for (int x = 0; x < dim; x++)
                {
                    // Reject based on steepness
                    float steepness = terrainData.GetSteepness((float)x / dim, (float)y / dim);
                    if (steepness > maxSteepness)
                    {
                        continue;
                    }

                    // Reject if inside location rect
                    // Rect is expanded slightly to give extra clearance around locations
                    tilePos.x = x;
                    tilePos.y = y;
                    const int natureClearance = 4;
                    Rect      rect            = dfTerrain.MapData.locationRect;
                    if (rect.x > 0 && rect.y > 0)
                    {
                        rect.xMin -= natureClearance;
                        rect.xMin += natureClearance;
                        rect.yMin -= natureClearance;
                        rect.yMax += natureClearance;
                        if (rect.Contains(tilePos))
                        {
                            continue;
                        }
                    }

                    // Chance scaled based on map pixel height
                    // This tends to produce sparser lowlands and denser highlands
                    // Adjust or remove clamp range to influence nature generation
                    float elevationScale = (dfTerrain.MapData.worldHeight / 128f);
                    elevationScale = Mathf.Clamp(elevationScale, 0.4f, 1.0f);

                    // Chance scaled by base climate type
                    float climateScale = 1.0f;
                    DFLocation.ClimateSettings climate = MapsFile.GetWorldClimateSettings(dfTerrain.MapData.worldClimate);
                    switch (climate.ClimateType)
                    {
                    case DFLocation.ClimateBaseType.Desert:             // Just lower desert for now
                        climateScale = 0.25f;
                        break;
                    }

                    // Chance also determined by tile type
                    WorldSample sample = TerrainHelper.GetSample(ref dfTerrain.MapData.samples, x, y);
                    if (sample.record == 1)
                    {
                        // Dirt
                        if (UnityEngine.Random.Range(0f, 1f) > chanceOnDirt * elevationScale * climateScale)
                        {
                            continue;
                        }
                    }
                    else if (sample.record == 2)
                    {
                        // Grass
                        if (UnityEngine.Random.Range(0f, 1f) > chanceOnGrass * elevationScale * climateScale)
                        {
                            continue;
                        }
                    }
                    else if (sample.record == 3)
                    {
                        // Stone
                        if (UnityEngine.Random.Range(0f, 1f) > chanceOnStone * elevationScale * climateScale)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        // Anything else
                        continue;
                    }

                    // Sample height and position billboard
                    Vector3 pos    = new Vector3(x * scale, 0, y * scale);
                    float   height = terrain.SampleHeight(pos + terrain.transform.position);
                    pos.y = height;

                    // Reject if too close to water
                    float beachLine = DaggerfallUnity.Instance.TerrainSampler.BeachElevation * terrainScale;
                    if (height < beachLine)
                    {
                        continue;
                    }

                    // Add to batch
                    int record = UnityEngine.Random.Range(1, 32);
                    dfBillboardBatch.AddItem(record, pos);
                }
            }

            // Apply new batch
            dfBillboardBatch.Apply();
        }
 /// <summary>
 /// Set height value at coordinates.
 /// </summary>
 public static void SetHeight(ref WorldSample[] samples, int x, int y, float height)
 {
     samples[y * terrainSampleDim + x].scaledHeight = height;
 }
 /// <summary>
 /// Set clamped height value at coordinates.
 /// </summary>
 public static void SetClampedHeight(ref WorldSample[] samples, int x, int y, float height)
 {
     x = Mathf.Clamp(x, 0, terrainTileDim - 1);
     y = Mathf.Clamp(y, 0, terrainTileDim - 1);
     samples[y * terrainSampleDim + x].scaledHeight = height;
 }
 /// <summary>
 /// Gets sample data at coordinate.
 /// </summary>
 public static WorldSample GetSample(ref WorldSample[] samples, int x, int y)
 {
     return samples[y * terrainSampleDim + x];
 }
 /// <summary>
 /// Get height value at coordinates.
 /// </summary>
 public static float GetHeight(ref WorldSample[] samples, int x, int y)
 {
     return samples[y * terrainSampleDim + x].scaledHeight;
 }
 /// <summary>
 /// Get clamped height value at coordinates.
 /// </summary>
 public static float GetClampedHeight(ref WorldSample[] samples, int x, int y)
 {
     x = Mathf.Clamp(x, 0, terrainTileDim - 1);
     y = Mathf.Clamp(y, 0, terrainTileDim - 1);
     return samples[y * terrainSampleDim + x].scaledHeight;
 }