Exemplo n.º 1
0
        public Win32VtkRenderingSurface(IntPtr windowId, bool offscreen)
        {
            _imageBuffer   = new BitmapBuffer(PixelFormat.Format32bppRgb);
            _overlayBuffer = new BitmapBuffer(PixelFormat.Format32bppArgb);
            _finalBuffer   = new BackBuffer();

            _vtkRenderer = new vtkRenderer();
            _vtkRenderer.SetBackground(0.0f, 0.0f, 0.0f);

            _vtkRenderWindow = new vtkWin32OpenGLRenderWindow();
            _vtkRenderWindow.OffScreenRenderingOn();
            _vtkRenderWindow.DoubleBufferOff();
            _vtkRenderWindow.EraseOn();
            _vtkRenderWindow.SwapBuffersOff();
            _vtkRenderWindow.SetDesiredUpdateRate(_dynamicFrameRate);
            _vtkRenderWindow.AddRenderer(_vtkRenderer);

            _dynamicRenderEventPublisher = !offscreen ? new DelayedEventPublisher((s, e) => Render(true, null)) : null;

            WindowID = windowId;
        }
		public Win32VtkRenderingSurface(IntPtr windowId, bool offscreen)
		{
			_imageBuffer = new BitmapBuffer(PixelFormat.Format32bppRgb);
			_overlayBuffer = new BitmapBuffer(PixelFormat.Format32bppArgb);
			_finalBuffer = new BackBuffer();

			_vtkRenderer = new vtkRenderer();
			_vtkRenderer.SetBackground(0.0f, 0.0f, 0.0f);

			_vtkRenderWindow = new vtkWin32OpenGLRenderWindow();
			_vtkRenderWindow.OffScreenRenderingOn();
			_vtkRenderWindow.DoubleBufferOff();
			_vtkRenderWindow.EraseOn();
			_vtkRenderWindow.SwapBuffersOff();
			_vtkRenderWindow.SetDesiredUpdateRate(_dynamicFrameRate);
			_vtkRenderWindow.AddRenderer(_vtkRenderer);

			var delayTime = Math.Min(10000, Math.Max(100, Settings.Default.RendererRefinementDelayMs));
			_dynamicFrameRate = Math.Min(1000, Math.Max(1, Settings.Default.RendererDynamicFps));
			_dynamicRenderEventPublisher = !offscreen ? new DelayedEventPublisher((s, e) => Render(true, null), delayTime) : null;

			WindowID = windowId;
		}
        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");
                }
            }
        }