WPF draw text in ModelVisual3D - wpf

I'm creating WPF application in which I'm drawing a point cloud. Points are made as little cubes. I'd like to sign indexes with numbers near to each "cube-point" (eg. 1, 2, 3, ...) so I want to add text to my 3D View.
This is my xaml part:
<ModelVisual3D x:Name="model">
<ModelVisual3D.Content>
<Model3DGroup x:Name="group">
<AmbientLight Color="DarkGray" />
<DirectionalLight Color="White" Direction="-5,-5,-7" />
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
In code-behind I'm adding GeometryModel3D (built with mesh cube-points) to Model3DGroup (named 'group').
I tried to use this code: http://www.ericsink.com/wpf3d/4_Text.html
but this is very inefficient way and everything works slowly when I generate and display about 7000 (number of cube-points) such textBlocks.
Do you have any idea how to add some text in a more efficient way?

Of course!
The best resouces about majority of WPF 3D features are in
1. Petzold Ch. book: 3D Programming for Windows
2. Jack Xu. Practical WPF Graphics Programming
Simplest way to take WPF 3D text feature is to work with code from the first detected book
http://www.microsoft.com/mspress/companion/9780735623941/

Related

Creating 3D model for SLARToolkit

I am working on an AR based web app where I need to display some product images on a marker. I found SLARToolkit and the samples are working fine. But now I need to display the 3D models of the products instead of sample "3D world and cubes". As I am a developer, I don't have any idea about 3D modeling though I have a designer in my team. Now I need to know, how to convert the images to 3D models that will be placed on the markers? Are there any softwares which can do the conversions?
This si a link that lets you play with 3d effect
3d
and I can suggest you to drop a shadow in silverlight using
<DropShadowEffect Direction="0" BlurRadius="10"
ShadowDepth="1" Opacity="0.6" Color="White" />

Viewport2DVisual3D blurry text on WPF controls

I'm attempting to host a WPF form on a Viewport2DVisual3D surface. I've set up the camera so that the controls fit the width of the window. The default geometry maps the entire form onto a square face, so it is necessary to do some sort of transformation to get the surface to look like a regular 2d form and not appear stretched vertically. The form looks okay overall but the text doesn't scale well, it is blurry and blocky and looks bad in different ways from line to line. Here's what I've tried to set the aspect ratio:
A ScaleTransform3D
Setting the mesh Positions to the proper aspect ratio
Setting the TextureCoordinates to the proper aspect ratio
The first two get me the results that I want, except for the blocky/blurry text. My conclusion at this point is that the font rendering is occurring before the form image is projected onto the 3d surface and then scaling occurs, so it will look bad no matter what. Does anyone know a way to work around this or to set it up right from the beginning? I don't know much about 3d graphics, just enough basic math to get the camera angles right, etc.
Have tested on Win 7 and XP.
Some of the resources I've used:
http://www.codeproject.com/KB/WPF/ContentControl3D.aspx
http://pavanpodila.spaces.live.com/blog/cns!9C9E888164859398!151.entry
A few snippets of the code:
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D x:Name="FrontFaceGeometry"
Positions="-1,1,0 -1,-1,0 1,-1,0 1,1,0"
TextureCoordinates="0,0 0,1 1,1 1,0"
TriangleIndices="0 1 2 0 2 3"/>
</Viewport2DVisual3D.Geometry>
...
<Grid Width="500" x:Name="FrontFaceGrid">
Then in the Window_Loaded routine, e.g.
var aRatio = FrontFaceGrid.ActualHeight / FrontFaceGrid.ActualWidth;
FrontFaceGeometry.Positions[0] = new System.Windows.Media.Media3D.Point3D(-1, aRatio, 0);
FrontFaceGeometry.Positions[1] = new System.Windows.Media.Media3D.Point3D(-1, -aRatio, 0);
FrontFaceGeometry.Positions[2] = new System.Windows.Media.Media3D.Point3D(1, -aRatio, 0);
FrontFaceGeometry.Positions[3] = new System.Windows.Media.Media3D.Point3D(1, aRatio, 0);
To avoid the blurred text and other visual distortions make the 3D XY aspect ratio equal to the 2D control aspect ratio. This is achieved by setting X and Y MeshGeometry3D.Positions. For example, a 2D control sized at 500x700 could be mapped to a rectangle 3D mesh without distortion by assigning positions
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D x:Name="FrontFaceGeometry"
Positions="-2.5,3.5,0 -2.5,-3.5,0 2.5,-3.5,0 2.5,3.5,0"
TextureCoordinates="0,0 0,1 1,1 1,0"
TriangleIndices="0 1 2 0 2 3"/>
</Viewport2DVisual3D.Geometry>
The image of the 2D control displayed within the 3D environment is always "stretched" to the mesh's dimensions.
You will be rendering the WPF form onto a texture on the square and then displaying the square using the GPU's texture engine. Depending on the mode the texture engine is using this could cause blockiness or blurriness (since the texture engine will try to interpolate the texture by default).
Why do you want to render it using a 3D visual and not normally if it is intended to fill the screen?

