예제 #1
0
        // Credit goes to Kragrathea.
        public static UnsafeBitmap BumpToNormalMap(UnsafeBitmap source, Single strength)
        {
            strength = Mathf.Clamp(strength, 0.0F, 10.0F);
            UnsafeBitmap result =
                new UnsafeBitmap(new Bitmap(source.Bitmap.Width, source.Bitmap.Height, PixelFormat.Format32bppArgb));

            source.LockBitmap();
            result.LockBitmap();
            for (Int32 by = 0; by < result.Bitmap.Height; by++)
            {
                for (Int32 bx = 0; bx < result.Bitmap.Width; bx++)
                {
                    Int32  x     = bx == 0 ? result.Bitmap.Width : bx;
                    Single xLeft = ((Color)source.GetPixel(x - 1, by)).grayscale * strength;
                    x = bx == (result.Bitmap.Width - 1) ? 0 : bx;
                    Single xRight = ((Color)source.GetPixel(x + 1, by)).grayscale * strength;
                    Int32  y      = by == 0 ? result.Bitmap.Height : by;
                    Single yUp    = ((Color)source.GetPixel(bx, y - 1)).grayscale * strength;
                    y = by == (result.Bitmap.Height - 1) ? 0 : by;
                    Single yDown  = ((Color)source.GetPixel(bx, y + 1)).grayscale * strength;
                    Single xDelta = ((xLeft - xRight) + 1) * 0.5f;
                    Single yDelta = ((yUp - yDown) + 1) * 0.5f;
                    result.SetPixel(bx, by, new Color(yDelta, yDelta, yDelta, xDelta));
                }
            }
            source.UnlockBitmap();
            result.UnlockBitmap();
            return(result);
        }
예제 #2
0
        /// <summary>
        ///     Extracts the average color from a bitmap file
        /// </summary>
        public static Color GetAverageColor(Bitmap bm)
        {
            Byte avgB;
            Byte avgG;
            Byte avgR;

            using (UnsafeBitmap bitmap = new UnsafeBitmap(bm))
            {
                bitmap.LockBitmap();
                Int64[] totals = { 0, 0, 0 };

                Int64 width  = bm.Width;
                Int64 height = bm.Height;

                for (Int32 y = 0; y < height; y++)
                {
                    for (Int32 x = 0; x < width; x++)
                    {
                        System.Drawing.Color c = bitmap.GetPixel(x, y);
                        totals[0] += c.B;
                        totals[1] += c.G;
                        totals[2] += c.R;
                    }
                }

                avgB = (Byte)(totals[0] / (width * height));
                avgG = (Byte)(totals[1] / (width * height));
                avgR = (Byte)(totals[2] / (width * height));
                bitmap.UnlockBitmap();
            }
            return(new Color32(avgR, avgG, avgB, 255));
        }
