コード例 #1
0
    private List <SectionCoord> SectionsInRadius(SectionCoord coord, float radius)
    {
        int dist = Mathf.CeilToInt(radius * 2 + 1);
        List <SectionCoord> sections = new List <SectionCoord>(dist * dist);

        int x, z, dir;

        x   = z = 0;
        dir = dist = 1;

        while (dist <= 2 * radius + 1)
        {
            while (2 * x * dir < dist)
            {
                if (x * x + z * z < radius * radius + 1)
                {
                    sections.Add(new SectionCoord(coord.x + x, coord.z + z));
                }
                x += dir;
            }
            while (2 * z * dir < dist)
            {
                if (x * x + z * z < radius * radius + 1)
                {
                    sections.Add(new SectionCoord(coord.x + x, coord.z + z));
                }
                z += dir;
            }
            dir *= -1;
            dist++;
        }

        return(sections);
    }
コード例 #2
0
    private BiomeCenter GenerateBiomeCenter(SectionCoord coord)
    {
        BiomeCenter center = new BiomeCenter();

        center.coord = coord;
        NotRandom.RNG rng = new NotRandom.RNG(NotRandom.Hash2Int(seedHash,
                                                                 center.coord.GetHashCode()));

        float nx = center.coord.x * biomeCenterSpacing + ((rng.Value() *
                                                           maxBiomeCenterOffset * 2) - maxBiomeCenterOffset);
        float nz = center.coord.z * biomeCenterSpacing + ((rng.Value() *
                                                           maxBiomeCenterOffset * 2) - maxBiomeCenterOffset);

        center.center = new Vector3(nx, 1f, nz);

        int index = (int)(rng.ValueUInt() % totalBiomeFrequency);

        for (int i = 0; i < biomes.Count; i++)
        {
            if (index >= 0 && index < biomes[i].relativeFrequency)
            {
                center.biome = biomes[i];
                break;
            }
            index -= biomes[i].relativeFrequency;
        }
        return(center);
    }
コード例 #3
0
    private float[,,] GenerateAlphamaps(SectionCoord coord,
                                        out List <Biome> containedBiomes)
    {
        List <float[, ]> alphamapList = new List <float[, ]>();

        containedBiomes = new List <Biome>();
        Biome b;
        List <BiomeStrength> locBiomes;

        float[,] alphamap;

        float nx, nz;

        for (int x = 0; x < genSettings.alphaMapRes; x++)
        {
            for (int z = 0; z < genSettings.alphaMapRes; z++)
            {
                nx  = coord.x - 0.5f + (float)x / (genSettings.alphaMapRes - 1);
                nz  = coord.z - 0.5f + (float)z / (genSettings.alphaMapRes - 1);
                nx *= genSettings.length;
                nz *= genSettings.length;

                locBiomes = GetBiomes(new Vector3(nx, 0f, nz));
                for (int i = 0; i < locBiomes.Count; i++)
                {
                    b = locBiomes[i].biome;
                    if (b == null)
                    {
                        continue;
                    }
                    if (!containedBiomes.Contains(b))
                    {
                        containedBiomes.Add(b);
                        alphamapList.Add(new float[genSettings.alphaMapRes,
                                                   genSettings.alphaMapRes]);
                    }
                    alphamapList[containedBiomes.IndexOf(b)][z, x] =
                        locBiomes[i].strength;
                }
            }
        }
        float[,,] alphamaps = new float[genSettings.alphaMapRes,
                                        genSettings.alphaMapRes, containedBiomes.Count];

        for (int i = 0; i < containedBiomes.Count; i++)
        {
            alphamap = alphamapList[i];
            for (int x = 0; x < genSettings.alphaMapRes; x++)
            {
                for (int z = 0; z < genSettings.alphaMapRes; z++)
                {
                    alphamaps[x, z, i] = alphamap[x, z];
                }
            }
        }

        return(alphamaps);
    }
コード例 #4
0
        public override bool Equals(object obj)
        {
            if (!(obj is SectionCoord))
            {
                return(false);
            }
            SectionCoord other = (SectionCoord)obj;

            return(other.x == x && other.z == z);
        }
