/// <summary> /// Animation rendering prolog: prepare all the global (uniform) values, start the main thread. /// </summary> private void buttonRenderAnim_Click(object sender, EventArgs e) { if (aThread != null) { return; } buttonRenderAnim.Enabled = false; buttonRender.Enabled = false; buttonRes.Enabled = false; buttonStop.Enabled = true; lock ( progress ) { progress.Continue = true; } // Global animation properties (it's safe to access GUI components here): time = (double)numFrom.Value; end = (double)numTo.Value; if (end <= time) { end = time + 1.0; } double fps = (double)numFps.Value; dt = (fps > 0.0) ? 1.0 / fps : 25.0; end += 0.5 * dt; frameNumber = 0; width = ImageWidth; if (width <= 0) { width = panel1.Width; } height = ImageHeight; if (height <= 0) { height = panel1.Height; } superSampling = (int)numericSupersampling.Value; if (scene == null) { scene = FormSupport.getScene(); // scene prototype } // Start main rendering thread: aThread = new Thread(new ThreadStart(this.RenderAnimation)); aThread.Start(); }
/// <summary> /// Redraws the whole image. /// </summary> private void RenderImage() { Cursor.Current = Cursors.WaitCursor; buttonRender.Enabled = false; buttonRenderAnim.Enabled = false; buttonRes.Enabled = false; width = ImageWidth; if (width <= 0) { width = panel1.Width; } height = ImageHeight; if (height <= 0) { height = panel1.Height; } superSampling = (int)numericSupersampling.Value; Bitmap newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb); if (scene == null) { scene = FormSupport.getScene(); // scene prototype } IImageFunction imf = FormSupport.getImageFunction(scene); imf.Width = width; imf.Height = height; IRenderer rend = FormSupport.getRenderer(imf, superSampling); rend.Width = width; rend.Height = height; rend.Adaptive = 0; rend.ProgressData = progress; progress.Continue = true; // animation: ITimeDependent sc = scene as ITimeDependent; if (sc != null) { sc.Time = (double)numTime.Value; } MT.InitThreadData(); Stopwatch sw = new Stopwatch(); sw.Start(); rend.RenderRectangle(newImage, 0, 0, width, height); sw.Stop(); labelElapsed.Text = string.Format(CultureInfo.InvariantCulture, "Elapsed: {0:f1}s", 1.0e-3 * sw.ElapsedMilliseconds); setImage(ref outputImage, newImage); buttonRender.Enabled = true; buttonRenderAnim.Enabled = true; buttonRes.Enabled = true; Cursor.Current = Cursors.Default; }
/// <summary> /// Worker thread (picks up individual frames and renders them one by one). /// </summary> protected void RenderWorker() { // thread-specific data: ITimeDependent mySceneTD = scene as ITimeDependent; IRayScene myScene = (mySceneTD == null) ? scene : (IRayScene)mySceneTD.Clone(); mySceneTD = myScene as ITimeDependent; MT.InitThreadData(); IImageFunction imf = FormSupport.getImageFunction(myScene); imf.Width = width; imf.Height = height; IRenderer rend = FormSupport.getRenderer(imf, superSampling); rend.Width = width; rend.Height = height; rend.Adaptive = 0; // turn off adaptive bitmap synthesis completely (interactive preview not needed) rend.ProgressData = progress; // worker loop: while (true) { double myTime; 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; time += dt; myFrameNumber = frameNumber++; } // set up the new result record: Result r = new Result(); r.image = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); r.frameNumber = myFrameNumber; // set specific time to my scene: if (mySceneTD != null) { mySceneTD.Time = myTime; } // render the whole frame: rend.RenderRectangle(r.image, 0, 0, width, height); // ... and put the result into the output queue: lock ( queue ) { queue.Enqueue(r); } sem.Release(); // notify the main animation thread } }