简体   繁体   中英

wpf (too many drawing visuals) cause jittery pan and zoom

in a canvas, i have around 2000 framework element derived items.. which inturn consist of around a total of 12000 drawing visuals. This canvas represents a 2d view of a complex machine. And this canvas has pan and zoom logic.
The drawing comes in a jiffy.. but when the machine/drawing is fully loaded.. then the pan and zoom is very jittery..

I could apply bitmapcache feature in .net4 to make it blazing fast. Then the problem is, when the canvas is zoomed into see the details.. pixel blocks can be seen.. which is very ugly..

Is there any way to speed up this.?


I dont find any reasonable answer for this..

I tried like this.. first i had 10000 framework eleements which represents simple shapes like rectangles and circles.. It was damn slow..

Then i tried one framework element which holds 10000 drawing visuals.. still it was slow..

Then i tried one framework element which contain one drawing visual which contains 10000 drawings.. still it is slow...

I'll start a bounty, I cannot set a bitmapcache all the time, cause the graphic is horrible.

So what I'm doing right now is, at the moment of I right click to do my panning, I convert all my controls with bitmapcache, and when I release the button, I remove the bitmapcache. Like this, it's only hideous when I'm panning, but it's very smooth.

The problem is when I convert everything with bitmapcache (or when I remove it), it takes about 1 second or 2 when I'm completely zoomed out... it's not acceptable to wait that time...

And for the performance, yes we freeze everything we can.

EDIT:

I just tried on a beast computer : dual quad core 3.6ghz, 6GB video card, 16 gb ram, SSD, everything.... and it takes 1 second to convert all the control to cache... if I don't cache it lag a lot

Try using to get the cached bitmap to be created at twice the resolution, so that when you zoom in its less pixelated. Maybe even try 3 times resolution...obviously there will be a memory trade off at some point. Note there is a bitmapcache size limit of 2048x2048.


Otherwise you could implement your own bitmap caching strategy - perhaps implement your own ScrollViewer and IScrollInfo, and create your own cached bitmaps using RenderTargetBitmap, and overlay that bitmap onto your canvas (and detach/hide the other set of visuals) while you are panning and zooming. To avoid the lag of creating the Bitmap (ie rendering all those visuals) when the zoom/pan is started, you could render the "machine" to aa high-resolution image in the background whenever the drawing has been modified, so it is ready to be used immediately.

http://www.codeproject.com/Articles/97871/WPF-simple-zoom-and-drag-support-in-a-ScrollViewer


If the 2d view of your complex machine is readonly/not edited, then you could maybe use Deep Zoom. The tricky bit would be in generating the high resolution images and creating the .dzi file. You'd have to host the .dzi on a webserver though.

http://www.codeproject.com/Articles/128695/Deep-Zoom-for-WPF

Provided you can generate a set of images at the different resolutions, here is how you can join them together to build the .dzi.

http://jimlynn.wordpress.com/2008/11/28/programmatically-create-deep-zoom-collections/

Allows analysis of .dzi file.

http://www.deepzoompublisher.com/Viewer/


Or you could try ZoomableApplication2 which claims to be able to virtualize a million items...this would help when you are zoomed-in to reduce the elements being processed...but not when you are at normal 1:1 view. http://blogs.msdn.com/b/kaelr/archive/2010/08/11/zoomableapplication2-a-million-items.aspx

How are you doing your pan and zoom? If they're being done in a way that invalidates the Canvas's layout then it's possible that you're doing a full Measure and Arrange pass (or just Arrange) on every frame, which slows down very quickly with that many elements. If you can do the manipulations using the Canvas's RenderTransform the layout won't need to be recalculated on every movement.

The other thing to try would be to try to reduce the number of FrameworkElements as much as possible, maybe by having a middle-man that takes a bunch of your current objects and spits out a single Visual to represent all of them in this view. Obviously there won't be the same interaction capabilities doing this, but again I'm not sure of your specific needs.

What about using a Quadtree ?

For (2d) games with huge levels obviously you never draw the whole world, only what can be seen.

Using a Quadtree will allow you to track objects location quite cheaply, later when drawing you only draw objects seen on (Quadtree) nodes visible on your screen. But this needs your own drawing routine.

Here is some code I did of how to find what to draw, https://gamedev.stackexchange.com/questions/29121/organize-a-game-set

Additionally,

Drawing 10K FrameworkElement, 12K DrawingVisual is an order or perhaps two of magnitude too high. If you have to keep these types IMO there should be more drawings per container, this way you will reduce some overhead.

This might interest you (Virtualized WPF Canvas) : http://blogs.msdn.com/b/kaelr/archive/2009/05/21/priorityquadtree.aspx

Personally I switched to OpenGL for high-performance but I reckon this is an extreme solution :-)))

请参阅此处获取具有Pan和Zoom的WPF VirtualCanvas实现,该实现可显示一百万个项目: ZoomableApplication2:百万项

不确定它是否适用于您的代码,但您可以在视觉元素上使用“冻结”来提高性能。

您可以将.NET 4.0与新的CacheMode API一起使用,它将极大地提升性能

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM