Exemple #1
0
        //public MapMagic.GeneratorsAsset mapMagicGens;
                #endif

        public void Generate(Data.Area area, Func <float, bool> stop = null)
        {
            if (area.pinned)
            {
                return;
            }
            change = false;
            if (stop != null && stop(0))
            {
                return;
            }

            //special case for preserving a demo scene on generator change
//			if (area.coord.x==0 && area.coord.z==0) return;
            Data.Area savedArea = null;
            if (leaveDemoUntouched && area.coord.x == 0 && area.coord.z == 0)
            {
                savedArea = (Data.Area)area.Clone();
            }

            if (generatorType == GeneratorType.Planar)
            {
                area.ClearLand();
                area.ClearObjects();
                area.ClearGrass();

                Matrix matrix = new Matrix(area.rect);
                planarGen.Generate(matrix, stop);

                area.AddLayer(matrix, planarGen.blockType, heightFactor: 1, noise: null);
            }

            if (generatorType == GeneratorType.Noise)
            {
                area.ClearLand();
                area.ClearObjects();
                area.ClearGrass();

                Noise noise = new Noise(123, permutationCount: 512);                //random to floor floats

                Matrix noiseMatrix = new Matrix(area.rect);

                if (stop != null && stop(0))
                {
                    return;
                }
                if (noiseGen.enabled)
                {
                    noiseGen.Generate(noiseMatrix, seed, stop);
                }

                if (stop != null && stop(0))
                {
                    return;
                }
                if (curveGen.enabled)
                {
                    curveGen.Generate(noiseMatrix, stop);
                }

                if (stop != null && stop(0))
                {
                    return;
                }
                area.AddLayer(noiseMatrix, noiseGen.blockType, heightFactor: heightFactor, noise: noise);              //TODO: set block types instead of magical numbers

                if (slopeGen.enabled)
                {
                    if (stop != null && stop(0))
                    {
                        return;
                    }
                    Matrix slopeMatrix = slopeGen.Generate(noiseMatrix, stop);
                    area.PaintLayer(slopeMatrix, slopeGen.blockType, noise: noise, paintThickness: slopeGen.thickness);
                }

                if (cavityGen.enabled)
                {
                    if (stop != null && stop(0))
                    {
                        return;
                    }
                    Matrix cavityMatrix = cavityGen.Generate(noiseMatrix, stop);
                    area.PaintLayer(cavityMatrix, cavityGen.blockType, noise: noise, paintThickness: cavityGen.thickness);
                }

                Matrix blurMatrix;
                if (blurGen.enabled)
                {
                    if (stop != null && stop(0))
                    {
                        return;
                    }
                    blurMatrix = blurGen.Generate(noiseMatrix, stop);
                    blurMatrix.Max(noiseMatrix);
                    area.ClampAppendLayer(blurMatrix, blurGen.blockType, noise: noise, heightFactor: heightFactor);
                }
                else
                {
                    blurMatrix = noiseMatrix;
                }

                if (stainsGen.enabled)
                {
                    Matrix matrix = area.GetSoilMatrix(stainsGen.soilOpacity);
                    //Matrix stains = new Matrix(area.rect);

                    stainsGen.Generate(matrix, seed, stop);
                    area.PaintLayer(matrix, stainsGen.blockType, noise: noise, paintThickness: stainsGen.thickness);
                }

                if (noiseGenB.enabled)
                {
                    Matrix matrix = new Matrix(area.rect);
                    noiseGenB.Generate(matrix, seed, stop);
                    area.SetLayer(matrix, null, noiseGenB.blockType, heightFactor: heightFactor, noise: noise);
                }

                if (scatterGen.enabled)
                {
                    if (stop != null && stop(0))
                    {
                        return;
                    }

                    SpatialHash spatialHash = new SpatialHash(new Vector2(area.rect.offset.x, area.rect.offset.z), area.rect.size.x, 16);

                    Matrix soil = area.GetSoilMatrix(scatterGen.soilOpacity);

                    scatterGen.Generate(spatialHash, seed, soil);

                    foreach (SpatialObject obj in spatialHash.AllObjs())
                    {
                        int x = (int)(obj.pos.x + 0.5f);
                        int z = (int)(obj.pos.y + 0.5f);
                        int y = (int)((obj.height + blurMatrix[x, z]) * heightFactor);
                        area.AddObject(new CoordDir(x, y, z), (short)scatterGen.blockType);
                    }
                }

                for (int g = 0; g < grassGens.gens.Length; g++)
                {
                    GrassGenerator grassGen = grassGens.gens[g];
                    //if (grassGen.enabled)
                    {
                        if (stop != null && stop(0))
                        {
                            return;
                        }

                        Matrix grassMatrix = area.GetSoilMatrix(grassGen.soilOpacity);

                        grassGen.Generate(grassMatrix, seed);

                        area.SetGrassLayer(grassMatrix, (byte)grassGen.grassType, 1, noise);
                    }
                }
            }

            else if (generatorType == GeneratorType.Heightmap)
            {
                area.ClearLand();
                area.ClearObjects();
                area.ClearGrass();

                Noise noise = new Noise(123, permutationCount: 512);                //random to floor floats

                Matrix matrix = new Matrix(area.rect);

                if (stop != null && stop(0))
                {
                    return;
                }
                if (standaloneHeightGen.enabled)
                {
                    standaloneHeightGen.Generate(matrix, seed, stop);
                }
                area.AddLayer(matrix, noiseGen.blockType, heightFactor: heightFactor, noise: noise);               //TODO: set block types instead of magical numbers
            }

            else if (generatorType == GeneratorType.MapMagic)
            {
                                #if MAPMAGIC
                if (stop != null && stop(0))
                {
                    return;
                }
                if (area.results == null)
                {
                    area.results = new MapMagic.Chunk.Results();
                }
                //MapMagic.Chunk.Size size = new MapMagic.Chunk.Size(area.rect.size.x,area.rect.size.x,heightFactor);

                if (stop != null && stop(0))
                {
                    return;
                }
                if (mapMagicGens != null)
                {
                    //mapMagicGens.Calculate(area.rect.offset.x, area.rect.offset.z, area.rect.size.x, area.results,  new MapMagic.Chunk.Size(area.rect.size.x,area.rect.size.x,heightFactor), seed, stop);
                    mapMagicGens.Generate(area.results, area.rect.offset.x, area.rect.offset.z, area.rect.size.x, area.rect.size.x, heightFactor, seed, stop);
                }
                else
                {
                    area.ClearLand(); area.ClearObjects(); area.ClearGrass();
                }
                                #else
                area.ClearLand(); area.ClearObjects(); area.ClearGrass();
                                #endif
            }

            if (stop != null && stop(0))
            {
                return;
            }
            if (removeThinLayers)
            {
                area.RemoveThinLayers(minLayerThickness);
            }

            if (stop != null && stop(0))
            {
                return;
            }
            if (polish)
            {
                area.Polish();
            }

            //special case for preserving a demo scene on generator change
            if (leaveDemoUntouched && area.coord.x == 0 && area.coord.z == 0)
            {
                Matrix mask = new Matrix(new CoordRect(0, 0, area.lines.Length, area.lines.Length));
                for (int x = 0; x < mask.rect.size.x; x++)
                {
                    for (int z = 0; z < mask.rect.size.z; z++)
                    {
                        int distFromEdge = Mathf.Min(x, mask.rect.size.x - x, z, mask.rect.size.z - z);
                        mask[x, z] = Mathf.Clamp01(distFromEdge / 50f);
                    }
                }

                Matrix maskInverted = (Matrix)mask.Clone(); maskInverted.InvertOne();

                area.MixAreas(new Data.Area[] { (Data.Area)area.Clone(), savedArea }, new Matrix[] { maskInverted, mask });
                area.objects = savedArea.objects;
            }

            //area.generated = true;
            //area.serializable = true;
        }