コード例 #5
0
    private void CalculateBiomeBounds(SectionCoord coord)
    {
        BiomeCenter target = SafeGetBiomeCenter(coord);

        if (target.boundsCalculated)
        {
            return;
        }

        List <BiomeCenter>  neighbors = new List <BiomeCenter>();
        List <SectionCoord> coords;
        Dictionary <SectionCoord, Plane> properBounds =
            new Dictionary <SectionCoord, Plane>();
        List <Plane> weakBounds = new List <Plane>();
        Plane        plane;
        Vector3      self = target.center;
        Vector3      other, middle;

        coords = SectionsInRadius(coord, 2.75f);

        for (int i = 1; i < coords.Count; i++)
        {
            neighbors.Add(SafeGetBiomeCenter(coords[i]));
        }

        for (int i = 0; i < neighbors.Count; i++)
        {
            other  = neighbors[i].center;
            middle = (self + other) / 2f;
            if (neighbors[i].boundsCalculated)
            {
                plane = neighbors[i].properBounds[coord].flipped;
                properBounds.Add(neighbors[i].coord, plane);
            }
            else
            {
                plane = new Plane((self - other).normalized, middle);
                properBounds.Add(neighbors[i].coord, plane);
            }
            weakBounds.Add(new Plane(plane.normal,
                                     middle - plane.normal * (biomeBlend / 2f)));
        }
        SimplifyConvexPlanes(weakBounds, self);
        lock (target)
        {
            if (!target.boundsCalculated)
            {
                target.properBounds     = properBounds;
                target.weakBounds       = weakBounds;
                target.boundsCalculated = true;
            }
        }
    }
コード例 #6
0
    private float[,] GenerateHeightmap(SectionCoord coord)
    {
        float[,] heightmap = new float[genSettings.heightMapRes,
                                       genSettings.heightMapRes];
        Biome b;
        float height, weight, nx, nz, bx, bz, totalHeight, totalWeight;
        List <BiomeStrength> biomes;

        for (int x = 0; x < genSettings.heightMapRes; x++)
        {
            for (int z = 0; z < genSettings.heightMapRes; z++)
            {
                nx          = coord.x - 0.5f + (float)x / (genSettings.heightMapRes - 1);
                nz          = coord.z - 0.5f + (float)z / (genSettings.heightMapRes - 1);
                bx          = nx * genSettings.length;
                bz          = nz * genSettings.length;
                nx         *= genSettings.length / noiseScale;
                nz         *= genSettings.length / noiseScale;
                biomes      = GetBiomes(new Vector3(bx, 0f, bz));
                totalHeight = 0f;
                totalWeight = 0f;
                for (int i = 0; i < biomes.Count; i++)
                {
                    b = biomes[i].biome;
                    if (b == null)
                    {
                        continue;
                    }
                    weight       = biomes[i].strength;
                    totalWeight += weight;

                    height = 0f;
                    for (int j = 0; j < b.heightmapOctaves; j++)
                    {
                        height += Mathf.Pow(2f, -j) * Mathf.PerlinNoise(
                            nx * Mathf.Pow(2, j) + offsets[j, 0],
                            nz * Mathf.Pow(2, j) + offsets[j, 1]);
                    }
                    height /= (2f - Mathf.Pow(2, -(b.heightmapOctaves - 1)));
                    height  = Mathf.Pow(height, b.heightExponent);
                    height  = height * (b.maxHeight - b.minHeight) + b.minHeight;

                    totalHeight += height * weight;
                }

                heightmap[z, x] = totalHeight / totalWeight;
            }
        }

        return(heightmap);
    }
コード例 #7
0
    public float TerrainHeightAt(Vector3 vLoc)
    {
        SectionCoord coord = SectionFor(vLoc);

        if (!SectionExists(coord))
        {
            return(Mathf.NegativeInfinity);
        }
        TerrainSection sec = terrains[coord];

        if (sec == null || sec.terrain == null)
        {
            return(Mathf.NegativeInfinity);
        }
        return(sec.terrain.SampleHeight(vLoc) + sec.terrain.GetPosition().y);
    }
コード例 #8
0
 private IEnumerator Remove_CR()
 {
     while (toRemove.Count > 0)
     {
         for (int i = 0; i < maxSimultaneousGens && toRemove.Count > 0; i++)
         {
             SectionCoord   coord = toRemove.Dequeue();
             TerrainSection sec   = terrains[coord];
             if (sec != null && sec.terrain != null)
             {
                 Destroy(sec.terrain.gameObject);
                 terrains.Remove(coord);
             }
         }
         yield return(null);
     }
     removeRunning = false;
 }
