Example #1
0
        /// <summary>
        /// Routine of one worker-thread.
        /// Result image and rendering progress are the only two shared objects.
        /// </summary>
        /// <param name="spec">Thread-specific data (worker-thread-selector).</param>
        private void RenderWorker(Object spec)
        {
            WorkerThreadInit init = spec as WorkerThreadInit;

            if (init != null)
            {
                MT.InitThreadData();
                rend.RenderRectangle(init.image, 0, 0, init.width, init.height,
                                     init.sel);
            }
        }
Example #2
0
        /// <summary>
        /// Routine of one worker-thread.
        /// Collect arrays and rendering progress are the only two shared objects.
        /// </summary>
        /// <param name="spec">Thread-specific data (worker-thread-selector).</param>
        private void SimulationWorker(Object spec)
        {
            WorkerThreadInit init = spec as WorkerThreadInit;

            if (init != null)
            {
                init.sim.Init(init.nPart, init.ppt);

                // infinite simulation loop:
                do
                {
                    double deltaT = init.dt + init.vart * (init.sim.rnd.UniformNumber() - 1.0);
                    init.sim.Tick(deltaT);
                    init.sim.SimTime += deltaT;
                    lock (progress)
                        if (!progress.Continue)
                        {
                            break;
                        }
                    init.sim.GatherBuffers();
                }while (true);
            }
        }
Example #3
0
        /// <summary>
        /// [Re]-renders the whole image (in separate thread). OLD VERSION!!!
        /// </summary>
        private void RenderImage_OLD()
        {
            Cursor.Current = Cursors.WaitCursor;

            // determine output image size:
            int width = ImageWidth;

            if (width <= 0)
            {
                width = panel1.Width;
            }

            int height = ImageHeight;

            if (height <= 0)
            {
                height = panel1.Height;
            }

            Bitmap newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);

            int threads = CheckMultithreading.Checked ? Environment.ProcessorCount : 1;
            int t; // thread ordinal number

            WorkerThreadInit[] wti = new WorkerThreadInit[threads];

            // separate renderer, image function and the scene for each thread (safety precaution)
            for (t = 0; t < threads; t++)
            {
                IRayScene      sc  = FormSupport.getScene();
                IImageFunction imf = getImageFunction(sc, width, height);
                IRenderer      r   = getRenderer(imf, width, height);
                wti[t] = new WorkerThreadInit(r, sc as ITimeDependent, imf as ITimeDependent, newImage, width, height, t, threads);
            }

            progress.SyncInterval = ((width * (long)height) > (2L << 20)) ? 3000L : 1000L;
            progress.Reset();
            CSGInnerNode.ResetStatistics();

            lock (sw)
                sw.Restart();

            if (threads > 1)
            {
                Thread[] pool = new Thread[threads];
                for (t = 0; t < threads; t++)
                {
                    pool[t] = new Thread(new ParameterizedThreadStart(RenderWorker));
                }
                for (t = threads; --t >= 0;)
                {
                    pool[t].Start(wti[t]);
                }

                for (t = 0; t < threads; t++)
                {
                    pool[t].Join();
                    pool[t] = null;
                }
            }
            else
            {
                MT.InitThreadData();
                wti[0].rend.RenderRectangle(newImage, 0, 0, width, height);
            }

            long elapsed;

            lock (sw)
            {
                sw.Stop();
                elapsed = sw.ElapsedMilliseconds;
            }

            string msg = string.Format(CultureInfo.InvariantCulture,
                                       "{0:f1}s  [ {1}x{2}, mt{3}, r{4:#,#}k, i{5:#,#}k, bb{6:#,#}k, t{7:#,#}k ]",
                                       1.0e-3 * elapsed, width, height, threads,
                                       (Intersection.countRays + 500L) / 1000L,
                                       (Intersection.countIntersections + 500L) / 1000L,
                                       (CSGInnerNode.countBoundingBoxes + 500L) / 1000L,
                                       (CSGInnerNode.countTriangles + 500L) / 1000L);

            SetText(msg);
            Console.WriteLine(@"Rendering finished: " + msg);
            SetImage(newImage);

            Cursor.Current = Cursors.Default;

            StopRendering();
        }
