Where can I get started drawing animated geometry in C#? I would like to draw a sort of countdown timer by drawing a partially shaded circle. At start the circle would be fully shaded, at 75% 3/4 of the circle would be shaded and at 0 completely unshaded. I really don't know where to begin with something like this.
If you still don't understand what I need, a lot of games use this sort of animation to represent a "cooldown" on an item or skill. Like a second hand going around a clock, revealing what is beneath it.
WPF is my target application but I imagine I will need to use some sort of GDI api.
You could start out with the drawing examples here, for how to make your pie-like graphic:
http://www.codeproject.com/KB/WPF/PieChartDataBinding.aspx
It looks like they use StreamGeometryContext, along with LineTo and ArcTo.
You could then work on applying an animation to the properties on that graphic, so the "slice" gets bigger over time, by changing the arc length:
http://msdn.microsoft.com/en-us/library/ms752312.aspx#applyanimationstoproperty
You could then wrap this all up nicely in a UserControl, with custom dependency properties, so you can reuse this throughout your app.
Edit: I was thinking you meant the shaded pie like in World of Warcraft. What you want is actually simpler. See can poyrazoğlu's answer for the graphical approach to take (although you really only need the top black circle, if you're going with an opacity approach).
Yes, it's really easy with WPF.
Just create another circle on top of the circle, make that one black, and let a timer update the opacity of the top circle from 1 to 0 by time (or whatever you want).
This is the "easy" way. A more "convenient", or "WPF-style" approach would include Bindings and possibly value conversions, you'll be binding the opacity of the circle to a custom value with a value converter (or decrementing that value, anyway there are lots of ways).
Choose whatever you want. They'll both work.
Related
I have some data that comes via messages to my chart. It's a electric current over time (seconds) chart. How can I change the behaviour of the FitToView mode (or write a different one) so that the plotter doesn't zoom out and scale to fit the whole line graph, but move left instead, showing for example only the 100 last seconds?
I thought of calculating minimums and maximums every message and changing the plotters restraints explicitly but it doesn't seem very optimal. Also due to the fact that I would have to set the restraints in code-behind but all the data is in the ViewModel (using MVVM with caliburn).
Edit: I've found the functionality for this (adding WidthFollowConstraint to the FitToView constraints) but the linegraph gets moved more than the axis and after that it compensates back to where it should be, making the whole graph glitch out on every iteration. How can this be fixed?
Apperently I forgot to answer this.
I made the graph move instead of scale by adding a MinimalSizeConstraint and a FollowWidthConstraint to the ConstraintCollection in the constructor of the D3 Viewport2D class. The names are pretty selfexplanitory. Basically this changes the FitToView funtion of the graph to the desired behaviour
I am writing a geoscience visualization application that uses wpf 3d. The user needs to be able to zoom deep into detail and out quick with minimum resources taken. I've decided to divide my slice (ModelVisual3D) into subrectangles (GeometryModel3D), so that each has it's own texture that changes when the camera zooms in (similar to Google maps).
The problem is that "cracks" are appearing between subrectangles, even though they actually have no empty space between them.
How to hide these? or is there any other way to assign multiple materials with different sizes to one ModelVisual3D?
PS I've tried making the background gray, light-gray, silver and white-smoke. It helps a little, but it's not acceptable. I've also tried overlapping the subrectangles, with no result.
Instead of your current setup you might want to make several textures at different resolutions and switch between these depending on the zoom level. (Mipmaps)
When getting really close you might replace the entire object and switch it for a much smaller one) and use a highly detailed texture.
It will require a bit more pre-processing but you will be able to use a single geometry.
Seems like changing ImageBrush's stretch to Stretch.None and using textures larger than the subsquare helps. Although now I need more precise control over texture coordinates for the surface.
I am looking for ideas to create a WPF Brush with a brushed steel look, similar to the MacOSX Panther style, preferably without resorting to an ImageBrush.
Is there a funky way to use a GradientBrush to create this effect?
Thanks in advance!
I don't know how to do this easily with programmatic brushes, but when I have used Photoshop to create a brushed steel effect, I essentially created noise, then smeared (blurred) it in the direction of the brushing:
http://www.adamdorman.com/tutorials/brushed_steel_tutorial.php
As someone mentioned in comments, you may want to do this, and create some sort of (repeating?) image brush. If you want your brushed steel effect to be programmatically generated, you could write a mean filter to do the blur for you. Generating noise is simple enough :)
An example of implementing a mean filter:
http://homepages.inf.ed.ac.uk/rbf/HIPR2/mean.htm
Modify this to have a Nx1 matrix, or have small (zero) for weights not on the current line, and you will have a horizontal blur.
You could use a rotated LinearGradientBrush with many GradientStops in different grey tones. Well, it's at least an approach. For it to be scalable you would somehow need to make the GradientStops just one pixel wide which probably requires giving the size of the filled object to the brush, I guess. Might become a difficult task, but that's the fate of a real hacker, isn't it?
I do NOT want the system trying to scale my drawing, I want to do it entirely on my own as any attempt to squeeze/stretch the graphics will produce ugly results. The problem is that as the image gets bigger I want to add more detail rather than have it simply scale up.
Right now I'm looking at two sets of stripes. One is black/white, the other is black/white/white. The pen width is set to 1.
When the line is drawn horizontally it's correct. The same logic drawing vertical lines appears to be doing some antialiasing, bleeding the black onto the nearby white. The black/white/white doesn't look as good as the horizontal, the black/white looks more like medium++ gray/medium-- gray.
The same code is generating the coordinates in all cases, the transform logic is simply selecting what offset to apply where as I am only supporting orientations on the cardinals. Since there's no floating point involved I can't be looking at precision issues.
How do I get the system to leave my graphics alone???
(Yeah, I realize this won't work at very high resolution and eventually I'll have to scale up the lines. Over any reasonable on-screen zoom factor this won't matter, for printer use I'll have to play with it and see where I need to scale. The basic problem is that I'm trying to shoehorn things into too few pixels without just making blobs.)
Edit: There is no scaling going on. I'm generating a bitmap the exact size of the target window. All lines are drawn at integer coordinates. The recommendation of setting SmoothingMode to None changes the situation: Now the black/white/white draws as a very clear gray/gray/white and the black/white draws as a solid gray box. Now that this is cleaned up I can see some individual vertical lines that were supposed to be black are actually doing the same thing of drawing as 2-pixel gray bars. It's like all my vertical lines are off by 1/2 pixel--yet every drawing command gets only integers.
Edit again: I've learned more about the problem. The image is being drawn correctly but trashed when displayed to the screen. (Saving it to disk and viewing it on the very same monitor shows it drawn correctly.)
You really should let the system manage it for you. You have described a certain behavior that is specific to the hardware you are using. Given different hardware, the problem may not exist at all, or it may exist horizontally but not vertically, or may only exist at much smaller or much larger resolutions, etc. etc.
The basic problem you described sounds like the vertical lines are being drawn "between" vertical stacks of pixels, which is causing the system to draw an anti-aliased line. The alternative to anti-aliasing the line is to shift it. The problem with that is the lines will "jitter" or "jerk" if the image is moved around, animated, or scaled or transformed in any other way. Generally, jerk is MUCH less desirable than anti-aliasing because it is more distracting.
You should be able to turn off anti-aliasing using the SmoothingMode enum, or you could try to handle positioning yourself. Either way, you are trading anti-aliasing for jittery, jerky rendering during any movement or transformation.
Have a look at System.Drawing.Drawing2d.SmoothingMode. Setting it to 'Default' or 'None' should turn off anti aliasing when doing line drawing. If you're talking about scaling an image without anti aliasing effects, have a look at InterpolationMode. Specifically, you might wish to set it to 'Nearest-Neighbor' which will keep your rectangular blocks perfectly crisp. Note that you will see some odd effects if you scale your image by anything other than whole numbers.
Perhaps you need to align your lines on half-pixel coordinates? A one pixel line drawn at say x = 5 would be drawn on the center of the line, which means it would go from x = 4.5 to x = 5.5. If you want it to go from x = 4 to x = 5 then you'd need to set its coordinate to x = 4.5.
GDI+ has a property: http://msdn.microsoft.com/en-us/library/system.drawing.graphics.pixeloffsetmode.aspx that allows you to control this behavior.
Sounds like you need to change your application to tell the system it is DPI aware so scaling doesn't occur. Here's an article on doing that: http://msdn.microsoft.com/en-us/library/ms701681%28VS.85%29.aspx
I took this WPF-VS2008 ScreenSaver template and started to make a new screen saver. I have some experience with winForms-platform (GDI+) screen savers, so i am little bit lost with WPF.
Background-element for my screen saver is Canvas.
A DispatcherTimer tick is set to 33 msec, which is ~ 30 FPS.
Background-color is just one huge LinearGradientBrush.
On the screen I have (per available screen, on my local computer i have 2) n-Ellipses drawn with randomly-calculated (Initialization) Background colors + Alpha channel. They are all in Canvas's Children collection.
I'm moving those Ellipses around the screen with some logic (every DispatcherTimer tick). I make a move per-ellipse, and then just call Canvas.SetLeft(...) and Canvas.SetTop(...) for each Ellipse.
If N (number of Ellipses) is higher > 70-80, i begin to notice graphics slow-downs.
Now, i wonder, if there is anything i could do to improve the graphic-smoothness when choosing higher N-values ? Can I "freeze" "something" before moving my Ellipses and "un-freeze" "something" when i'm finished ? Or is there any other trick i could do?
Not that i would be too picky about mentioned performance drop downs - becouse when N==50, everything works smooth as it should. Even if Ellipses are ALL in the SAME place (loads of transparency stuff), there are no problems at all.
Have you tried rendering in the CompositionTarget.Rendering event, rather than in a timer? I've gotten impressive performance in a 3D screen saver when using the Rendering event and doing my own double buffering. (See http://stuff.seans.com/2008/08/21/simple-water-animation-in-wpf/ , http://stuff.seans.com/2008/08/24/raindrop-animation-in-wpf/ , and http://stuff.seans.com/2008/09/01/writing-a-screen-saver-in-wpf/ )
You will improve performance if you call the Freeze method on objects that inherit from Freezable - brushes for example.
The reason is that Freezable supports extra change notifications that have to be handled by the graphics system, when you call Freeze the object can no longer change and so there are no more change notifications.
For an example of this notification system, if you create a brush, use it to paint a rectangle (for example) and then change the brush the on-screen rectangle will change color.
It is not possible to unfreeze something once it has been frozen (although a copy of the object is unfozen by default). Double buffering is also enabled by default in WPF so you cannot gain here.
Once way to improve performance if not already done is to use geometry objects such as Ellipse Geometry rather than shapes if you do not need to the all of the events as these are lighter weight.
I also have found this MSDN Article Optimizing Performance: 2D Graphics and Imaging that suggests a CachingHint may help along with some other tips.
Finally ensure that you are using the latest service pack one as it has many performance improvements outlined here