Silverlight Line Graph with Gradient

I have a series of points which I will turn into a line on a graph. What I want is to give the area under the graph a gradient fill. It would look somewhat similar to a Bloomberg graph like this;
My question really has three parts;
First, how should I fill only the area under the graph?
Second, how do I fill that with a gradient?
Finally, if I have multiple lines on the same graph any area under more than one line should have a greyscale gradient fill, how would you set this up?
My biggest problem is deciding on the data structures to use, I could use many multiple sided shapes (One for each line/ data series) and then tell the brush to draw;
Transparent if it's not in any shape
The colour of one series if it's in one shape (Alpha relative to height to give grad)
Black if it's in multiple shapes (Alpha relative to height to give grad)
Then I'd draw the shapes' boundaries in white afterwards.
Thanks,
Gav
The gradient effect is possible using the free version of Visiblox Silverlight Charts. See the example application 'Hindsight' to see how Visiblox charts can be applied to an application of this context.
I've attached a crude code snippet of the XAML on how to achieve this effect:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:v="clr-namespace:Visiblox.Charts;assembly=Visiblox.Charts">
<UserControl.Resources>
<LinearGradientBrush x:Key="GradientBrush" StartPoint="1.0, 0.0" EndPoint="1.0, 1.0">
<GradientStop Color="AliceBlue" Offset="0.3" />
<GradientStop Color="DarkBlue" Offset="0.7" />
</LinearGradientBrush>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<v:Chart x:Name="Chart">
<v:Chart.Series>
<v:LineSeries x:Name="Series" ShowArea="True" AreaFill="{StaticResource GradientBrush}"/>
</v:Chart.Series>
</v:Chart>
</Grid>
Personally, I would take the action that Hindsight does, removing the area under lines when there are multiple series on the plot area. I think at that point the gradients get in the way of the data, and as you mentioned above, to do something about this incurs a computational cost. This could also lead to misinterpretations of the data so be wary.
In terms of getting your data to the chart, you can use the Visiblox BindableDataSeries to bind your business objects directly onto the chart. :)
Disclosure: I have previously worked as a developer on Visiblox Charts.
Hope this helps!

Get Point3D relative to Mesh in WPF

I have a pretty simple 3D scene that is roughly built up like this:
<Viewport3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup x:Name="Group1">
<GeometryModel3D x:Name="m1">...</GeometryModel3D>
</Model3DGroup>
<Model3DGroup x:Name="Group2">
<GeometryModel3D x:Name="m2">...</GeometryModel3D>
</Model3DGroup>
<Model3DGroup x:Name="Group3">
<GeometryModel3D x:Name="m3">...</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
And basically each of the 3 GeometryModel3D's has its own Mesh, Transforms, etc...
When I do hit testing on the Viewport3D, all I ever get is the point in 3D space that I clicked when I hit something. What I really am after, is the point ON the mesh that I hit in 3D space (not a single Point on the mesh, but rather the Point3D).
The goal for me is to add a new Material to the clicked on Mesh at the exact point that the user clicks. And I cannot do that if I only have access to the Point3D relative to the Viewport3D (because of all the transforms on the meshes etc...)
An example might be that the m1 Geometry is a rectangle like shape, with some slight rotations and transformed up the Y axis so its at the top of the screen.
When I click on the VERY bottom of the mesh, I would like to get the X-Y (Z not needed here) point relative to the local coordinate space of that mesh...
I hope that all makes sense, and thanks for any help you can give
Mark
I think what you're describing is actually two things:
Ray projection: given a hit-point on the 2D representation (i.e., the screen), cast a Ray from that point into your scene. This is alternatively called "Unproject", since it kind of relies on inverting the original screen transformation matrix and choosing some minimum and maximum "depth" values.
Ray/Mesh hit intersection: given a Ray and a Mesh, find where they meet. A slightly generalized variant is Ray/Sphere intersection Ray-Sphere Intersection
Check out this guy's blog, he has all the info I think you'll need:
Daniel Lehenbauer's Blog

