WPF 3D: Camera… and rollin’

In trying to port my Offline Maps application to Windows Presentation Foundation I finally started experimenting with WPF.

The ultimate goal is to have a user interface designed with WPF and to view the tiles in a WPF 3D viewport with the possibility to pan, tilt, rotate and zoom, or simply put: travel over the tiles in a 3 dimensional view.

But before all that, I’ll first have to learn WPF. And that is what this series of posts will be all about.

Today, I’ll talk to you about the camera in WPF 3D. To be more specific: the Perspective Camera:

Creation of a 3D scene

I will not be rehashing how to create a 3D scene in WPF. You can find some very good tutorials about that on the internet. One of them is this Windows Presentation Foundation (WPF) 3D Tutorial which teaches you the basics of meshes, triangularisation and normals.

Looking at your scene

The same above tutorial also shows you how you can look at your scene using a persprective camera. You get the chance to experiment with various viewpoints and angles. It does however not fully explain the intercation between the FieldOfView and Position properties of the camera. That’s the gap I’l l try to fill with this tutorial.

The interaction between FieldOfView and Position

What is the field of view and the position of a camera? Well according to the MSDN documentation of the property the field of view for a prespective camera is…

… the horizontal bounds of the camera’s projection between the camera’s position and the image plane.

and the position poperty…

… returns the location of the camera, not the LookDirection on which the camera’s projection is centered.

So, if we visualize this in a picture, we get:
DefinitionFOVandPOS

Now, let’s say we have a cube with sides 20 units and we are looking at it with a perspective camera with following properties:
FieldOfView = 90 degrees
Position = 10 units away from the cube

We have a setup similar to this:

FieldOfView90Position10

The green line represents the projection plane on wich our scene is drawn by WPF. You can see that the projection of the backplane of the cube takes 1:3 of the cubes width and the front of the cube takes up our complete field of view width. This is exactly the same is what we see in the application (which is of course not that supprising):

FieldOfView90Position10App

Now, if we step back further from our cube and set the camera’s position at 20 units away from it, we get following projection:

FieldOfView90Position20

There are a few things to notice here:
First, the front of our cube does no longer take up our complete field of view: we have some space between the sides of our cube and the intersection of our field of view with the projection plane.
Second, the projection of the backplane of the cube no longer is 1:3 of the frontside but now is 1:2.

Again, unsurprisingly, this matches what we see in our application:

FieldOfView90Position20App

Now, if we stay at our current position, but narrow our field of view, we get following projection:

FieldOfView53Position20

Notice how the space at the sides of our cube disappeared. With the field of view being 53 degrees and our position at 20 units from the cube, our field of view border touches again the sides of our cube. Also notice how the ratio of the backplane to the frontplane of our cube didn’t change by changing the field of view alone (thus, in respect with our previous example)

Our application again confirms our expectations.

FieldOfView53Position20App

Conclusion

In conclusion we can state that:

Changing the position of our camera with respect to the subject we are looking at will change the ratio’s of horizontal lines at different depth’s (Z-vallues)

Changing the field of view will not change the ratio’s but will make the subject appear bigger.

Downloads

The code

Links

[1] Windows Presentation Foundation (WPF) 3D Tutorial

Writing code for both the full .NET Framework and the .NET Compact Framework

Porting my Offline Maps application to the .NET Compact Framework, I was in for a big supprise:

I thought it would be simple: I intentionally seperated most of the GUI code from the Business code thinking that I would simply need to port the GUI and everything would be OK.

No sir, that didn’t work…

Problems encountered

The first supprise was that in Visual Studio 2005 you can not set a reference in a Device Application project to a normal .NET library. You must specify a special Class Library project specific to Windows Mobile (I’ ve been using the Windows Mobile 6 Professional SDK).

Secondly, not being used to programming for the .NET Compact Framework, I thought that having explicitly used mainstream classes, a simple recompile for the Compact Framework would suffise. However that didn’t work: apparently you can have equally named classes, but they don’t necessarily have the same methods. The Compact Framework mostly just supports a subset of the full Framework class methods.

Solutions

Looking for solutions I came across this article.
It offers a multitude of solutions from which I mostly used the “one folder, two projects” and “use partial classes”.

Another point to keep in mind is that if you have overloaded methods in a class with versions taking objects and versions taking the bare properties of those objects, sometimes the Compact Framework only supports those taking bare properties.

An example of this last case is a method which takes a rectangle as an argument opposed to a method taking an X and Y coordinate for the position and a Width and Height for the size of the rectangle.

Also, if some classes or methods aren’t supported that can lead to a whole area of functionality not being supported. An example of this are the StartCap, EndCap and LineJoin properties of a pen which are not supported in the Compact Framework. They can require you to implement a complete abstraction layer for your functionality. Fortunately I got a way with a partial class with two different implementations of a “CreateRoundedPen” method.

Something which surprised me the most is that some Environment static properties which after all are meant to enable cross platform development aren’t supported neither.

As an example the Compact Framework does not support the Environment.NewLine property. Weel, at least not in the version I used. I noticed in the Compact Framework 3.5 documentation that it is now supported.

Conclusion

So, cross device development from a single code base does take some preparation. It requires you to think about how to setup your projects folder structure and to read the documentation on classes and methods so to choose the method supported in both platforms.

But what experience, and derived from it tips, do you have?

Links

[1] Share Code: Write Code Once For Both Mobile And Desktop Apps
[2] MSDN documentation on the Environment.NewLine property

Offline Maps: released version 1.1.1.3

I’ve just released version 1.1.1.3 of the application.

The application allows you to download tiles served by google maps and openstreetmap to your harddrive and then view them offline, thus without an internet connection.

Google changed the base URL for the map-tiles which made the previous version unusable.
People with programming knowledge could change the code, but those using the binaries could not use the application for map-tiles.

You can get it at the Offline Maps page

That problem has now been solved.