Ejemplo n.º 1
0
 public void OpenGenerator()
 {
     CurrentModelIndex = 0;
     VoxelFilePath     = "";
     Data = VoxelData.CreateNewData();
     // Node Open
     if (Data)
     {
         foreach (var gp in Data.Groups)
         {
             if (!NodeOpen.ContainsKey(gp.Key))
             {
                 NodeOpen.Add(gp.Key, false);
             }
         }
     }
     // Switch Model
     SwitchModel(CurrentModelIndex);
     Load_Generation();
     DataDirty = false;
 }
Ejemplo n.º 2
0
 public void OpenCombiner()
 {
     CurrentModelIndex = 0;
     VoxelFilePath     = "";
     Data = VoxelData.CreateNewData();
     // Node Open
     if (Data)
     {
         foreach (var gp in Data.Groups)
         {
             if (!NodeOpen.ContainsKey(gp.Key))
             {
                 NodeOpen.Add(gp.Key, false);
             }
         }
     }
     SwitchModel(CurrentModelIndex);
     ClearScene();
     CombineList.Clear();
     SelectingPrefabIndex = -1;
     DataDirty            = false;
 }
Ejemplo n.º 3
0
        public static VoxelData Generate(Preset preset, System.Action <float, int> onProgress = null)
        {
            try {
                if (preset == null)
                {
                    return(VoxelData.CreateNewData());
                }

                var data = VoxelData.CreateNewData();
                data.Voxels = new List <int[, , ]> {
                };
                int sizeX  = preset.SizeX;
                int sizeY  = preset.SizeY;
                int height = Mathf.Max(
                    Mathf.CeilToInt(preset.GroundHeight.y),
                    Mathf.CeilToInt(preset.WaterHeight.y)
                    );
                var         voxels       = new int[sizeX, height, sizeY];
                const float PERLIN_ZOOM  = 10f;
                float       perlinOffset = (Mathf.Abs((float)preset.PerlinSeed) / int.MaxValue) * PERLIN_ZOOM;

                // Palette
                data.Palette = new List <Color>();
                int gColorLen        = preset.GroundColors.Count + preset.GrassColors.Count;
                int paletteLoopCount = 128 / (gColorLen + 1);
                for (int loop = 0; loop <= paletteLoopCount && data.Palette.Count < 256; loop++)
                {
                    for (int i = 0; i < preset.GroundColors.Count; i++)
                    {
                        data.Palette.Add(Color.Lerp(preset.GroundColors[i], preset.GroundColors[i] * 0.618f, ((float)loop) / paletteLoopCount));
                    }
                    for (int i = 0; i < preset.GrassColors.Count; i++)
                    {
                        data.Palette.Add(Color.Lerp(preset.GrassColors[i], preset.GrassColors[i] * 0.618f, ((float)loop) / paletteLoopCount));
                    }
                    data.Palette.Add(Color.Lerp(preset.WaterColor, preset.WaterColor * 0.618f, ((float)loop) / paletteLoopCount));
                }
                for (int i = 0; data.Palette.Count < 256; i++)
                {
                    data.Palette.Add(new Color(0.25f, 0.25f, 0.25f));
                }

                // Seeds
                var seeds = new float[sizeX, sizeY];
                for (int x = 0; x < sizeX; x++)
                {
                    for (int y = 0; y < sizeY; y++)
                    {
                        seeds[x, y] = (preset.Seeds[y * sizeX + x] - Preset.SEED_START) / 255f;
                    }
                }

                // Island
                if (preset.Island)
                {
                    for (int x = 0; x < sizeX; x++)
                    {
                        seeds[x, 0]         = 0f;
                        seeds[x, sizeY - 1] = 0f;
                    }
                    for (int y = 0; y < sizeY; y++)
                    {
                        seeds[0, y]         = 0f;
                        seeds[sizeX - 1, y] = 0f;
                    }
                }

                // Iteration
                for (int iter = 0; iter < preset.Iteration; iter++)
                {
                    var temp = new float[sizeX, sizeY];
                    for (int x = 0; x < sizeX; x++)
                    {
                        if (onProgress != null)
                        {
                            onProgress(((float)x / (sizeX - 1) / preset.Iteration) + ((float)iter / preset.Iteration), 0);
                        }
                        for (int y = 0; y < sizeY; y++)
                        {
                            temp[x, y] = GetIterationValue(seeds, x, y, preset.IterationRadius, preset.IterationLerp, sizeX, sizeY);
                        }
                    }
                    seeds = temp;
                }

                // Min Max
                float seedMin      = 1f;
                float seedMax      = 0f;
                int   minMaxOffset = preset.Island ? (int)(preset.IterationRadius * 2f) : 0;
                for (int x = minMaxOffset; x < sizeX - minMaxOffset; x++)
                {
                    for (int y = minMaxOffset; y < sizeY - minMaxOffset; y++)
                    {
                        seedMin = Mathf.Min(seedMin, seeds[x, y]);
                    }
                }
                for (int x = 0; x < sizeX; x++)
                {
                    for (int y = 0; y < sizeY; y++)
                    {
                        seedMax = Mathf.Max(seedMax, seeds[x, y]);
                    }
                }

                // Island
                if (preset.Island)
                {
                    for (int x = 0; x < sizeX; x++)
                    {
                        seeds[x, 0]         = 0f;
                        seeds[x, sizeY - 1] = 0f;
                    }
                    for (int y = 0; y < sizeY; y++)
                    {
                        seeds[0, y]         = 0f;
                        seeds[sizeX - 1, y] = 0f;
                    }
                }

                // Ground
                if (preset.Land && preset.GroundHeight.y > 0.01f)
                {
                    float bumpMuti = preset.GroundBump / 5f;
                    for (int x = 0; x < sizeX; x++)
                    {
                        if (onProgress != null)
                        {
                            onProgress(((float)x / (sizeX - 1) / preset.Iteration), 1);
                        }
                        for (int y = 0; y < sizeY; y++)
                        {
                            int h = (int)Util.Remap(
                                seedMin, seedMax,
                                preset.GroundHeight.x,
                                preset.GroundHeight.y + 0.999f,
                                seeds[x, y]
                                );
                            int colorIndex = Mathf.Clamp((int)(Mathf.PerlinNoise(
                                                                   (1f - Mathf.Repeat((x / (sizeX - 1f)) * bumpMuti, 0.999f)) * PERLIN_ZOOM + perlinOffset,
                                                                   (1f - Mathf.Repeat((y / (sizeY - 1f)) * bumpMuti, 0.999f)) * PERLIN_ZOOM + perlinOffset
                                                                   ) * gColorLen), 0, gColorLen - 1);
                            bool isGrass          = colorIndex >= preset.GroundColors.Count;
                            int  basicGroundIndex = Mathf.Clamp(colorIndex - preset.GroundColors.Count, 0, preset.GroundColors.Count - 1);
                            h = Mathf.Clamp(h, 0, height - 1);
                            for (int i = 0; i < h; i++)
                            {
                                int index = colorIndex;
                                if (isGrass && i < h - 1)
                                {
                                    index = basicGroundIndex;
                                }
                                if (preset.Tint)
                                {
                                    index = Mathf.RoundToInt(Mathf.Clamp(
                                                                 Util.Remap(preset.GroundHeight.x, preset.GroundHeight.y - 1f, paletteLoopCount * 0.5f, 0f, i),
                                                                 0f, paletteLoopCount - 1f
                                                                 )) * (gColorLen + 1) + index;
                                }
                                voxels[x, i, y] = index + 1;
                            }
                        }
                    }
                }


                // Cave
                if (preset.Cave)
                {
                    if (onProgress != null)
                    {
                        onProgress(0f, 2);
                    }
                    // Get Cave Voxel
                    var   caveVoxels       = new int[sizeX, height, sizeY];
                    float bumpMuti         = preset.CaveBump / 5f;
                    float cavePerlinOffset = (Mathf.Abs((float)preset.CaveSeed) / int.MaxValue) * PERLIN_ZOOM;
                    float rotSpeedMuti     = preset.CaveBump * 5f;

                    int     minHeight  = Mathf.Clamp(Mathf.RoundToInt(preset.CaveHeight.x), 0, height - 1);
                    int     maxHeight  = Mathf.Clamp(Mathf.RoundToInt(preset.CaveHeight.y), 0, height - 1);
                    float   posX       = Mathf.Repeat(preset.CaveSeed, sizeX - 0.01f);
                    float   posY       = Mathf.Repeat(-preset.CaveSeed, sizeY - 0.01f);
                    float   speedAngle = 0f;
                    Vector2 speed      = Vector2.up;

                    for (int i = 0; i < sizeX * sizeY; i++)
                    {
                        float perlin = Mathf.Clamp01(Mathf.PerlinNoise(
                                                         Mathf.Repeat((posX / (sizeX - 1f)) * bumpMuti, 0.999f) * PERLIN_ZOOM + cavePerlinOffset,
                                                         Mathf.Repeat((posY / (sizeY - 1f)) * bumpMuti, 0.999f) * PERLIN_ZOOM + cavePerlinOffset
                                                         ));
                        int h = (int)Util.Remap(0f, 1f, minHeight, maxHeight + 0.999f, perlin);

                        int     xMin      = Mathf.Max(Mathf.RoundToInt(posX) - Mathf.CeilToInt(preset.CaveRadius), 0);
                        int     xMax      = Mathf.Min(Mathf.RoundToInt(posX) + Mathf.CeilToInt(preset.CaveRadius), sizeX - 1);
                        int     yMin      = Mathf.Max(Mathf.RoundToInt(posY) - Mathf.CeilToInt(preset.CaveRadius), 0);
                        int     yMax      = Mathf.Min(Mathf.RoundToInt(posY) + Mathf.CeilToInt(preset.CaveRadius), sizeY - 1);
                        Vector2 centerPos = new Vector2(posX, posY);
                        for (int x = xMin; x <= xMax; x++)
                        {
                            for (int y = yMin; y <= yMax; y++)
                            {
                                if (Vector2.Distance(new Vector2(x, y), centerPos) <= preset.CaveRadius)
                                {
                                    int z    = Mathf.Clamp((int)(h - preset.CaveRadius), 0, height - 1);
                                    int zMax = Mathf.Clamp((int)(h + preset.CaveRadius), 0, height - 1);
                                    for (; z < zMax; z++)
                                    {
                                        caveVoxels[x, z, y] = 1;
                                    }
                                }
                            }
                        }

                        float seed01 = (preset.Seeds[i] - Preset.SEED_START) / 255f;
                        speedAngle = Mathf.Repeat(speedAngle + Util.Remap(0, 1, -rotSpeedMuti, rotSpeedMuti, seed01), 360f);
                        speed      = Quaternion.Euler(0, 0, speedAngle) * speed;
                        posX       = Mathf.Repeat(posX + speed.x, sizeX);
                        posY       = Mathf.Repeat(posY + speed.y, sizeY);
                    }

                    data.Voxels.Add(caveVoxels);

                    // Fix Into Ground
                    if (preset.Land)
                    {
                        for (int x = 0; x < sizeX; x++)
                        {
                            for (int y = 0; y < sizeY; y++)
                            {
                                for (int h = 0; h < height; h++)
                                {
                                    if (caveVoxels[x, h, y] > 0 && voxels[x, h, y] > 0)
                                    {
                                        voxels[x, h, y] = 0;
                                    }
                                }
                            }
                        }
                    }
                }


                // Water
                var waterStack = new Stack <Int3>();
                if (preset.Water)
                {
                    float bumpMuti = preset.WaterBump / 5f;
                    for (int x = 0; x < sizeX; x++)
                    {
                        if (onProgress != null)
                        {
                            onProgress(((float)x / (sizeX - 1) / preset.Iteration), 3);
                        }
                        for (int y = 0; y < sizeY; y++)
                        {
                            float perlin = Mathf.PerlinNoise(
                                Mathf.Repeat((x / (sizeX - 1f)) * bumpMuti, 0.999f) * PERLIN_ZOOM + perlinOffset,
                                Mathf.Repeat((y / (sizeY - 1f)) * bumpMuti, 0.999f) * PERLIN_ZOOM + perlinOffset
                                );
                            int h = (int)Mathf.Lerp(
                                preset.WaterHeight.x,
                                preset.WaterHeight.y + 0.999f,
                                perlin
                                );
                            for (int i = 0; i < h; i++)
                            {
                                if (voxels[x, i, y] > 0)
                                {
                                    continue;
                                }
                                int v = preset.Tint ?
                                        Mathf.RoundToInt(Mathf.Clamp(
                                                             Util.Remap(preset.WaterHeight.x, preset.WaterHeight.y - 1f, paletteLoopCount * 0.5f, 0f, i),
                                                             0f, paletteLoopCount - 1f
                                                             )) * (gColorLen + 1) + gColorLen + 1
                                                                        : gColorLen + 1;
                                voxels[x, i, y] = -v;
                                waterStack.Push(new Int3(x, i, y));
                            }
                        }
                    }

                    // Fix Water Physics
                    if (onProgress != null)
                    {
                        onProgress(0.5f, 4);
                    }
                    if (preset.Land)
                    {
                        int _a, _b, _c, _d;
                        for (int safeCount = 1000000; safeCount > 0 && waterStack.Count > 0; safeCount--)
                        {
                            var pos = waterStack.Pop();
                            if (voxels[pos.A, pos.B, pos.C] < 0)
                            {
                                _a = pos.A > 0 ? voxels[pos.A - 1, pos.B, pos.C] : 1;
                                _b = pos.A < sizeX - 1 ? voxels[pos.A + 1, pos.B, pos.C] : 1;
                                _c = pos.C > 0 ? voxels[pos.A, pos.B, pos.C - 1] : 1;
                                _d = pos.C < sizeY - 1 ? voxels[pos.A, pos.B, pos.C + 1] : 1;
                                if (_a == 0 || _b == 0 || _c == 0 || _d == 0)
                                {
                                    voxels[pos.A, pos.B, pos.C] = 0;
                                    if (_a < 0)
                                    {
                                        waterStack.Push(new Int3(pos.A - 1, pos.B, pos.C));
                                    }
                                    if (_b < 0)
                                    {
                                        waterStack.Push(new Int3(pos.A + 1, pos.B, pos.C));
                                    }
                                    if (_c < 0)
                                    {
                                        waterStack.Push(new Int3(pos.A, pos.B, pos.C - 1));
                                    }
                                    if (_d < 0)
                                    {
                                        waterStack.Push(new Int3(pos.A, pos.B, pos.C + 1));
                                    }
                                }
                            }
                        }
                    }
                    // Fix -Voxels
                    for (int x = 0; x < sizeX; x++)
                    {
                        for (int y = 0; y < sizeY; y++)
                        {
                            for (int h = 0; h < height; h++)
                            {
                                if (voxels[x, h, y] < 0)
                                {
                                    voxels[x, h, y] = -voxels[x, h, y];
                                }
                            }
                        }
                    }
                }


                // End
                data.Voxels.Insert(0, voxels);
                if (onProgress != null)
                {
                    onProgress(1f, int.MaxValue);
                }
                return(data);
            } catch (System.Exception ex) {
                if (onProgress != null)
                {
                    onProgress(1f, int.MaxValue);
                }
                throw ex;
            }
        }