コード例 #9
0
    private BiomeCenter SafeGetBiomeCenter(SectionCoord coord)
    {
        BiomeCenter bc, test;

        if (!biomeCenters.TryGetValue(coord, out bc))
        {
            bc = GenerateBiomeCenter(coord);
            lock (biomeCenters)
            {
                if (!biomeCenters.TryGetValue(coord, out test))
                {
                    biomeCenters.Add(coord, bc);
                }
                else
                {
                    bc = test;
                }
            }
        }

        return(bc);
    }
コード例 #10
0
 private IEnumerator Create_CR()
 {
     while (toCreate.Count > 0)
     {
         while (((!detectMaxSimultaneousGens && numGenThreads <
                  maxSimultaneousGens) || (detectMaxSimultaneousGens &&
                                           numGenThreads < (SystemInfo.processorCount / 2 + 1))) &&
                toCreate.Count > 0)
         {
             numGenThreads++;
             SectionCoord coord = toCreate.Dequeue();
             StartCoroutine(GenerateSection_CR(coord));
             generating.Add(coord);
             yield return(null);
         }
         yield return(new WaitUntil(() => (!detectMaxSimultaneousGens &&
                                           numGenThreads < maxSimultaneousGens) ||
                                    (detectMaxSimultaneousGens && numGenThreads <
                                     (SystemInfo.processorCount / 2 + 1))));
     }
     createRunning = false;
 }
コード例 #11
0
    public List <BiomeStrength> GetBiomes(Vector3 vLoc)
    {
        List <BiomeStrength> output = new List <BiomeStrength>(biomes.Count);

        Vector3      loc      = new Vector3(vLoc.x, 0f, vLoc.z);
        Vector3      biomeLoc = loc / biomeCenterSpacing;
        SectionCoord coord    = new SectionCoord(Mathf.RoundToInt(biomeLoc.x),
                                                 Mathf.RoundToInt(biomeLoc.z));

        BiomeCenter center = SafeGetBiomeCenter(coord);
        float       weakDist, dist, totalStrength;

        if (!center.boundsCalculated)
        {
            CalculateBiomeBounds(coord);
        }

        weakDist = Mathf.Infinity;

        for (int k = 0; weakDist > biomeBlend &&
             k < center.weakBounds.Count; k++)
        {
            dist = center.weakBounds[k].GetDistanceToPoint(loc);
            if (dist < weakDist)
            {
                weakDist = dist;
            }
        }
        if (weakDist > biomeBlend)
        {
            output.Add(new BiomeStrength(center.biome, 1f));
            return(output);
        }

        List <SectionCoord> coords = SectionsInRadius(coord, 2.75f);

        for (int i = 0; i < coords.Count; i++)
        {
            center = SafeGetBiomeCenter(coords[i]);
            if (!center.boundsCalculated)
            {
                CalculateBiomeBounds(coords[i]);
            }

            weakDist = Mathf.Infinity;

            for (int k = 0; weakDist >= 0.0f &&
                 k < center.weakBounds.Count; k++)
            {
                dist = center.weakBounds[k].GetDistanceToPoint(loc);
                if (dist < weakDist)
                {
                    weakDist = dist;
                }
            }
            if (weakDist > biomeBlend)
            {
                output.Clear();
                output.Add(new BiomeStrength(center.biome, 1f));
                return(output);
            }
            if (weakDist >= 0.0f)
            {
                int j = 0;
                for (; j < output.Count; j++)
                {
                    if (output[j].biome == center.biome)
                    {
                        output[j].strength += (weakDist / biomeBlend);
                        break;
                    }
                }
                if (j == output.Count)
                {
                    output.Add(new BiomeStrength(center.biome, weakDist / biomeBlend));
                }
            }
        }

        totalStrength = 0f;
        for (int i = 0; i < output.Count; i++)
        {
            output[i].strength =
                Mathf.Pow(Mathf.Clamp01(output[i].strength), 2f);
            totalStrength += output[i].strength;
        }
        for (int i = 0; i < output.Count; i++)
        {
            output[i].strength /= totalStrength;
        }
        return(output);
    }
コード例 #12
0
 public TerrainSection(SectionCoord coord = new SectionCoord(), Terrain terrain = null)
 {
     this.coord   = coord;
     this.terrain = terrain;
 }