Exemple #2
0
        private void GenerateSurface(ref DataChunk chunk, Point3 pos)
        {
            int    x, z, position, maxY, curY;
            double y, fX, terrainRange, treeChance;

            for (ushort xz = 0; xz < 16 * 16; xz++)
            {
                x  = (xz & 0x00F);
                z  = (xz & 0x0F0) / 0x10;
                x += pos.X * 0x10;
                z += pos.Z * 0x10;

                terrainRange = TerrainRangeGenerator.Generate(x, z);
                // Roughen up the surface a little 10%
                y = .9 + HeightRoughner.Generate(x, z) * .1;
                if (terrainRange >= .5)
                {
                    #region Above sealevel
                    y *= HeightGenerator.Generate(x, z);

                    // Apply the TerrainRange noise
                    y *= (terrainRange - .5) * 2;

                    // Apply the max height
                    y *= MaxMountainHight - MinSurfaceHeight;

                    // This is were we seperate the mountains from the hills
                    // .5(x+4(x-.5)^3+.5)
                    fX  = y / (MaxMountainHight - MinSurfaceHeight);
                    fX  = fX + (4 * ((fX - .5) * (fX - .5) * (fX - .5)) + .5);
                    fX /= 2;
                    y  *= fX;

                    // Apply the min height
                    y += MinSurfaceHeight;

                    // Round it and apply chunk height
                    y    = Math.Ceiling(y);
                    maxY = (int)y;
                    y   -= pos.Y * 0x10;

                    // Ceiling check
                    if (y > 0xF)
                    {
                        y = 0xF;
                    }
                    // Air check
                    if (y < 0)
                    {
                        continue;
                    }

                    y       *= 0x100;
                    position = xz + (int)y;

                    // Surface block
                    curY = (int)(pos.Y * 0x10 + y / 0x100);

                    if (maxY - curY == 0)
                    {
                        if (SurfaceEnd == pos.Y)
                        {
                            treeChance = 0;
                        }
                        else
                        {
                            treeChance  = TreeGenerator.Generate(x, z);
                            treeChance *= Math.Round((terrainRange - .5) * 40 > 1 ? 1 : (terrainRange - .5) * 40, 1);
                            treeChance  = Math.Round(treeChance, 1);
                        }
                        chunk.Blocks[position] = new DataBlock()
                        {
                            Material = treeChance < 1 ? MaterialType.Grass : MaterialType.Stone,
                            Position = (ushort)position
                        };
                    }
                    else
                    {
                        chunk.Blocks[position] = new DataBlock()
                        {
                            Material = maxY - curY <= 3 ? MaterialType.Dirt : MaterialType.Stone,
                            Position = (ushort)position
                        };
                    }

                    // Non-surface blocks
                    while (y >= 0x100)
                    {
                        y       -= 0x100;
                        curY     = (int)(pos.Y * 0x10 + y / 0x100);
                        position = xz + (int)y;
                        chunk.Blocks[position] = new DataBlock()
                        {
                            Material = maxY - curY <= 3 ? MaterialType.Dirt : MaterialType.Stone,
                            Position = (ushort)position
                        };
                    }
                    #endregion
                }
                else if (terrainRange >= .475)
                {
                    #region Beach
                    // Apply the TerrainRange noise
                    y *= 1 - (.5 - terrainRange) * 40;

                    // Apply the min height (which is basically the max height for beaches)
                    y *= MinSurfaceHeight + 1;

                    // Round it and apply chunk height
                    y    = Math.Ceiling(y);
                    maxY = (int)y;
                    y   -= pos.Y * 0x10;

                    // Ceiling check
                    if (y > 0xF)
                    {
                        y = 0xF;
                    }
                    // Air check
                    if (y < 0)
                    {
                        continue;
                    }

                    y *= 0x100;
                    // Surface block
                    position = xz + (int)y;
                    chunk.Blocks[position] = new DataBlock()
                    {
                        Material = MaterialType.Sand,
                        Position = (ushort)position
                    };
                    // Non-surface blocks
                    while (y >= 0x100)
                    {
                        y       -= 0x100;
                        curY     = (int)(pos.Y * 0x10 + y / 0x100);
                        position = xz + (int)y;
                        chunk.Blocks[position] = new DataBlock()
                        {
                            Material = MaterialType.Sand,
                            Position = (ushort)position
                        };
                    }
                    #endregion
                }
                else // terrainRange < .475
                {
                    #region Ocean
                    // TODO: Water

                    // Apply the TerrainRange noise
                    y *= (.475 - terrainRange) * (1 / .475);

                    // Apply the max depth
                    y *= MaxOceanDepth;

                    // Round it and apply chunk height
                    y    = Math.Ceiling(y);
                    maxY = (int)y;
                    y   -= pos.Y * 0x10;

                    // Ceiling check
                    if (y > 0xF)
                    {
                        y = 0xF;
                    }
                    // Air check
                    if (y < 0)
                    {
                        continue;
                    }

                    y *= 0x100;
                    // Surface block
                    position = xz + (int)y;
                    chunk.Blocks[position] = new DataBlock()
                    {
                        Material = MaterialType.Stone,
                        Position = (ushort)position
                    };
                    // Non-surface blocks
                    while (y >= 0x100)
                    {
                        y       -= 0x100;
                        curY     = (int)(pos.Y * 0x10 + y / 0x100);
                        position = xz + (int)y;
                        chunk.Blocks[position] = new DataBlock()
                        {
                            Material = MaterialType.Stone,
                            Position = (ushort)position
                        };
                    }
                    #endregion
                }
            }
        }