Im having trouble with the Viewbox and Viewport properties of the various brushes.
For
example, in my 3D experiements, I have been creating a VisualBrush from
a TextBlock succesfully, but because this seems to create many
intermediate rendering targets, and because the actual text is
infrequently changing, I thought I would render the text to a bitmap
and use an ImageBrush instead.
Unfortunately, I havent managed to come to grips with how Viewbox and Viewport affect the brush.
Lets say I create a mesh whose texture coordinates range from (0,0) to (1,1).
Now the following code works fine for me, though it does stretch the TextBlock to fill the mesh, which isnt entirely satisfactory.
MeshGeometry3D mesh = CreatePlane(center, axis1, axis2);
TextbBlock block = new TextBlock();
block.Text = "Hello";
VisualBrush brush = new VisualBrush(block);
GeometryModel3D model = new GeometryModel3D(mesh, brush);
The code I would like to use is as follows:
MeshGeometry3D mesh = CreatePlane(center, axis1, axis2);
TextbBlock block = new TextBlock();
block.Text = "Hello";
RenderTargetBitmap bitmap = new RenderTargetBitmap(128, 128, 96, 96, PixelFormats.Default);
bitmap.Render(block);
ImageBrush brush = new ImageBrush(bitmap);
brush.TileMode = TileMode.None;
brush.Stretch = Stretch.None;
brush.ViewboxUnits = BrushMappingMode.Absolute;
brush.ViewportUnits = BrushMappingMode.Absolute;
GeometryModel3D model = new GeometryModel3D(mesh, brush);
What
I havent been able to figure out is some combination of Viewbox and
Viewport and ViewboxUnits and ViewPortUnits that results in anything
sensible being displayed. Its always either way too big or way too
small. I also cant seem to figure out what the difference between Viewbox and Viewport actually are, even from multiple readings of the docs.
I know I need to set them to _something_ to get the results I want, I just cant figure out what it is though. Seems as if there are too many layers of relativity going on here.

TileMode Stretch None still looks stretched?
Tico1177
hi damien,
RE: though it does stretch the TextBlock to fill the mesh, which isnt entirely satisfactory.
try setting *just* the Viewport to a small area.
TileMode
="Tile" Stretch="None" Viewport="0,0,10,10" ViewportUnits="Absolute"in combo with Tile and Stretch it should not then fill the area but be constrained to the viewport to define producing a non-stretched tiled effect.
c
http://www.XpectWorld.com - customised "super-easy to use" Windows Vista based .Net software & consultancy and the Xtensions Customer Xperience Manager database
j!
you seem to know a lot of the viewport and viewbox. Could you tell me if it's possible to prevent dpi resizing, cause I'm experiencing the problem that my 72dpi-image is being resized to a 96dpi-image when it's rendered.
thanks in advance,
Kimme
Aditi A.Kirkole
Hey Damien,
It might help to think of this in 2 seperate steps. First, there is a 2D->2D scale/translate transformation that maps the 0,0,128, 128 Image into texture coordinates. This is what the Viewbox & Viewport describe. Then, there is the 3D texture mapping that maps those 2D texture coordinates onto a mesh.
In 2D, Viewbox & Viewport are all you have. You can think of the Viewbox as the 'selection' box for your Image. For example, if you only wanted a portion of your image to show up, not the entire image, you would change the Viewbox. Since your not interested in that, I'd leave Viewbox & ViewboxUnits alone, because they are setup to select the entire image by-default.
Then, there is the Viewport. In 3D, the Viewport is a 2D rectangle specified in texture coordinates. By default, it covers the entire texture coordinate range of your mesh. You can think of it as the Viewbox's 'destination' rectangle in texture-coordinate units. And by default (Stretch=Fill, ViewportUnits=RelativeToBoundingBox, Viewport=0,0,1,1), your entire image will be mapped to the entire texture coordinate range.
For your scenario that's a good thing. You want u=0, v=0 to coorespond to the upper-left corner of your image, and u=1, v=1 to coorespond to the bottom-right corner (assuming your using texture coordinates in the range 0,0 -> 1,1. If your using texture coordinates outside of this range, then you should set ViewportUnits to 'Absolute' and the Image will map to 0,0,1,1 regardless of what u/v values you set on your verticies).
To recap: Earlier I mentioned it's best to think of this API in 2 steps. The first is the Viewbox->Viewport. We haven't changed any default values on the ImageBrush, and the Viewbox->Viewport transformation is mapping the upper-left corner of the image to u=0, v=0, and the bottom-right corner to u=1, v=1.
Now the slightly trickier part - texture mapping. What you want is a 1-1 mapping from each pixel in your source image to each pixel on your monitor, and all of this after the source image has been mapped onto a 3D mesh. Typically in 3D you don't think of the destination pixels at all, which is why this is tricky.
Here's the ideal scenario, your 'model' scenario if you will: set your mesh verticies such that they are a 2D rectangle exactly 128 monitor-pixels across, with the upper-left vertex having u=0, v=0, and the bottom-right vertex having u=1, v=1.
Basically, you've created a 2D rectangle using a 3D mesh. Because of the way 3D does texture mapping you will always have slight blurring, but it should be pretty clear. Now, if you apply any perspective transformation (e.g., by tilting or deforming the 2D rectangle such that there isn't a 1-1 mapping from source pixels to monitor pixels), you'll get more blurring. The severity of this blurring will be dependent on how far off the source pixels are from the monitor pixels, but that happens any time you map a 2D texture onto 3D mesh.
Hope that helps,
Tim