예제 #1
0
        public void Setup()
        {
            Console.Write("Enter video framerate: ");
            var framerate = Console.ReadLine();

            Console.Write("Enter total frame count: ");
            var frames = int.Parse(Console.ReadLine());

            Console.Write("Enter output video file name (no extension): ");
            var name = Console.ReadLine().Trim();

            Console.Write("Enter resolution separated by a comma (480,480): ");
            var res = Console.ReadLine().Split(',').ToList().ConvertAll(resPart => int.Parse(resPart)).ToArray();

            Console.Write("Enter mandelbrot power range (x in f(z)=z^x + c) separated by a comma (1,10): ");
            var range = Console.ReadLine().Split(',').ToList().ConvertAll(rangePart => int.Parse(rangePart)).ToArray();
            var s     = Stopwatch.StartNew();

            Console.WriteLine("Generation is starting, please wait...");
            var done = 0;

            var items  = Enumerable.Range(0, frames).ToArray();
            var chunks = items
                         .Select((s2, i) => new { Value = s2, Index = i })
                         .GroupBy(x => x.Index / 10)
                         .Select(grp => grp.Select(x => x.Value).ToArray()).ToList();

            var threads = new List <Thread>();

            for (var t = 0; t < Environment.ProcessorCount - 1; t++)
            {
                var t2     = t;
                var thread = new Thread(() =>
                {
                    start:;
                    if (chunks.Count == 0)
                    {
                        goto exit;
                    }

                    var assignedChunk = chunks[0];
                    chunks.RemoveAt(0);
                    foreach (var a in assignedChunk)
                    {
                        var pow   = PMath.Map(a, 1, frames, range[0], range[1]);
                        var Image = new PSprite(res[0], res[1]);

                        var pixels = Image.Art.GetPixels();
                        for (var y = 0; y < Image.Height; y++)
                        {
                            for (var x = 0; x < Image.Width; x++)
                            {
                                var xTarget = 4f;
                                var yTarget = (xTarget / Image.Width) * Image.Height;

                                var x2 = (x / (Image.Width / (xTarget))) - (xTarget / 2);
                                var y2 = (y / (Image.Height / (yTarget))) - (yTarget / 2);

                                var c         = new Complex(x2, y2);
                                var z         = Complex.Zero;
                                var max       = -1f;
                                var maxWasHit = false;
                                for (var i = 0; i < maxDepth; i++)
                                {
                                    z = (Complex.Pow(z, pow)) + c;
                                    if ((z.Real * z.Real) + (z.Imaginary * z.Imaginary) > 16 && max == -1f)
                                    {
                                        max       = i;
                                        maxWasHit = true;
                                        break;
                                    }
                                }

                                var color = PColor.Black;

                                if (maxWasHit)
                                {
                                    var floorMax = (int)Math.Floor(max);
                                    var c1       = pallet[floorMax % pallet.Length];
                                    var c2       = pallet[(floorMax + 1) % pallet.Length];
                                    color        = PColor.Lerp(c1, c2, 0.5f);
                                }

                                var pos = ((y * Image.Width) + x) * 4;

                                pixels[pos]     = (byte)(color.R);
                                pixels[pos + 1] = (byte)(color.G);
                                pixels[pos + 2] = (byte)(color.B);
                                pixels[pos + 3] = 255;
                            }
                        }
                        Image.Art.SetPixels(pixels);
                        Image.Save(folder + a.ToString("000000") + ".png");
                        var percent           = (done / (float)frames);
                        var remaining         = (1f - percent) * 100;
                        var secondsPerPercent = s.Elapsed.TotalSeconds / (percent * 100f);
                        var minutesRemaining  = ((secondsPerPercent * remaining) / 60f);
                        var estimatedTime     = DateTime.Now.AddMinutes(done == 0 ? 0 : minutesRemaining);
                        Console.WriteLine("Progress: " + done + "/" + frames + "  " + (percent * 100f).ToString("0.00") +
                                          "%   Estimated completion time: " + estimatedTime);
                        done++;
                    }
                    goto start;
                    exit:;
                })
                {
                    Name     = "Mandelbrot: Core " + (t + 1),
                    Priority = ThreadPriority.AboveNormal,
                };
                threads.Add(thread);
                thread.Start();
            }
            ;

            var info = new ProcessStartInfo()
            {
                FileName         = "ffmpeg",
                Arguments        = string.Format(" -framerate {0} -i %06d.png -c:v libx264 -r {0} {1}.mp4", framerate, name),
                WorkingDirectory = folder,
            };

            var activeThreads = 1;

            do
            {
                Console.Title = "Active thread count: " + activeThreads;
                activeThreads = threads.Where(t => t.IsAlive).Count();
                Thread.Sleep(1000);
                Title(activeThreads);
            }while (activeThreads > 0);

            Console.Title = "Active thread count: 0";

            var p = Process.Start(info);

            p.WaitForExit();

            Console.WriteLine(@"Saved as " + folder + "out.mp4");
            Console.ReadLine();
            Close();
        }