コード例 #13
0
    private IEnumerator GenerateSection_CR(SectionCoord coord)
    {
        TerrainSection sec;

        if (terrains.TryGetValue(coord, out sec) && sec != null &&
            sec.terrain != null)
        {
            if (numGenThreads > 0)
            {
                numGenThreads--;
            }
            yield break;
        }
        if (sec == null)
        {
            sec = new TerrainSection(coord);
        }

        float[,] heightmap  = null;
        float[,,] alphamaps = null;
        int                 bx, bz;
        float               height;
        Vector3             targLoc;
        GameObject          go;
        BiomeData           bd;
        List <SectionCoord> biomeCenters;

        List <Biome> containedBiomes = null;
        List <DetailPrototypeData> detailPrototypeDatas = null;
        List <int[, ]>             detailMaps           = null;
        List <TreePrototypeData>   treePrototypeDatas   = null;
        List <TreeInstance>        treeInstances        = null;

        Thread heightThread = new Thread(() =>
        {
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.BeginThreadProfiling(
                "Heightmap", "" + coord.x + ":" + coord.z);
#endif
            heightmap = GenerateHeightmap(coord);
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.EndThreadProfiling();
#endif
        });
        Thread alphaThread = new Thread(() =>
        {
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.BeginThreadProfiling(
                "Alphamap", "" + coord.x + ":" + coord.z);
#endif
            alphamaps = GenerateAlphamaps(coord, out containedBiomes);
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.EndThreadProfiling();
#endif
        });
        Thread detailThread = new Thread(() =>
        {
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.BeginThreadProfiling(
                "Detailmap", "" + coord.x + ":" + coord.z);
#endif
            detailMaps = GenerateDetailMaps(coord,
                                            out detailPrototypeDatas);
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.EndThreadProfiling();
#endif
        });
        Thread treeThread = new Thread(() =>
        {
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.BeginThreadProfiling(
                "Treemap", "" + coord.x + ":" + coord.z);
#endif
            treeInstances = GenerateTreeInstances(coord,
                                                  out treePrototypeDatas);
#if DEBUG_THREADS
            UnityEngine.Profiling.Profiler.EndThreadProfiling();
#endif
        });

        yield return(null);

        treeThread.Start();
        yield return(null);

        heightThread.Start();
        yield return(null);

        alphaThread.Start();
        yield return(null);

        detailThread.Start();
        yield return(new WaitUntil(() => (heightmap != null &&
                                          alphamaps != null && detailMaps != null &&
                                          treeInstances != null && !loadingSection)));

        TerrainLayer[] terrainLayers = new TerrainLayer[containedBiomes.Count];
        loadingSection = true;
        sectionLoading = coord;

        TerrainData data = new TerrainData();

        data.heightmapResolution = genSettings.heightMapRes;
        yield return(null);

        data.alphamapResolution = genSettings.alphaMapRes;
        data.SetDetailResolution(genSettings.detailMapRes,
                                 genSettings.detailMapResPerPatch);
        data.size = new Vector3(genSettings.length, genSettings.height,
                                genSettings.length);
        yield return(null);

        data.SetHeights(0, 0, heightmap);
        yield return(null);

        for (int i = 0; i < containedBiomes.Count; i++)
        {
            terrainLayers[i] = containedBiomes[i].terrainLayer;
        }

        DetailPrototype[] detailPrototypes = null;
        if (detailPrototypeDatas.Count > 0)
        {
            detailPrototypes = new DetailPrototype[detailPrototypeDatas.Count];
        }
        for (int i = 0; i < detailPrototypeDatas.Count; i++)
        {
            DetailPrototype     dp  = detailPrototypes[i] = new DetailPrototype();
            DetailPrototypeData dpd = detailPrototypeDatas[i];
            dp.bendFactor   = dpd.bendFactor;
            dp.dryColor     = dpd.dryColor;
            dp.healthyColor = dpd.healthyColor;
            dp.maxHeight    = dpd.maxHeight;
            dp.maxWidth     = dpd.maxWidth;
            dp.minHeight    = dpd.minHeight;
            dp.minWidth     = dpd.minWidth;
            dp.noiseSpread  = dpd.noiseSpread;
            if (dpd.prototype != null)
            {
                dp.prototype        = dpd.prototype;
                dp.usePrototypeMesh = true;
            }
            else
            {
                dp.prototypeTexture = dpd.prototypeTexture;
                dp.usePrototypeMesh = false;
            }
            dp.renderMode = dpd.renderMode;
        }
        yield return(null);

        data.terrainLayers = terrainLayers;
        data.SetAlphamaps(0, 0, alphamaps);
        yield return(null);

        TreePrototype[] treePrototypes = null;
        if (treePrototypeDatas.Count > 0)
        {
            treePrototypes = new TreePrototype[treePrototypeDatas.Count];
        }
        for (int i = 0; i < treePrototypeDatas.Count; i++)
        {
            TreePrototype tp = treePrototypes[i] = new TreePrototype();
            tp.bendFactor = treePrototypeDatas[i].bendFactor;
            tp.prefab     = treePrototypeDatas[i].prefab;
        }
        yield return(null);

        if (detailPrototypes != null)
        {
            data.detailPrototypes = detailPrototypes;
            yield return(null);

            for (int i = 0; i < detailMaps.Count; i++)
            {
                data.SetDetailLayer(0, 0, i, detailMaps[i]);
            }
            yield return(null);
        }
        if (treePrototypes != null)
        {
            data.treePrototypes = treePrototypes;
            yield return(null);

            data.SetTreeInstances(treeInstances.ToArray(), true);
        }
        yield return(null);

        data.RefreshPrototypes();

        yield return(null);

        GameObject obj = Terrain.CreateTerrainGameObject(data);

        sec.terrain = obj.GetComponent <Terrain>();

        sec.terrain.treeBillboardDistance = 150;
        sec.terrain.materialTemplate      = terrainMaterial;

        sec.terrain.allowAutoConnect = true;
        obj.transform.position       = new Vector3(coord.x * genSettings.length -
                                                   genSettings.length / 2, 0f, coord.z * genSettings.length -
                                                   genSettings.length / 2);
        yield return(null);

        sec.terrain.Flush();
        yield return(null);

        bx = Mathf.RoundToInt((coord.x * genSettings.length) /
                              biomeCenterSpacing);
        bz = Mathf.RoundToInt((coord.z * genSettings.length) /
                              biomeCenterSpacing);
        biomeCenters = SectionsInRadius(new SectionCoord(bx, bx), 2);
        for (int i = 0; i < biomeCenters.Count; i++)
        {
            BiomeCenter center = SafeGetBiomeCenter(biomeCenters[i]);
            height  = sec.terrain.SampleHeight(center.center);
            targLoc = new Vector3(center.center.x, height, center.center.z +
                                  sec.terrain.GetPosition().y);
            if (sec.terrain.terrainData.bounds.Contains(targLoc -
                                                        sec.terrain.transform.position))
            {
                if (center.biome.ambientPrefab != null)
                {
                    go = Instantiate(center.biome.ambientPrefab, targLoc,
                                     Quaternion.identity, sec.terrain.transform);
                }
                else
                {
                    go = new GameObject();
                    go.transform.position = targLoc;
                    go.transform.parent   = sec.terrain.transform;
                }
                bd            = go.AddComponent <TerrainManager.BiomeData>();
                bd.biome      = center.biome;
                bd.center     = targLoc;
                bd.boundaries = center.properBounds.Values.ToList();
                SimplifyConvexPlanes(bd.boundaries, bd.center);
            }
        }

        yield return(null);

        terrains.Add(coord, sec);
        if (numGenThreads > 0)
        {
            numGenThreads--;
        }
        generating.Remove(coord);
        if (coord.Equals(sectionLoading))
        {
            loadingSection = false;
        }
    }