예제 #3
0
        /// <summary>
        ///     Generates a PQS Setup + the Scaled Space Maps needed
        /// </summary>
        /// <returns></returns>
        // ReSharper disable once InconsistentNaming
        private static void GeneratePQS(ref ConfigNode node, String name, String folder, Planet planet, Color planetColor,
                                        out Color average, out List <Color> biomes)
        {
            // Log
            Console.WriteLine("Preparing to load PQS data");

            // Create the node
            ConfigNode pqs = new ConfigNode("PQS");

            // TODO: Material Settings?

            // Create a node for the mods
            ConfigNode mods = new ConfigNode("Mods");

            pqs.AddConfigNode(mods);

            // Load the PQSDatabase and select a setup
            ConfigNode       pqsDatabase = Utility.Load("pqs");
            List <PQSPreset> data        = pqsDatabase.nodes.Select(n => Parser.CreateObjectFromConfigNode <PQSPreset>(n))
                                           .ToList();

            data = data.Where(d => ((planet.radius * 100) > d.MinRadius) && ((planet.radius * 100) < d.MaxRadius))
                   .ToList();
            PQSPreset setup = data[Random.Next(0, data.Count)];

            // Setup the interpreter
            Interpreter interpreter = new Interpreter()
                                      .SetVariable("planet", planet, typeof(Planet))
                                      .SetVariable("pqsVersion", setup, typeof(PQSPreset))
                                      .SetVariable("Random", Random, typeof(Random))
                                      .SetVariable("Seed", Seed, typeof(Int32))
                                      .SetVariable("Color", Utility.GenerateColor(), typeof(Color))
                                      .Reference(typeof(Parser))
                                      .Reference(typeof(Generator))
                                      .Reference(typeof(Utility))
                                      .Reference(typeof(Utils));

            // Transfer the mod nodes and evaluate expressions
            foreach (ConfigNode modNode in setup.Mods.nodes)
            {
                mods.AddConfigNode(Utility.Eval(modNode, interpreter));
            }

            // Create a new PQSObject
            PQS           pqsVersion  = new PQS(planet.radius * 100);
            List <PQSMod> patchedmods = new List <PQSMod>();

            // Log
            Console.WriteLine($"Created PQS Object for {name}");

            // Get all loaded types
            List <Type> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).ToList();

            // Load mods from Config
            foreach (ConfigNode mod in mods.nodes)
            {
                // get the mod type
                if (types.Count(t => t.Name == mod.name) == 0)
                {
                    continue;
                }
                Type   loaderType = types.FirstOrDefault(t => t.Name == mod.name);
                String testName   = mod.name != "LandControl" ? "PQSMod_" + mod.name : "PQSLandControl";
                Type   modType    = types.FirstOrDefault(t => t.Name == testName);
                if ((loaderType == null) || (modType == null))
                {
                    continue;
                }

                // Do any PQS mods already exist on this PQS matching this mod?
                IEnumerable <PQSMod> existingmods = pqsVersion.mods.Where(m => m.GetType() == modType);

                // Create the loader
                Object loader = Activator.CreateInstance(loaderType);

                // Reflection, because C# being silly... :/
                MethodInfo createNew = loaderType.GetMethod("Create", new[] { typeof(PQS) });
                MethodInfo create    = loaderType.GetMethod("Create", new[] { modType });

                IList <PQSMod> pqsmods = existingmods as IList <PQSMod> ?? existingmods.ToList();
                if (pqsmods.Any())
                {
                    // Attempt to find a PQS mod we can edit that we have not edited before
                    PQSMod existingMod = pqsmods.FirstOrDefault(m => !patchedmods.Contains(m) &&
                                                                (!mod.HasValue("name") ||
                                                                 (mod.HasValue("index")
                                                                           ? (pqsmods.ToList().IndexOf(m) ==
                                                                              Int32.Parse(mod.GetValue("index"))) &&
                                                                  (m.name == mod.GetValue("name"))
                                                                           : m.name == mod.GetValue("name"))));
                    if (existingMod != null)
                    {
                        create.Invoke(loader, new Object[] { existingMod });
                        Parser.LoadObjectFromConfigurationNode(loader, mod);
                        patchedmods.Add(existingMod);
                    }
                    else
                    {
                        createNew.Invoke(loader, new Object[] { pqsVersion });
                        Parser.LoadObjectFromConfigurationNode(loader, mod);
                    }
                }
                else
                {
                    createNew.Invoke(loader, new Object[] { pqsVersion });
                    Parser.LoadObjectFromConfigurationNode(loader, mod);
                }

                // Log
                Console.WriteLine($"Created a new instance of {loaderType.Name} on {name}");
            }

            // Size
            Int32 width = pqsVersion.radius >= 600000 ? 4096 : pqsVersion.radius <= 100000 ? 1024 : 2048;

            // Biome colors
            int numBiomes = Random.Next(2, 10);

            biomes = new List <Color>(numBiomes);
            for (int i = 0; i < numBiomes; i++)
            {
                biomes.Add(Utility.GenerateColor());
            }

            // Export ScaledSpace Maps
            using (UnsafeBitmap diffuse = new UnsafeBitmap(width, width / 2))
            {
                using (UnsafeBitmap height = new UnsafeBitmap(width, width / 2))
                {
                    using (UnsafeBitmap biomeMap = new UnsafeBitmap(width, width / 2))
                    {
                        Console.WriteLine("Exporting Scaled Space maps from the PQS. This could take a while...");

                        // Iterate over the PQS
                        pqsVersion.SetupSphere();
                        diffuse.LockBitmap();
                        height.LockBitmap();
                        biomeMap.LockBitmap();
                        for (Int32 i = 0; i < width; i++)
                        {
                            for (Int32 j = 0; j < (width / 2); j++)
                            {
                                // Create a VertexBuildData
                                VertexBuildData builddata = new VertexBuildData
                                {
                                    directionFromCenter =
                                        Quaternion.CreateFromAngleAxis((360d / width) * i,
                                                                       Vector3.Up) *
                                        Quaternion
                                        .CreateFromAngleAxis(90d - ((180d / (width / 2.0)) * j),
                                                             Vector3.Right) *
                                        Vector3.Forward,
                                    vertHeight = pqsVersion.radius
                                };

                                // Build the maps
                                pqsVersion.OnVertexBuildHeight(builddata);
                                pqsVersion.OnVertexBuild(builddata);
                                builddata.vertColor.a = 1f;

                                Single h = Mathf.Clamp01((Single)((builddata.vertHeight - pqsVersion.radius) *
                                                                  (1d / pqsVersion.radiusMax)));
                                Single h1 = Mathf.Clamp01((Single)((builddata.vertHeight - pqsVersion.radius) *
                                                                   (1d / (pqsVersion.radiusMax != 0 ? pqsVersion.radiusMax : planet.radius))));

                                diffuse.SetPixel(i, j, builddata.vertColor);
                                height.SetPixel(i, j, new Color(h, h, h));

                                biomeMap.SetPixel(i, j, biomes[(int)(h1 * (numBiomes - 1))]);
                            }
                        }
                        diffuse.UnlockBitmap();
                        height.UnlockBitmap();
                        biomeMap.UnlockBitmap();

                        // Save the textures
                        Directory.CreateDirectory(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/");
                        using (UnsafeBitmap normals = Utility.BumpToNormalMap(height, 9))
                        {
                            // TODO: Implement something to make strength dynamic
                            diffuse.Bitmap
                            .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Texture.png",
                                  ImageFormat.Png);
                            height.Bitmap
                            .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Height.png",
                                  ImageFormat.Png);       // In case you need it :)
                            normals.Bitmap
                            .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Normals.png",
                                  ImageFormat.Png);
                            biomeMap.Bitmap
                            .Save(Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/" + name + "_Biomes.png",
                                  ImageFormat.Png);
                        }
                    }
                }

                // Log
                Console.WriteLine($"Saved maps to {Directory.GetCurrentDirectory() + "/systems/" + folder + "/PluginData/"}");

                // Finish
                node.AddConfigNode(pqs);

                // Colors
                average = Utility.GetAverageColor(diffuse.Bitmap);
            }
        }