public static void CreateAnimation(Viewport from, Viewport to, ref ReadOnlyBuffer <float> coordinates, int imageWidth, int imageHeight)
        {
            // Creating/handling the frames folder.
            if (Directory.Exists("frames"))
            {
                foreach (var f in Directory.GetFiles("frames"))
                {
                    File.Delete(f);
                }
            }
            else
            {
                Directory.CreateDirectory("frames");
            }
            Thread.Sleep(500);

            var previousMaxDensity = -1f;

            /// This just determines how many frames to render.
            var timeToTake = 1; // seconds
            var frameRate  = 1000;

            var progress = 0;

            var watch = new Stopwatch();

            watch.Start();
            for (var i = 0; i < frameRate * timeToTake; i++)
            {
                var t = i / (float)(frameRate * timeToTake);
                t = Smoothing(t);
                var image = new PSprite(imageWidth, imageHeight);
                image.Art.SetPixels(GalaxyRenderer.Render(
                                        Viewport.Lerp(from, to, t), 1000, 1000,
                                        GalaxyRenderer.DefaultColorMapping,
                                        i == 0 ? (float?)null : previousMaxDensity,
                                        out previousMaxDensity,
                                        ref coordinates));
                if (!(image is null))
                {
                    image.Save(@"frames\" + i.ToString("000000") + ".png");
                    image.Dispose();
                }
                progress++;

                #region Logging progress per frame
                Console.WriteLine(progress + " / " + (frameRate * timeToTake) + "  -  " + ((progress * 100) / (double)(frameRate * timeToTake)).ToString("0.00") + "%");

                var secondsPerFrame = watch.Elapsed.TotalSeconds / progress;
                var framesRemaining = (frameRate * timeToTake) - progress;
                var timeRemaining   = new TimeSpan((long)(10000000 * (framesRemaining * secondsPerFrame)));
                Console.WriteLine("Estimated time remaining: " +
                                  timeRemaining.Hours.ToString("00") + ":" +
                                  timeRemaining.Minutes.ToString("00") + ":" +
                                  timeRemaining.Seconds.ToString("00"));
                Console.WriteLine("Average time per frame: " + secondsPerFrame.ToString("0.00") + " seconds.");
                #endregion
            }

            Console.WriteLine("Frame rendering complete. Compiling video...");
            var info = new ProcessStartInfo()
            {
                FileName         = "ffmpeg",
                Arguments        = string.Format(" -framerate {0} -i %06d.png -c:v libx264 -r {0} {1}.mp4", frameRate, "out"),
                WorkingDirectory = "frames",
            };
            var p = Process.Start(info);
            p.WaitForExit();
            Console.WriteLine("Finished. Saved video as out.mp4.");
            Console.Read();
        }
예제 #2
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();
        }