コード例 #14
0
 private bool SectionExists(SectionCoord coord)
 {
     return(terrains.ContainsKey(coord) && terrains[coord].terrain != null &&
            !toRemove.Contains(coord));
 }
コード例 #15
0
    private List <TreeInstance> GenerateTreeInstances(SectionCoord coord,
                                                      out List <TreePrototypeData> treePrototypes)
    {
        treePrototypes = new List <TreePrototypeData>();
        List <TreeInstance> treeInstances = new List <TreeInstance>();

        float cellSize = minTreeDistance / Mathf.Sqrt(2);
        int   numCells = Mathf.CeilToInt(genSettings.length / cellSize);

        int unprocessed = -1;
        int noTree      = -2;

        int[,] trees      = new int[numCells, numCells];
        Vector3[,] points = new Vector3[numCells, numCells];

        NotRandom.RNG rng = new NotRandom.RNG(NotRandom.Hash2Int(seedHash,
                                                                 coord.GetHashCode()));

        List <Vector3>           toProcess = new List <Vector3>();
        List <Vector3>           processed = new List <Vector3>();
        List <Vector3>           selected = new List <Vector3>();
        List <TreePrototypeData> selectedTree = new List <TreePrototypeData>();
        Vector3 test, next;
        List <BiomeStrength> biomes;
        Biome b = null;
        int   p, ax, az, anx, anz, annx, annz, range, tree, totalTreeFreq;
        int   maxX, maxZ, maxRange;
        float bx, bz, a, r, str;
        bool  canTree;

        next = new Vector3(rng.Value() * (genSettings.length -
                                          minBorderTreeDistance * 2) + minBorderTreeDistance, 0f,
                           rng.Value() * (genSettings.length -
                                          minBorderTreeDistance * 2) + minBorderTreeDistance);
        anx              = Mathf.FloorToInt(next.x / cellSize);
        anz              = Mathf.FloorToInt(next.z / cellSize);
        maxRange         = Mathf.CeilToInt(maxMinTreeDistance / cellSize);
        range            = Mathf.CeilToInt(minTreeDistance / cellSize);
        trees[anx, anz]  = unprocessed;
        points[anx, anz] = next;
        toProcess.Add(next);

        while (toProcess.Count > 0)
        {
            p    = (int)(rng.ValueUInt() % toProcess.Count);
            test = toProcess[p];
            toProcess.RemoveAt(p);
            ax = Mathf.FloorToInt(test.x / cellSize);
            az = Mathf.FloorToInt(test.z / cellSize);

            canTree = true;
            maxX    = Mathf.Min(maxRange, numCells - 1 - ax);
            maxZ    = Mathf.Min(maxRange, numCells - 1 - az);
            for (int x = Mathf.Max(-maxRange, -ax); canTree && x <= maxX; x++)
            {
                for (int z = Mathf.Max(-maxRange, -az); canTree && z <= maxZ; z++)
                {
                    anx  = ax + x;
                    anz  = az + z;
                    tree = trees[anx, anz];
                    if (tree > 0 && Vector3.Distance(test, points[anx, anz]) <
                        selectedTree[tree - 1].minDistance)
                    {
                        canTree = false;
                    }
                }
            }

            if (canTree)
            {
                bx     = (coord.x - 0.5f) * genSettings.length + test.x;
                bz     = (coord.z - 0.5f) * genSettings.length + test.z;
                biomes = GetBiomes(new Vector3(bx, 0f, bz));
                if (biomes.Count == 1)
                {
                    b   = biomes[0].biome;
                    str = biomes[0].strength;
                }
                else
                {
                    b   = null;
                    str = 0f;
                    for (int i = 0; i < biomes.Count; i++)
                    {
                        if (b == null)
                        {
                            b   = biomes[i].biome;
                            str = biomes[i].strength;
                        }
                        else
                        {
                            if (biomes[i].strength > str)
                            {
                                b   = biomes[i].biome;
                                str = biomes[i].strength;
                            }
                        }
                    }
                }
                if (str < minBiomeTreeStrength || b == null ||
                    b.treePrototypes == null ||
                    b.treePrototypes.Count == 0)
                {
                    canTree = false;
                }
            }
            if (canTree && b != null)
            {
                totalTreeFreq = 0;
                for (int i = 0; i < b.treePrototypes.Count; i++)
                {
                    totalTreeFreq += b.treePrototypes[i].relativeFrequency;
                }
                int index = (int)(rng.ValueUInt() % totalTreeFreq);

                for (int i = 0; i < b.treePrototypes.Count; i++)
                {
                    if (index >= 0 && index < b.treePrototypes[i].relativeFrequency)
                    {
                        selectedTree.Add(b.treePrototypes[i]);
                        selected.Add(test);
                        trees[ax, az] = selectedTree.Count;
                        break;
                    }
                    index -= b.treePrototypes[i].relativeFrequency;
                }
            }
            for (int i = 0; i < treeTestPoints; i++)
            {
                a = rng.Value();
                r = rng.Value();
                r = r * minTreeDistance + minTreeDistance;

                next = new Vector3(test.x + r * Mathf.Cos(a * 2 * Mathf.PI),
                                   0f, test.z + r * Mathf.Sin(a * 2 * Mathf.PI));
                if (next.x < minBorderTreeDistance ||
                    next.z < minBorderTreeDistance ||
                    next.x > genSettings.length - minBorderTreeDistance ||
                    next.z > genSettings.length - minBorderTreeDistance)
                {
                    continue;
                }
                anx = Mathf.FloorToInt(next.x / cellSize);
                anz = Mathf.FloorToInt(next.z / cellSize);
                if (trees[anx, anz] != 0)
                {
                    continue;
                }
                canTree = true;
                maxX    = Mathf.Min(range, numCells - 1 - anx);
                maxZ    = Mathf.Min(range, numCells - 1 - anz);
                for (int x = Mathf.Max(-range, -anx); canTree &&
                     x <= maxX; x++)
                {
                    for (int z = Mathf.Max(-range, -anz); canTree &&
                         z <= maxZ; z++)
                    {
                        annx = anx + x;
                        annz = anz + z;

                        if (trees[annx, annx] != 0 &&
                            Vector3.Distance(next, points[annx, annz]) <
                            minTreeDistance)
                        {
                            canTree = false;
                        }
                    }
                }
                if (canTree)
                {
                    toProcess.Add(next);
                    trees[anx, anz]  = unprocessed;
                    points[anx, anz] = next;
                }
            }
            processed.Add(test);
            if (trees[ax, az] < 1)
            {
                trees[ax, az] = noTree;
            }
        }
        TreeInstance      ti;
        TreePrototypeData tpd;

        for (int i = 0; i < selected.Count; i++)
        {
            tpd = selectedTree[i];
            if (!treePrototypes.Contains(tpd))
            {
                treePrototypes.Add(tpd);
            }
            ti                = new TreeInstance();
            ti.color          = tpd.color;
            ti.lightmapColor  = tpd.lightmapColor;
            ti.prototypeIndex = treePrototypes.IndexOf(tpd);
            ti.position       = selected[i] / genSettings.length;
            ti.heightScale    = rng.Value() * (tpd.maxHeightScale -
                                               tpd.minHeightScale) + tpd.minHeightScale;
            ti.widthScale = rng.Value() * (tpd.maxWidthScale -
                                           tpd.minWidthScale) + tpd.minWidthScale;
            ti.rotation = rng.Value() * 2 * Mathf.PI;

            treeInstances.Add(ti);
        }

        return(treeInstances);
    }