Example #4
0
        /// <summary>
        /// Worker thread (picks up individual frames and renders them one by one).
        /// </summary>
        protected void RenderWorker(object spec)
        {
            // thread-specific data:
            WorkerThreadInit init = spec as WorkerThreadInit;

            if (init == null)
            {
                return;
            }

            MT.InitThreadData();

            // worker loop:
            while (true)
            {
                double myTime;
                double myEndTime;
                int    myFrameNumber;

                lock ( progress )
                {
                    if (!progress.Continue ||
                        time > end)
                    {
                        sem.Release();      // chance for the main animation thread to give up as well..
                        return;
                    }

                    // got a frame to compute:
                    myTime        = time;
                    myEndTime     = (time += dt);
                    myFrameNumber = frameNumber++;
                }

                // set up the new result record:
                Result r = new Result();
                r.image       = new Bitmap(init.width, init.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                r.frameNumber = myFrameNumber;

                // set specific time to my scene:
                if (init.scene != null)
                {
                    init.scene.Time = myTime;
                }

                ITimeDependent anim = init.rend as ITimeDependent;
                if (anim != null)
                {
                    anim.Start = myTime;
                    anim.End   = myEndTime;
                }

                if (init.imfunc != null)
                {
                    init.imfunc.Start = myTime;
                    init.imfunc.End   = myEndTime;
                }

                // render the whole frame:
                init.rend.RenderRectangle(r.image, 0, 0, init.width, init.height);

                // ... and put the result into the output queue:
                lock ( queue )
                {
                    queue.Enqueue(r);
                }
                sem.Release();              // notify the main animation thread
            }
        }
Example #5
0
        /// <summary>
        /// Main animation rendering thread.
        /// Initializes worker threads and collects the results.
        /// </summary>
        protected void RenderAnimation()
        {
            Cursor.Current = Cursors.WaitCursor;

            int threads = Environment.ProcessorCount;
            int t; // thread ordinal number

            WorkerThreadInit[] wti = new WorkerThreadInit[threads];

            for (t = 0; t < threads; t++)
            {
                IRayScene      sc  = FormSupport.getScene(textParam.Text);
                IImageFunction imf = FormSupport.getImageFunction(sc);
                imf.Width  = width;
                imf.Height = height;

                IRenderer r = FormSupport.getRenderer(imf);
                r.Width        = width;
                r.Height       = height;
                r.Adaptive     = 0;   // turn off adaptive bitmap synthesis completely (interactive preview not needed)
                r.ProgressData = progress;

                wti[t] = new WorkerThreadInit(r, sc as ITimeDependent, imf as ITimeDependent, width, height);
            }

            initQueue();
            sem = new Semaphore(0, 10 * threads);

            // pool of working threads:
            Thread[] pool = new Thread[threads];
            for (t = 0; t < threads; t++)
            {
                pool[t] = new Thread(new ParameterizedThreadStart(RenderWorker));
            }
            for (t = threads; --t >= 0;)
            {
                pool[t].Start(wti[t]);
            }

            // loop for collection of computed frames:
            int        frames             = 0;
            int        lastDisplayedFrame = -1;
            const long DISPLAY_GAP        = 10000L;
            long       lastDisplayedTime  = -DISPLAY_GAP;
            Stopwatch  sw = new Stopwatch();

            sw.Start();

            while (true)
            {
                sem.WaitOne();              // wait until a frame is finished

                lock ( progress )           // regular finish, escape, user break?
                {
                    if (!progress.Continue ||
                        time >= end &&
                        frames >= frameNumber)
                    {
                        break;
                    }
                }

                // there could be a frame to process:
                Result r;
                lock ( queue )
                {
                    if (queue.Count == 0)
                    {
                        continue;
                    }
                    r = queue.Dequeue();
                }

                // GUI progress indication:
                double seconds = 1.0e-3 * sw.ElapsedMilliseconds;
                double fps     = ++frames / seconds;
                SetText(string.Format(CultureInfo.InvariantCulture, "Frames (mt{0}): {1}  ({2:f0} s, {3:f2} fps)",
                                      threads, frames, seconds, fps));
                if (r.frameNumber > lastDisplayedFrame &&
                    sw.ElapsedMilliseconds > lastDisplayedTime + DISPLAY_GAP)
                {
                    lastDisplayedFrame = r.frameNumber;
                    lastDisplayedTime  = sw.ElapsedMilliseconds;
                    SetImage((Bitmap)r.image.Clone());
                }

                // save the image file:
                string fileName = string.Format("out{0:0000}.png", r.frameNumber);
                r.image.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
                r.image.Dispose();
            }

            for (t = 0; t < threads; t++)
            {
                pool[t].Join();
                pool[t] = null;
            }

            Cursor.Current = Cursors.Default;

            StopAnimation();
        }
Example #6
0
        /// <summary>
        /// [Re]-renders the whole image (in separate thread). OLD VERSION!!!
        /// </summary>
        private void RenderImage_OLD()
        {
            Cursor.Current = Cursors.WaitCursor;

            // Determine output image size.
            int width = ImageWidth;

            if (width <= 0)
            {
                width = panel1.Width;
            }

            int height = ImageHeight;

            if (height <= 0)
            {
                height = panel1.Height;
            }

            Bitmap newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);

            int threads = CheckMultithreading.Checked ? Environment.ProcessorCount : 1;
            int t; // thread ordinal number
            int superSampling = (int)NumericSupersampling.Value;

            WorkerThreadInit[] wti = new WorkerThreadInit[threads];

            // 1. preprocessing - compute simulation, animation data, etc.
            _ = FormSupport.getScene(true, out _, out _, superSampling, TextParam.Text);

            // Separate renderer, image function and the scene for each thread (safety precaution).
            for (t = 0; t < threads; t++)
            {
                // 2. initialize data for regular frames (using the pre-computed context).
                IRayScene sc = FormSupport.getScene(
                    false,
                    out IImageFunction imf,
                    out IRenderer rend,
                    superSampling,
                    TextParam.Text);

                // IImageFunction.
                imf        = getImageFunction(imf, sc);
                imf.Width  = width;
                imf.Height = height;

                // IRenderer.
                if (rend == null) // not defined in the script
                {
                    rend = getRenderer();
                }
                rend.ImageFunction = imf;
                rend.Width         = width;
                rend.Height        = height;
                rend.Adaptive      = 8;
                rend.ProgressData  = progress;

                wti[t] = new WorkerThreadInit(rend, sc as ITimeDependent, imf as ITimeDependent, newImage, width, height, t, threads);
            }

            progress.SyncInterval = ((width * (long)height) > (2L << 20)) ? 3000L : 1000L;
            progress.Reset();
            CSGInnerNode.ResetStatistics();

            lock (sw)
                sw.Restart();

            if (threads > 1)
            {
                Thread[] pool = new Thread[threads];
                for (t = 0; t < threads; t++)
                {
                    pool[t] = new Thread(new ParameterizedThreadStart(RenderWorker));
                }
                for (t = threads; --t >= 0;)
                {
                    pool[t].Start(wti[t]);
                }

                for (t = 0; t < threads; t++)
                {
                    pool[t].Join();
                    pool[t] = null;
                }
            }
            else
            {
                MT.InitThreadData();
                wti[0].rend.RenderRectangle(newImage, 0, 0, width, height);
            }

            long elapsed;

            lock (sw)
            {
                sw.Stop();
                elapsed = sw.ElapsedMilliseconds;
            }

            string msg = string.Format(CultureInfo.InvariantCulture,
                                       "{0:f1}s  [ {1}x{2}, mt{3}, r{4:#,#}k, i{5:#,#}k, bb{6:#,#}k, t{7:#,#}k ]",
                                       1.0e-3 * elapsed, width, height, threads,
                                       (Intersection.countRays + 500L) / 1000L,
                                       (Intersection.countIntersections + 500L) / 1000L,
                                       (CSGInnerNode.countBoundingBoxes + 500L) / 1000L,
                                       (CSGInnerNode.countTriangles + 500L) / 1000L);

            SetText(msg);
            Console.WriteLine(@"Rendering finished: " + msg);
            SetImage(newImage);

            Cursor.Current = Cursors.Default;

            StopRendering();
        }