Tiling rectangles seamlessly in WPF

I want to seamlessly tile a bunch of different-colored Rectangles in WPF. That is, I want to put a bunch of rectangles edge-to-edge, and not have gaps between them.
If everything is aligned to pixels, this works fine. But I also want to support arbitrary zoom, and ideally, I don't want to use SnapsToDevicePixels (because it would compromise quality when the image is zoomed way out). But that means my Rectangles sometimes render with gaps. For example:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black">
<Canvas SnapsToDevicePixels="False">
<Canvas.RenderTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</Canvas.RenderTransform>
<Rectangle Canvas.Left="25" Width="100" Height="100" Fill="#CFC"/>
<Rectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF"/>
</Canvas>
</Page>
If the ScaleTransform's ScaleX is 1, then the Rectangles fit together seamlessly. When it's 0.5, there's a dark gray streak between them. I understand why -- the combined semi-transparent edge pixels don't combine to be 100% opaque. But I would like a way to fix it.
I could always just make the Rectangles overlap, but I won't always know in advance what patterns they'll be in (this is for a game that will eventually support a map editor). Besides, this would cause artifacts around the overlap area when things were zoomed way in (unless I did bevel-cut angles on the underlapping portion, which is an awful lot of work, and still causes problems at corners).
Is there some way I can combine these Rectangles into a single combined "shape" that does render without internal gaps? I've played around with GeometryDrawing, which does exactly that, but then I don't see a way to paint each RectangleGeometry with a different-colored brush.
Are there any other ways to get shapes to tile seamlessly under an arbitrary transform, without resorting to SnapsToDevicePixels?
You might consider using guidelines (see GuidelineSet on MSDN) and overriding the Rectangles' OnRender methods so that their boundaries line up with the pixel boundaries of the device. WPF uses guidelines to determine whether and where to snap drawings.
Internally, it's exactly what SnapsToDevicePixels is using to ensure that objects line up with the device's pixels, but by placing guidelines manually you'll be able to control when the snapping behaviour is applied and when it is not (so when your image is zoomed all of the way out, you can avoid drawing guidelines, or only draw guidelines where your shapes lie next to other shapes, and rely on WPF's anti-aliasing to take care of the rest). You might be able to do it with an attached property so that you can apply it to any element, though if it's only one type of element (e.g. Rectangle) that you need this behaviour on, it's probably not worth the extra effort.
It seems like Microsoft is aware of this problem, too - WPF 4.0 is expected to feature Layout Rounding, which, like the version in Silverlight, rounds off non-integer values at the Render pass when layout rounding has been enabled.
I guess the gaps are not actual gaps but the stroke that is painted. When you scale it down than you just make the stroke smaller to a point where it is not visible anymore. I tried to paint the stroke in the color of the rectangle wich works just fine on any scale.
&ltPage xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black"&gt
&ltCanvas SnapsToDevicePixels="False"&gt
&ltCanvas.RenderTransform&gt
&ltScaleTransform ScaleX="0.5" ScaleY="0.5"/&gt
&lt/Canvas.RenderTransform&gt
&ltRectangle Canvas.Left="25" Width="100" Height="100" Fill="#CFC" Stroke="#CFC"/&gt
&ltRectangle Canvas.Left="125" Width="100" Height="100" Fill="#CCF" Stroke="#CCF"/&gt
&lt/Canvas&gt
&lt/Page&gt

Resources