Monday, October 12, 2009

r CPU completely dry.

x y

M11 M12
M21 M22

x' y'

The transform formulas are:

x' = M11•x + M21•y
y' = M12•x + M22•y

With this 2×2 matrix transform, you can scale in the horizontal direction (by setting M11) or the vertical direction (M22), and you can perform rotation and shear by various combinations of the values of the four cells. The default matrix that performs no transformation has a diagonal of 1's:

1 0
0 1

But there's a problem here: Although you can scale, rotate, and shear, you can not perform the type of transform known as translation, which simply shifts an object to another location on the 2D plane.

The mathematician August Ferdinand Möbius (1790–1868) realized that translation could be included in the 2D transform by adding an extra dimension to make what are called homogeneous coordinates. Basically, two dimensional translation is equivalent to three-dimensional shear. (A more extensive discussion appears on pages 300-306 of my book 3D Programming for Windows.) The transform matrix looks like this (again, using property names of the WPF and Silverlight Matrix structure):

M11 M12 0
M21 M22 0
OffsetX OffsetY 1

Translation factors named OffsetX and OffsetY have been added as a third row. When applying this transform matrix, a two-dimensional point (x, y) is first converted to a three-dimensional point (x, y, 1) on the XY plane where Z equals 1, and than that point is multiplied by the matrix:

x y 1

M11 M12 0
M21 M22 0
OffsetX OffsetY 1

x' y' 1

The 3D point that results from this calculation is also on the XY plane where Z equals 1, so the Z coordinate can simply be ignored. The transform formulas are:

x' = M11•x + M21•y + OffsetX
y' = M12•x + M22•y + OffsetY

This is the standard two-dimensional affine transform supported by the Windows Presentation Foundation and Silverlight. The values in the third column of the matrix are constants and cannot be changed. These values are necessary to keep the entire transform restricted to the XY plane. Consequently, the affine transform can never transform a square into anything other a parallelogram.

But suppose you could change those values in the third column. What would happen? What would a non-affine transform look like?

Here's a hypothetical two-dimensional 3×3 matrix capable of non-affine transforms:

M11 M12 M13
M21 M22 M23
OffsetX OffsetY M33

Just as with the affine transform matrix, we can represent a two-dimensional point (x, y) as a three-dimensional point (x, y, 1) and multiply the point by that transform:

x y 1

M11 M12 M13
M21 M22 M23
OffsetX OffsetY M33

x' y' z'

Now we're in big trouble. We've broken out of two dimensions, or at least the XY plane where Z equals 1, as the transform formulas show:

x' = M11•x + M21•y + OffsetX
y' = M12•x + M22•y + OffsetY
z' = M13•x + M23•y + M33

This is a problem because we're still trying to work in two dimensions, and somehow we have to project that three-dimensional point back on the XY plane where Z equals 1. The standard solution (and perhaps the simplest) is to divide all three coordinates by z':