コード例 #16
0
    private List <int[, ]> GenerateDetailMaps(SectionCoord coord,
                                              out List <DetailPrototypeData> detailPrototypes)
    {
        List <int[, ]> detailmaps = new List <int[, ]>();

        detailPrototypes = new List <DetailPrototypeData>();

        float nx, nz, bx, bz, density;
        List <BiomeStrength> biomes = null;
        Biome b;
        DetailPrototypeData dpd;

        for (int x = 0; x < genSettings.detailMapRes; x++)
        {
            for (int z = 0; z < genSettings.detailMapRes; z++)
            {
                nx  = coord.x - 0.5f + (float)x / (genSettings.detailMapRes - 1);
                nz  = coord.z - 0.5f + (float)z / (genSettings.detailMapRes - 1);
                bx  = nx * genSettings.length;
                bz  = nz * genSettings.length;
                nx *= genSettings.length / detailNoiseScale;
                nz *= genSettings.length / detailNoiseScale;

                biomes = GetBiomes(new Vector3(bx, 0f, bz));

                for (int i = 0; i < biomes.Count; i++)
                {
                    b = biomes[i].biome;
                    if (b == null)
                    {
                        continue;
                    }
                    for (int j = 0; j < b.detailPrototypes.Count; j++)
                    {
                        dpd = b.detailPrototypes[j];
                        if (!detailPrototypes.Contains(dpd))
                        {
                            detailPrototypes.Add(dpd);
                            detailmaps.Add(new int[genSettings.detailMapRes,
                                                   genSettings.detailMapRes]);
                        }

                        density = 0f;
                        for (int k = 0; k < numDetailOctaves; k++)
                        {
                            density += Mathf.Pow(2f, -k) * Mathf.PerlinNoise(
                                nx * Mathf.Pow(2, k) + detailOffsets[k, 0],
                                nz * Mathf.Pow(2, k) + detailOffsets[k, 1]);
                        }
                        density /= (2f - Mathf.Pow(2,
                                                   -(numDetailOctaves - 1)));

                        detailmaps[detailPrototypes.IndexOf(dpd)][z, x] =
                            Mathf.FloorToInt(((density * (dpd.maxDensity -
                                                          dpd.minDensity)) + dpd.minDensity) *
                                             Mathf.Pow(biomes[i].strength, 2f));
                    }
                }
            }
        }

        return(detailmaps);
    }