## Using the Matrix3DProjection Class in Silverlight 3

July 23, 2009

Roscoe, N.Y.

About two years ago, I did a blog entry entitled Non-Affine Transforms in 2D?, which used the 3D capabilities in WPF to simulate a 2D non-affine transform. The demo program let you independently grab the four corners of a bitmap and pull them into arbitrary locations.

Early this year, I created a 2D non-affine transform structure for Silverlight in the blog entry
Non-Affine Transforms in Silverlight, and used it to manipulate all the individual *Point* objects in a collection of *Polygons* that contributed to a piece of Office clip art.

All this time, I didn't know that I was priming myself for the new *Matrix3DProjection* class in Silverlight 3. You use this class to apply non-affine 3D transforms to regular 2D Silverlight objects, as is demonstrated by the following program that basically merges the demo programs in the two previous blog entries but is simpler than either of them:

The program lets you choose a big *Button*, a collection of *Polygon* objects defining a piece of Office clip-art, or an *Image* displaying a bitmap of my face and shoulders. Drag the blue dots to deform the element. **The program works best if you maintain a convex quadrilateral!**

Some background: Normally in a 2D graphics system like WPF or Silverlight, you can apply graphical transforms based on combinations of translation, scaling, rotation, and skewing, but these are all *affine* transforms: A rectangle is never transformed into anything other than a parallelogram.

2D graphics transforms are represented as 3×3 matrices, but for affine transforms, the last row of the matrix always consists of the numbers 0, 0, and 1. If those values were changable, non-affine transforms would be available, and you could define transforms that taper the sides of transformed rectangles so the result isn't necessarily a parallelogram.

In 3D graphics, transforms are represented as 4×4 matrices, and non-affine transforms are customarily allowed because they are required for perspective effects. The non-affine transform effectively tapers the size of the image away from the camera. (My book
*3D Programming for Windows: Three-Dimensional Graphics Programming for the Windows Presentation Foundation* goes into much detail on 3D transforms, which is crucial information even if you're not specifically doing WPF 3D. Also, the book could really use a few more sales to convince Microsoft Press to let me write more books in the future.)

Silverlight 3 defines a new *Projection* property on *UIElement* of type *Projection*, an abstract class with two derivatives: *PlaneProjection* (which I haven't worked with yet but seems to create a 3D non-affine transform from 12 settable properties) and *Matrix3DProjection*, which lets you specify the transform directly as a *Matrix3D* object. The *Matrix3D* structure has been imported into Silverlight from WPF, and it is now the only member of the new Silverlight *System.Windows.Media.Media3D* namespace. (The demo program displays the resultant *Matrix3D* defined by the location of the four corners of the deformed element.)

It seems a little strange to be working with a 3D matrix that is only applied to 2D elements, but I think it makes more sense than opening up the existing 2D *Matrix* structure to allow non-affine transforms, or creating a new matrix structure just for this purpose.

Deforming a rectangular object to fit an arbitrary convex quadrilateral is just one application of the new Silverlight 3D transform. The first blog entry cited above discusses the math I've used; the algorithm is implemented in the *CalculateNewTransform* method in MainPage.xaml.cs in the
downloadable source code.