(x', y', z') → (x'/z', y'/z', z'/z') → (x'/z', y'/z', 1)

Now we're back on the XY plane where Z equals 1, but with a potential problem: Division is involved, so there might well be singularities where z' equals zero, which would result in infinite coordinates. This is what makes the transform "non-affine." By definition, affine transforms do not involve infinity.

Try to get a little intuitive feel for the effect of the third column on the transformed coordinates. By default, M33 is 1; decreasing that value performs an overall positive scaling on the coordinates, and increasing it makes everything uniformly smaller. That's not very interesting, and usually M33 is kept at 1 for convenience. When M33 equals one, a positive value of M13 causes X and Y values to decrease as X gets larger, so that the image tapers in the positive X direction. Similarly a positive value of M23 causes X and Y values to decrease as Y gets larger. Negative values of M13 and M23 cause X and Y values to increase for a reverse tapering.

Silverlight 3 has not introduced a 3×3 matrix where the values of the third column can be set for non-affine transforms. However, Silverlight 3 has lifted the Matrix3D structure from WPF, and made it available for creating Matrix3DProjection objects, which can then be set to the Projection property of 2D Silverlight elements.

As you've seen, 2D graphics requires 3D homogeneous coordinates and a 3×3 matrix to allow translation to be defined along with the linear transforms. Analogously, translation in three-dimensional space is equivalent to skewing in four-dimensional space, so the 3D transform is a 4×4 matrix. These are the property names of the Matrix3D structure:

M11 M12 M13 M14
M21 M22 M23 M24
M31 M32 M33 M34
OffsetX OffsetY OffsetZ M44

A point in 3D space (x, y, z) is represented as a 4D point (x, y, z, 1) for multiplication by the matrix:

x y z 1

M11 M12 M13 M14
M21 M22 M23 M24
M31 M32 M33 M34
OffsetX OffsetY OffsetZ M44

x' y' z' w'

Notice that the fourth dimension is represented by the letter W because we've run out of letters after Z. The transform formulas are:

x' = M11•x + M21•y + M31•z + OffsetX
y' = M12•x + M22•y + M32•z + OffsetY
z' = M13•x + M23•y + M33•z + OffsetZ
w' = M14•x + M24•y + M34•z + M44

Points are projected back into 3D space with the following process:

(x', y', z', w') → (x'/w', y'/w', z'/w', w'/w') → (x'/w', y'/w', z'/w', 1)

Non-affine transforms are required in 3D graphics for perspective effects: Objects seem to get smaller as they recede from the viewer's vantage point. This is a three-dimensional taper transform. Additionally, at some point prior to rendering, all the Z coordinates are collapsed for the two-dimensional video display or printer.

In Silverlight 3, we're not really dealing with 3D space. There aren't even Point3D and Vector3D structures to help us manipulate points in the third dimension. We're really only transforming 2D points of UIElement derivatives. Matrix3D is a bit of overkill for this purpose, but it's a familiar entity (at least to WPF programmers). Conceptually, the two-dimensional coordinate point (x, y) is treated as a four-dimensional coordinate point (x, y, 0, 1) for the matrix multiplication:

x y 0 1

M11 M12 M13 M14
M21 M22 M23 M24
M31 M32 M33 M34
OffsetX OffsetY OffsetZ M44

x' y' z' w'

Notice that the third row of the matrix has no effect on the result. The transform formulas are consequently somewhat simpler:

x' = M11•x + M21•y + OffsetX
y' = M12•x + M22•y + OffsetY
z' = M13•x + M23•y + OffsetZ
w' = M14•x + M24•y + M44

Points are projected back into 3D space normally by dividing by w':

(x', y', z', w') → (x'/w', y'/w', z'/w', w'/w') → (x'/w', y'/w', z'/w', 1)

You might assume that the Z coordinate is simply ignored for rendering these points on the two-dimensional surface of the video display, but that is not the case. My experimentation reveals that any point where the Z coordinate is less than zero, or greater than one, is clipped. I will try to explore this problem and solutions in future blog entries.

For two-dimensional taper transforms, you can leave cells in the third column (as well as the third row) at their default values so the matrix transform looks like this:

Dulce et Decorum Est

Harry Patch, believed to be the last British veteran of the First World War, only in recent years began speaking of his terrifying experiences on the front. He died yesterday at the age of 111. This is a poem written in 1917 by another young English soldier.

Dulce et Decorum Est

Bent double, like old beggars under sacks,
Knock-kneed, coughing like hags, we cursed through sludge,
Till on the haunting flares we turned our backs
And towards our distant rest began to trudge.
Men marched asleep. Many had lost their boots
But limped on, blood-shod. All went lame; all blind;
Drunk with fatigue; deaf even to the hoots
Of tired, outstripped Five-Nines that dropped behind.

Gas! GAS! Quick, boys! — An ecstasy of fumbling,
Fitting the clumsy helmets just in time;
But someone still was yelling out and stumbling
And flound'ring like a man in fire or lime ...
Dim, through the misty panes and thick green light,
As under a green sea, I saw him drowning.

In all my dreams, before my helpless sight,
He plunges at me, guttering, choking, drowning.

If in some smothering dreams you too could pace
Behind the wagon that we flung him in,
And watch the white eyes writhing in his face,
His hanging face, like a devil's sick of sin;
If you could hear, at every jolt, the blood
Come gargling from the froth-corrupted lungs,
Obscene as cancer, bitter as the cud
Of vile, incurable sores on innocent tongues, —
My friend, you would not tell with such high zest
To children ardent for some desperate glory,
The old Lie: Dulce et decorum est
Pro patria mori.

— Wilfred Owen (1893 - 1918)

The Latin at the end is a quotation form Horace meaning "It is sweet and honorable to die for one's country."

F# is built on the .NET type system, and provides access to any type defined in a .NET assembly. Types can also be defined in F# using the keyword ty

Terse Syntax

One of the most striking features of F# code is that it is very terse - ideas can typically be expressed with a small amount of code. There are a few significant language features which contribute to this:

1. Type Inference: F# is strongly typed, like C#, but instead of having to declare the type of variables, parameters and return types, F# uses type inference to determine these automatically. When the types cannot be inferred, type annotations can be supplied in the code, such as in the definition of the modSquared function above.
2. #light: The #light directive in F# allows code to omit begin...end keywords and some other tokens, and instead relies on indentation to indicate nesting. This is similar to languages like Python, and enables the same kind of syntactic lightness that programs in these languages enjoy.
3. Expressions: F# programs are built out of expressions, which can be composed very simply. For example, if is an expression in F#, as opposed to in C# where it is a statement. This can make code simpler, while also enabling a high degree of flexibility.


F# code can use all of the exisiting .NET libraries, such as the Console class used in the code above. But F# also has access to a rich set of F# libraries, providing types that are well suited to functional programming and F# in particular. A few notable libraries:

1. Math: One very useful example is the F# math libraries, representing datatypes such as Vector, Matrix, and BigNum, as well as the Complex numbers used in the code above.

F# comes with an "F# Interactive" toolwindow for Visual Studio, and also a command line interactive shell (fsi.exe). These are tremendously useful for protyping and exploring, and can also be used as a testbed while working on larger projects. As an example (see screenshot below) the code above can be pasted into an interactive shell to execute immediately. If you want to make changes, just edit the code and paste into the interactive prompt again to run the new version.

Taking LINQ to Objects to Extremes: A fully LINQified RayTracer

Not too long ago I blogged about a C# raytracer which took advantage of a lot of C#3.0 language constructs. However, you may have noticed that it did not actually use LINQ query expressions all that much. Well, after discussing this with a coworker on the PLINQ team at lunch one day - I was convinced that it should be possible to express the logic of the raytracer in a LINQ to Objects query. The result is below - a single 60-line LINQ query which captures the complete raytracing algorithm.

[DISCLAIMER: I am by no means suggesting it's a good idea to write code like this. Do so only at your own risk! Just as you *could* write your entire application in one method body, or decide to replace all if statements with virtual method dispatches, doing what I show below is a clear abuse of this language construct. But it's an interesting example to show that there is a lot of expresiveness available in C#3.0 query expressions.]

One Really Big Query Expression!

.NET Framework Multitargeting in Visual Studio 2008 (aka Orcas)

Friday, June 29, 2007 9:54 PM

One of the really great features I worked on for our upcoming release is ".NET Framework Multitargeting" for Visual Studio. This allows you to build applications targeting any of these frameworks using Visual Studio 2008:

* .NET Framework 2.0 - released with Visual Studio 2005
* .NET Framework 3.0 - released with Windows Vista
* .NET Framework 3.5 - will release with Visual Studio Orcas

When targeting .NET Framework 2.0, for example, Visual Studio will try to protect you from using any features that are only available in a higher framework version. This lets you confidently use Visual Studio 2008 for targeting any of these three platforms. New projects can be created targeting any of these frameworks, and projects can later be changed to target a different framework.

Why is this so important?

We've heard over-and-over again from .NET developers about how much harder it is to move to the next framework version than to move to the next Visual Studio version. Upgrading to a new Visual Studio means installing on a few developer machines - upgrading to target a new framework means ensuring that every client of the application has the new framework installed. Because of this, we very often get asked about whether it's possible to target the older frameworks with the newer tools. With Visual Studio 2008 - we're enabling just that.

There's another reason this is important for Visual Studio 2008 in particular. With .NET 2.0, .NET 3.0 and .NET 3.5, we'll have released three framework versions in about 2 years - but only two Visual Studio versions. Because of this - Visual Studio 2008 needs to be a great tool for targeting both .NET3.0 and .NET3.5, and multitrargeting enables this. In addition, we want developers and development organizations to be able to easily move from Visual Studio 2005 to Visual Studio 2008 - and support for multitargeting lowers the barrier to entry - you can continue working on your .NET 2.0 applications in Visual Studio 2008.

A few details...

New Project Dialog

The New Project and New Website dialogs now have an additional UI element to choose the framework version to target. Choosing a target will limit the set of available templates in the dialog. Additionally, templates that are available for multiple targets will be generated with different default references and usings/imports based on the framework target. Out of the box, the defaults are to target .NET3.5 - but, just like other options in the dialog, the choice is "sticky", so if you pick .NET2.0, it'll default to that in the future.

Since some templates are unaffected by the .NET Framework target - the description of the template also mentions whether or not a specific .NET Framework target will be applied.

Project Properties

You can change the framework target of your project at any time through the Project->Properties dialog. If you change the target to a higher framework version, you will be able to use the new API features available in that framework. If you change the target to a lower framework version, any references in your project which are no longer allowed will be disabled (but left in your References list), and compiling your project will likely result in build failures due to the missing assemblies. However, we've tried to ensure that changing to a lower framework is easily reversible.

In C# projects, the drop-down to make these changes appears on the Application tab, for VB projects it appears in the Compiler->Advanced... tab and for C++ projects it appears in the Framework and References section.

Add Reference Dialog

The real heart of multitargeting support is the Add Reference dialog (see "So, how does this work?" below for details).

In the ".NET" tab, references which are not available for the target framework are grayed out and cannot be added. A hover-tip message explains the reason why. All the assemblies that ship as part of the higher frameworks will be grayed out, as will any other assemblies which themselves have references to assemblies in the higher frameworks.

In the "Browse" tab, you can still browse to any assembly, but if that assembly requires a higher framework version than your project, a warning dialog will be presented.

Add New Item Dialog

Some of the items that can be added to a project are dependent on a minimum framework version. For example the "Linq to SQL Classes" item template requires .NET 3.5. The Add New Item dialog thus filters out these items that are not available for the project. Custom or third party templates can also set the framework versions they want to be available in - so that they can integrate correctly into this filtering.


The toolbox provides controls from many different assemblies - some of which may not be available for the framework target of your project. So any controls defined in assemblies which are not available on your target framework will be filtered out of the toolbox. For example, the ElementHost WinForms control which allows WPF interop as part of .NET3.0 is not available in the toolbox when building a WinForms project targeting .NET 2.0.


At the end of the day, .NET framework target is all about deployment prequisites. So in the Prerequisites dialog we've provided a few options for which .NET Framework package to include with your deployment.


Many of the new language features in the .NET languages can be used with any of the available .NET framework targets. So Visual Studio 2008 allows you to use C#3.0, VB9, and VC9 for all projects, including those targeting .NET2.0 and .NET3.0.

Websites are different in this regard - you cannot use the new language features in a web site targeting .NET 2.0 or .NET 3.0. This restriction is in place because Web Sites need to compile on the web server, and this requires that the new compilers be installed on the Web Server. Since these new compilers come as part of the .NET 3.5 framework, this framework is required on the web server to use new language features.


The Visual Studio 2008 Express products have a limited version of multitargeting. All of the infrastructure described above is available - except for the dropdown in the New Project Dialog. This keeps the multitargeting features out of the way for beginning and hobbyist developers - but ensures that projects can continue to move between Express and full versions of Visual Studio as they could in Visual Studio 2005.

So, how does this work?

The three frameworks supported by Visual Studio Orcas are each supersets of one another - instead of being replacements as the previous .NET Framework releases have been. One benefit of this is that .NET Framework Multitargeting can be based just on the available set of references. That is - when you target .NET3.0, the only things you should be prevented from using are those that depend on assemblies in .NET3.5 - and this can be done by ensuring that you don't accidentally reference these assemblies.

There is one caveat to this - called "red bits". These are the changes in the framework that are part of .NET Framework 2.0 Service Pack 1 and .NET Framework 3.0 Service Pack 1, both of which will be released along with Visual Studio 2008. These two service packs are required for .NET3.5 to be installed, and they include a few very targetted additions of new functionality to the .NET 2.0 and .NET 3.0 frameworks. This means that when you target .NET 2.0 in Visual Studio Orcas, you are really targeting .NET 2.0 SP1. This is similar to what happens when you are using Visual Studio 2003 after the .NET Framework 1.1 service pack is installed on your machine - so it's really nothing new. But for those who want to be extra cautious about their framework dependencies, it's somthing to be aware of.

Try it Now!

Orcas Beta1 is available now, and includes almost all of the multitargeting support described above. Take a look and let us know what you think. Orcas Beta2, which will be available later this summer, will include everything described here - along with a ton of other improvements and bug fixes across the rest of Visual Studio 2008 and the .NET 3.5 Framework. As always, send us feedback through Connect.

C#3.0 Session at TechEd2007 - Code Samples

Thursday, June 07, 2007 1:42 PM

I just presented my C#3.0 session at TechEd Orlando titled "DEV346 - Microsoft Visual C# Under the Covers: An In-Depth Look at C# 3.0". The talk introduces the new C# language features and takes a tour behind the scenes of LINQ to Objects to see how C# is used to enable creating rich new kinds of APIs.

Here are the code samples from the talk:

File iconFirstDemo.cs File iconSecondDemo.cs

And here's a little in-line snippet - the results of the first demo:

using System;
using System.Collections.Generic;
using System.Linq;

class Customer
// C#3.0 Feature: Auto-Implemented Properties
public string CustomerID { get; set; }
public string ContactName { get; set; }
public string City { get; set; }

class Program
static void Main(string[] args)
List customers = LoadCustomers();

// C#3.0 Feature: Query Expressions
var query = from c in customers
where c.City == "London"
orderby c.ContactName.Split(' ')[1]
select new { c.CustomerID, c.ContactName };

foreach (var item in query)
Console.WriteLine("{0}, {1}", item.CustomerID, item.ContactName);

private static List LoadCustomers()
// C#3.0 Feature: 'var' - Local Variable Type Inference
// C#3.0 Feature: Collection Initializers
var customers = new List()
// C#3.0 Feature: Object Initializers
new Customer { CustomerID = "ALFKI",
ContactName = "Maria Anders",
City = "Berlin"},
new Customer { CustomerID = "ANATR",
ContactName = "Ana Trujillo",
City = "M?xico D.F."},
// more customers ...
new Customer { CustomerID = "WOLZA",
ContactName = "Zbyszek Piestrzeniewicz",
City = "Warszawa"}

return customers;

Friday, September 25, 2009

Change Text Size in Firefox? How To

Here is a simple fix I didn't see on the menu. Unlike Internet Explorer, Firefox 3+ does not have a View > Text Size menu.

Try going to Tools > Options > Content Tab > Fonts & Colors box

From there you can change the default font to 16, the typical default setting, if you need to reset it.