Example #7
0
        /// <summary>
        /// Worker thread (picks up individual frames and renders them one by one).
        /// </summary>
        protected void RenderWorker(object spec)
        {
            // Thread-specific data.
            WorkerThreadInit init = spec as WorkerThreadInit;

            if (init == null)
            {
                return;
            }

            MT.InitThreadData();

            // Worker loop.
            while (true)
            {
                double myTime;
                double myEndTime;
                int    myFrameNumber;

                lock (progress)
                {
                    if (!progress.Continue ||
                        time > end)
                    {
                        sem.Release();      // chance for the main animation thread to give up as well..
                        return;
                    }

                    // I've got a frame to compute.
                    myTime        = time;
                    myEndTime     = (time += dt);
                    myFrameNumber = frameNumber++;
                }

                // Set up the new result record.
                Result r = new Result();
                r.image       = new Bitmap(init.width, init.height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                r.frameNumber = myFrameNumber;

                // Set specific time to my scene.
                if (init.scene != null)
                {
#if DEBUG
                    Debug.WriteLine($"Scene #{init.scene.getSerial()} setTime({myTime})");
#endif
                    init.scene.Time = myTime;
                }

                if (init.rend is ITimeDependent arend)
                {
                    arend.Start = myTime;
                    arend.End   = myEndTime;
                }

                if (init.imfunc != null)
                {
                    init.imfunc.Start = myTime;
                    init.imfunc.End   = myEndTime;
                }

                // Render the whole frame...
                init.rend.RenderRectangle(r.image, 0, 0, init.width, init.height);

                // ...and put the result into the output queue.
                lock (queue)
                {
                    queue.Enqueue(r);
                }
                sem.Release();              // notify the main animation thread
            }
        }
Example #8
0
        /// <summary>
        /// Main animation rendering thread.
        /// Initializes worker threads and collects the results.
        /// </summary>
        protected void RenderAnimation()
        {
            Cursor.Current = Cursors.WaitCursor;

            int    threads = Environment.ProcessorCount;
            int    t; // thread ordinal number
            int    superSampling = (int)numericSupersampling.Value;
            double minTime       = (double)numFrom.Value;
            double maxTime       = (double)numTo.Value;
            double fps           = (double)numFps.Value;

            WorkerThreadInit[] wti = new WorkerThreadInit[threads];

            // 1. preprocessing - compute simulation, animation data, etc.
            FormSupport.getScene(
                true,
                out _, out _,
                ref ActualWidth,
                ref ActualHeight,
                ref superSampling,
                ref minTime,
                ref maxTime,
                ref fps,
                textParam.Text);

            for (t = 0; t < threads; t++)
            {
                // 2. initialize data for regular frames (using the pre-computed context).
                IRayScene sc = FormSupport.getScene(
                    false,
                    out IImageFunction imf,
                    out IRenderer rend,
                    ref ActualWidth,
                    ref ActualHeight,
                    ref superSampling,
                    ref minTime,
                    ref maxTime,
                    ref fps,
                    textParam.Text);

                if (t == 0)
                {
                    // Update GUI.
                    if (ImageWidth > 0) // preserving default (form-size) resolution
                    {
                        ImageWidth  = ActualWidth;
                        ImageHeight = ActualHeight;
                        UpdateResolutionButton();
                    }
                    UpdateSupersampling(superSampling);
                    UpdateAnimationTiming(minTime, maxTime, fps);
                }

                if (sc is ITimeDependent sca)
                {
                    sc = (IRayScene)sca.Clone();
                }

                // IImageFunction.
                if (imf == null) // not defined in the script
                {
                    imf = FormSupport.getImageFunction(sc);
                }
                else
                if (imf is RayCasting imfray)
                {
                    imfray.Scene = sc;
                }
                imf.Width  = ActualWidth;
                imf.Height = ActualHeight;

                // IRenderer.
                if (rend == null) // not defined in the script
                {
                    rend = FormSupport.getRenderer(superSampling);
                }
                rend.ImageFunction = imf;
                rend.Width         = ActualWidth;
                rend.Height        = ActualHeight;
                rend.Adaptive      = 0; // turn off adaptive bitmap synthesis completely (interactive preview not needed)
                rend.ProgressData  = progress;

                wti[t] = new WorkerThreadInit(rend, sc as ITimeDependent, imf as ITimeDependent, ActualWidth, ActualHeight);
            }

            // Update animation timing.
            time = minTime;
            end  = maxTime;
            if (end <= time)
            {
                end = time + 1.0;
            }

            dt          = (fps > 0.0) ? 1.0 / fps : 25.0;
            end        += 0.5 * dt;
            frameNumber = 0;

            initQueue();
            sem = new Semaphore(0, 10 * threads);

            // Pool of working threads.
            Thread[] pool = new Thread[threads];
            for (t = 0; t < threads; t++)
            {
                pool[t] = new Thread(new ParameterizedThreadStart(RenderWorker));
            }
            for (t = threads; --t >= 0;)
            {
                pool[t].Start(wti[t]);
            }

            // Loop for collection of computed frames.
            int        frames             = 0;
            int        lastDisplayedFrame = -1;
            const long DISPLAY_GAP        = 10000L;
            long       lastDisplayedTime  = -DISPLAY_GAP;
            Stopwatch  sw = new Stopwatch();

            sw.Start();

            while (true)
            {
                sem.WaitOne();            // wait until a frame is finished

                lock (progress)           // regular finish, escape, user break?
                {
                    if (!progress.Continue ||
                        time >= end &&
                        frames >= frameNumber)
                    {
                        break;
                    }
                }

                // There could be a frame to process.
                Result r;
                lock (queue)
                {
                    if (queue.Count == 0)
                    {
                        continue;
                    }
                    r = queue.Dequeue();
                }

                // GUI progress indication:
                double seconds = 1.0e-3 * sw.ElapsedMilliseconds;
                double cfps    = ++frames / seconds;
                SetText(string.Format(CultureInfo.InvariantCulture, "Frames (mt{0}): {1}  ({2:f0} s, {3:f2} fps)",
                                      threads, frames, seconds, cfps));
                if (r.frameNumber > lastDisplayedFrame &&
                    sw.ElapsedMilliseconds > lastDisplayedTime + DISPLAY_GAP)
                {
                    lastDisplayedFrame = r.frameNumber;
                    lastDisplayedTime  = sw.ElapsedMilliseconds;
                    SetImage((Bitmap)r.image.Clone());
                }

                // Save the image file.
                string fileName = string.Format("out{0:0000}.png", r.frameNumber);
                r.image.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
                r.image.Dispose();
            }

            for (t = 0; t < threads; t++)
            {
                pool[t].Join();
                pool[t] = null;
            }

            Cursor.Current = Cursors.Default;

            StopAnimation();
        }