Example #1
0
        public void Render(UpdateOverlayCallback updateOverlayCallback)
        {
            if (_dynamicRenderEventPublisher != null)
            {
                _dynamicRenderEventPublisher.Publish(null, null);

                Render(false, updateOverlayCallback);
            }
            else
            {
                Render(true, updateOverlayCallback);
            }
        }
		private void Render(bool fullQuality, UpdateOverlayCallback updateOverlayCallback)
		{
			lock (_lockRender)
			{
				try
				{
					var mirrored = false;
					var mTime = -1;
					if (_sceneGraphRoot != null)
					{
						_sceneGraphRoot.UpdateSceneGraph(_vtkRenderer);
						mirrored = _sceneGraphRoot.ViewPortSpatialTransform.FlipX ^ _sceneGraphRoot.ViewPortSpatialTransform.FlipY;
						mTime = _sceneGraphRoot.GetMTime();
					}

					_vtkRenderWindow.SetDesiredUpdateRate(fullQuality ? _stillFrameRate : _dynamicFrameRate);

					// decide whether or not to render the VTK layer of the image based on the last modification time of the scene graph
					// do not use the renderer or renderwindow's MTime because they are affected by the update rate change above
					var renderTime = -1f;
					if (mTime > _lastRenderTime)
					{
						var renderClock = _renderClock ?? (_renderClock = new CodeClock());
						renderClock.Clear();
						renderClock.Start();

						var bmpData = ImageBuffer.Bitmap.LockBits(new Rectangle(0, 0, _clientRectangle.Width, _clientRectangle.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
						try
						{
							_vtkRenderWindow.Render();

							// since we just rendered, the correct OpenGL context is still 'current' on this thread so we don't need to makeCurrent
							glReadBuffer(GL_FRONT_LEFT); // select the front buffer
							glDisable(GL_TEXTURE_2D); // according to VTK code, some video drivers have issues with this feature
							glPixelStorei(GL_PACK_ALIGNMENT, 4); // align to 4 byte boundaries (since we're copying 32-bit pixels anyway)

							// now read from the OpenGL buffer directly into our surface buffer
							var pData = bmpData.Stride > 0 ? bmpData.Scan0 : bmpData.Scan0 + (bmpData.Height - 1)*bmpData.Stride;
							glReadPixels(0, 0, _clientRectangle.Width, _clientRectangle.Height, GL_BGRA, OpenGlImplementation.ReadPixelsTypeBgra, pData);

							// OpenGL buffer data is a bottom-up image, and the GDI+ memory bitmap might be top-bottom, so we flip the scan lines here
							if (bmpData.Stride > 0)
								FlipImage(bmpData.Scan0, bmpData.Height, bmpData.Stride);
						}
						finally
						{
							ImageBuffer.Bitmap.UnlockBits(bmpData);

							// only record the last render time for full quality renders only
							if (fullQuality) _lastRenderTime = mTime;
						}

						renderClock.Stop();
						renderTime = renderClock.Seconds;

						// perform a single horizontal flip here if necessary, since the VTK camera does not support a mirrorred view port
						ImageBuffer.Bitmap.RotateFlip(mirrored ? RotateFlipType.RotateNoneFlipX : RotateFlipType.RotateNoneFlipNone);
					}

					if (renderTime >= 0)
					{
						if (VtkPresentationImageRenderer.ShowFps)
						{
							var font = _gdiFont ?? (_gdiFont = new Font(FontFamily.GenericMonospace, 12, FontStyle.Bold, GraphicsUnit.Point));
							var msg = string.Format("FPS: {0,6}", renderTime >= 0.000001 ? (1/renderTime).ToString("f1") : "------");
							ImageBuffer.Graphics.DrawString(msg, font, Brushes.Black, 11, 11);
							ImageBuffer.Graphics.DrawString(msg, font, Brushes.White, 10, 10);

							if (fullQuality)
							{
								msg = string.Format("TTI: {0,6} ms", renderTime >= 0.000001 ? (renderTime*1000).ToString("f1") : "------");
								ImageBuffer.Graphics.DrawString(msg, font, Brushes.Black, 11, 15 + 11);
								ImageBuffer.Graphics.DrawString(msg, font, Brushes.White, 10, 15 + 10);
							}
						}
					}

					if (fullQuality)
					{
						if (_reportRenderingPerformance && _statRenderFrameCount > 0 && _statRenderDuration > 0.000001)
						{
							var avgLowFrameRate = _statRenderFrameCount/_statRenderDuration;
							Platform.Log(LogLevel.Info, "VTKRenderer: LOD FPS: {0:f1} ({1} frame(s) in {2:f1} ms); FINAL: {3:f1} ms", avgLowFrameRate, _statRenderFrameCount, _statRenderDuration*1000, renderTime*1000);
						}
						_statRenderFrameCount = 0;
						_statRenderDuration = 0;
					}
					else
					{
						_statRenderDuration += renderTime;
						++_statRenderFrameCount;
					}

					if (updateOverlayCallback != null)
						updateOverlayCallback.Invoke();

					FinalBuffer.RenderImage(ImageBuffer);
					FinalBuffer.RenderImage(OverlayBuffer);
					FinalBuffer.RenderToScreen();

					EventsHelper.Fire(_invalidated, this, new EventArgs());
				}
				catch (Exception ex)
				{
					Platform.Log(LogLevel.Error, ex, "VTK Rendering Exception");
				}
			}
		}
		public void Render(UpdateOverlayCallback updateOverlayCallback)
		{
			if (_dynamicRenderEventPublisher != null)
			{
				_dynamicRenderEventPublisher.Cancel();

				Render(false, updateOverlayCallback);

				_dynamicRenderEventPublisher.Publish(null, null);
			}
			else
			{
				Render(true, updateOverlayCallback);
			}
		}
        private void Render(bool fullQuality, UpdateOverlayCallback updateOverlayCallback)
        {
            lock (_lockRender)
            {
                try
                {
                    var mirrored = false;
                    var mTime    = -1;
                    if (_sceneGraphRoot != null)
                    {
                        _sceneGraphRoot.UpdateSceneGraph(_vtkRenderer);
                        mirrored = _sceneGraphRoot.ViewPortSpatialTransform.FlipX ^ _sceneGraphRoot.ViewPortSpatialTransform.FlipY;
                        mTime    = _sceneGraphRoot.GetMTime();
                    }

                    _vtkRenderWindow.SetDesiredUpdateRate(fullQuality ? _stillFrameRate : _dynamicFrameRate);

                    // decide whether or not to render the VTK layer of the image based on the last modification time of the scene graph
                    // do not use the renderer or renderwindow's MTime because they are affected by the update rate change above
                    var renderTime = -1f;
                    if (mTime > _lastRenderTime)
                    {
                        var renderClock = _renderClock ?? (_renderClock = new CodeClock());
                        renderClock.Clear();
                        renderClock.Start();

                        var bmpData = ImageBuffer.Bitmap.LockBits(new Rectangle(0, 0, _clientRectangle.Width, _clientRectangle.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
                        try
                        {
                            _vtkRenderWindow.Render();

                            // since we just rendered, the correct OpenGL context is still 'current' on this thread so we don't need to makeCurrent
                            glReadBuffer(GL_FRONT_LEFT);                          // select the front buffer
                            glDisable(GL_TEXTURE_2D);                             // according to VTK code, some video drivers have issues with this feature
                            glPixelStorei(GL_PACK_ALIGNMENT, 4);                  // align to 4 byte boundaries (since we're copying 32-bit pixels anyway)

                            // now read from the OpenGL buffer directly into our surface buffer
                            var pData = bmpData.Stride > 0 ? bmpData.Scan0 : bmpData.Scan0 + (bmpData.Height - 1) * bmpData.Stride;
                            glReadPixels(0, 0, _clientRectangle.Width, _clientRectangle.Height, GL_BGRA, OpenGlImplementation.ReadPixelsTypeBgra, pData);

                            // OpenGL buffer data is a bottom-up image, and the GDI+ memory bitmap might be top-bottom, so we flip the scan lines here
                            if (bmpData.Stride > 0)
                            {
                                FlipImage(bmpData.Scan0, bmpData.Height, bmpData.Stride);
                            }
                        }
                        finally
                        {
                            ImageBuffer.Bitmap.UnlockBits(bmpData);

                            // only record the last render time for full quality renders only
                            if (fullQuality)
                            {
                                _lastRenderTime = mTime;
                            }
                        }

                        renderClock.Stop();
                        renderTime = renderClock.Seconds;

                        // perform a single horizontal flip here if necessary, since the VTK camera does not support a mirrorred view port
                        ImageBuffer.Bitmap.RotateFlip(mirrored ? RotateFlipType.RotateNoneFlipX : RotateFlipType.RotateNoneFlipNone);
                    }

                    if (renderTime >= 0)
                    {
                        if (VtkPresentationImageRenderer.ShowFps)
                        {
                            var font = _gdiFont ?? (_gdiFont = new Font(FontFamily.GenericMonospace, 12, FontStyle.Bold, GraphicsUnit.Point));
                            var msg  = string.Format("FPS: {0,6}", renderTime >= 0.000001 ? (1 / renderTime).ToString("f1") : "------");
                            ImageBuffer.Graphics.DrawString(msg, font, Brushes.Black, 11, 11);
                            ImageBuffer.Graphics.DrawString(msg, font, Brushes.White, 10, 10);

                            if (fullQuality)
                            {
                                msg = string.Format("TTI: {0,6} ms", renderTime >= 0.000001 ? (renderTime * 1000).ToString("f1") : "------");
                                ImageBuffer.Graphics.DrawString(msg, font, Brushes.Black, 11, 15 + 11);
                                ImageBuffer.Graphics.DrawString(msg, font, Brushes.White, 10, 15 + 10);
                            }
                        }
                    }

                    if (fullQuality)
                    {
                        if (_reportRenderingPerformance && _statRenderFrameCount > 0 && _statRenderDuration > 0.000001)
                        {
                            var avgLowFrameRate = _statRenderFrameCount / _statRenderDuration;
                            Platform.Log(LogLevel.Info, "VTKRenderer: LOD FPS: {0:f1} ({1} frame(s) in {2:f1} ms); FINAL: {3:f1} ms", avgLowFrameRate, _statRenderFrameCount, _statRenderDuration * 1000, renderTime * 1000);
                        }
                        _statRenderFrameCount = 0;
                        _statRenderDuration   = 0;
                    }
                    else
                    {
                        _statRenderDuration += renderTime;
                        ++_statRenderFrameCount;
                    }

                    if (updateOverlayCallback != null)
                    {
                        updateOverlayCallback.Invoke();
                    }

                    FinalBuffer.RenderImage(ImageBuffer);
                    FinalBuffer.RenderImage(OverlayBuffer);
                    FinalBuffer.RenderToScreen();

                    EventsHelper.Fire(_invalidated, this, new EventArgs());
                }
                catch (Exception ex)
                {
                    Platform.Log(LogLevel.Error, ex, "VTK Rendering Exception");
                }
            }
        }