Tile Generation Part 2

By
Dave
2012
May
12
18:15
Posted in

I previously discussed a command-line tool for generating image tiles. I've updated the tool to include an additional parameter for image format. Usage is as follows, and the tool is available for download:

C:\tilegen /?
Generates a directory of tiles from a source image equirectangular projection

TILEGEN [drive:][path]filename level [/S=size] [/D=directory] [/F=filename] [/I=image]

   [drive:][path]filename   Soure image
   level                    Level of detail (0-based)
   /S=size                  Size of tile, default 256px
   /D=directory             Directory format, default level{0}
   /F=filename              Filename format, default {col}_{row}
   /I=image                 Image format (JPEG, PNG, TIFF), default JPEG (Compression=90)

Note that the source image is not scaled so must be correct level and size,
i.e. width (px) = 2 * 2^level * size, height (px) = 2^level * size

C:\>

Tile Generation

By
Dave
2011
Nov
12
18:30
Posted in

I needed to create image tiles to provide textures for level of detail rendering of planetary bodies. After looking around for a bit, I decided to write a simple tool for the job. For equirectangular1 projections, all I needed was to load big images and chop them up into a number of tiles according to a naming convention.

I decided not to support image resizing, as there are plenty of tools available which can do the job with an appropriate filter for the type of image.

The System.Drawing namespace can load big images using Bitmap.FromFile(), providing the image fits into memory, which in practical terms means Windows 64bit. The Graphics.DrawImageUnscaled() method can then be used to draw a tile, providing I maintain the dpi of the source image.

The command-line version is available for download. Usage is as follows:

C:\Tiles>tilegen /?
Generates a directory of tiles from a source image equirectangular projection

TILEGEN [drive:][path]filename level [/S=size] [/D=directory] [/F=filename]

   [drive:][path]filename   Soure image
   level                    Level of detail (0-based)
   /S=size                  Size of tile, default 256px
   /D=directory             Directory format, default level{0}
   /F=filename              Filename format, default {col}_{row}

Note that the source image is not scaled so must be correct level and size,
i.e. width (px) = 2 * 2^level * size, height (px) = 2^level * size

C:\Tiles>

To generate 8x256px tiles at level 1 from an appropriately-named 1024x512px image, I use:

C:\Tiles>tilegen 1024x512.jpg 1
Loading source image...done, 0.02s
Creating folder...done
Generating tile 8/8...done, 0.05s

C:\Tiles>

The optional parameters allow generation of different tile sizes, and output of custom directory and file path names.

1 Equirectangular is also known as Simple Cylindrical and Plate Carrée.

Digital Clock

By
Dave
2011
May
07
17:03
Posted in

I was thinking about approaches for displaying the date and time in XNA applications. The easiest approach is simply to use the SpriteBatch class and render a string, however I wanted to be able to support a display of arbitrary sizes, which can be problemmatic with rasterized fonts.

I could use a set of vector fonts, however I would then have to calculate the vertices dynamically when the date or time changed.

An interesting alternative is to pre-generate the vertices for a digital clock. In this way, I have all the vertices I need in a VertexBuffer and can decide the colors for each segment on the GPU after passing the date and time as an effect parameter. An initial screenshot is shown in Figure 1.

Digital Clock

Figure 1. Digital Clock.

The "on" and "off" colors are set with effect parameters, and in Figure 1 I have used an "off" color to simulate light-bleed in a physical display.

The geometry is configurable with parameters for segment thickness, size of gap between segments, character spacing, seperator width and slant.

Multitouch Game Loop Input Processing

By
Dave
2011
Jan
21
19:37
Posted in

There are multiple potential sources of input for an XNA game component, such as keyboard, gamepad, mouse, Surface multitouch, .NET 4 Touch, etc. Dealing with multpile approaches to gathering input in the Update loop of each component can become complex, and adding support for a new input type further adds to this complexity.

I divided my input handling into two different categories:

  1. Controller-based input such as keyboard and gamepad.
  2. Manipulation-based input such as mouse, Surface multitouch, and .NET 4 touch.

For the latter, I wanted to abstract input handling such that a given game component only had to deal with a custom Manipulator type. In this way, I would be free to change or add input source(s) without affecting the implementation in a game component.

Clearly, different input sources provide different types and degrees of information. Surface multitouch Contacts for example, provide information on size, orientation, type etc, whereas a mouse only provides position. In many cases only position information is necessary, however additional properties can easily be added to the Manipulator type and supported by a game component if available. In this case I decided to sub-class my Manipulator type to the following:

  1. Mouse and finger-touch
  2. Surface Tag contacts
  3. Surface blob contacts

In order to deal with multitouch manipulations, I could process input using my previosuly-discussed Manipulation classes and processor.

The following video demonstrates the use of multiple input sources:

Video 1. Input processing from multiple sources.

Since a mouse can only deliver single-touch input, when demonstrating mouse input in Video 1 I switch the pivot type to "Tracked" in order to be able to demonstrate rotation and scaling, as shown in Figure 1.

Figure 1. Input processing from multiple sources.

Of course, it is unlikely that a scenario mixing both Mouse and Surface input would ever be used in practice, however it serves to illustrate how a game component can handle input in a consistent way, without being aware of the input source. For example, the buttons on the left of the screen are "pressed" using either Surface v1 Contact or a mouse-click, however the buttons only tracking Manipulator state.

A useful application of this approach is the ability to write XNA applications which work with both Surface v1 multitouch input and .NET 4 multitouch (and mouse for single-touch if multi-touch hardware is not available) without any code changes, i.e. multi-platform targetting.

Multitouch Game Loop Inertia Processing

By
Dave
2010
Sep
21
18:11
Posted in

In Part 1 I described a lightweight class to process general multitouch manipulations using a game-loop model in XNA.

A key aspect in bringing realism to a multitouch experience is the use of momentum and inertia. The Microsoft.Surface.Core.Manipulations.Affine2DInertiaProcessor provides this support in an event-driven model. In order to continue the approach of using a game-loop model, I needed to add linear and angular velocities, and expansion rates to my manipulation processor.

Changes in manipulator position occur relatively rarely in relation to the game loop frequency, hence calculating rates of change requires averaging these changes over time. The choice of duration and quantity of these time periods is somewhat subjective, and I settled on 5 samples averaged over a maximum of 200ms. Clearly this leads to a small latency between measured and actual velocities, however the smoothing effect is beneficial.

In order to visualise these rates, both for debbugging and to settle on suitable sampling settings, I added visual indicators of direction and magnitude, as shown below in Figure 1.

Multitouch manipulation

Figure 1. Visualising linear and angular velocities and expansion rates during multitouch manipulation.

With the addition of linear and angular velocities and expansion rates, I could now add a simple inertial processing component which uses these properties as input parameters. This inertial processor uses a simple deceleration algorithm, with configurable rates for translation, rotation, and expansion. The solution is demonstrated in the following video.

Video 1. Multitouch game loop inertia processing.

Note that for gestures such as a flick, where velcity increases rapidly, a time-weighted average may be more suitable for calculating the inertia processor's input parameters, and I'll investigate this at a later date.

Multitouch Game Loop Manipulation Processing

By
Dave
2010
Aug
12
23:05
Posted in

Multitouch Surface support for XNA-based applications is provided via the Microsoft.Surface.Core.Manipulations namespace in an event-driven model. I was interested in investigating general multitouch processing within a game-loop model, i.e. not involving events, and thought it would be instructuve to develop my own class to process manipulations in this way.

In a similar manner to the Affine2DManipulationProcessor, I wanted to support arbitrary combinations of translation, rotation, and scale. Translation is trivial, since it is simply a matter of tracking the changes in each manipulation point between calls and taking the average.

Rotation and scale is a little more tricky, since each of these values are relative to a centre-point, or manipulation origin. Rotation is calculated from the average angle between each point and the origin, and scale is calculated from the average distance. Unlike a mouse cursor, manipulation points come and go, so the key is only to track changes to those points which persist between calls, and then update the positions, origin, distance and angles for the next call.

In order to generalise manipulation points from multiple sources such as mouse, gamepad, Surface Contacts and .NET 4.0 Touch, I created my own Manipulation structure to abstract properties such as ID and position. My input processing can then build a collection of these objects from any relevant source(s) and pass them to my manipulation processor as part of the Update call as follows:

myManipulationProcessor.ProcessManipulators(myManipulators);

The cumulative transforms for translation, rotation and scale (according to the supported manipulation types specified) are then immediately available as properties on the manipulation processor.

In order to test the solution, I wrote a small harness to visualise the manipulation points, and their effect on a reference cross-hair. While I also added support for a mouse (right-click to add/remove points, left-drag to move points), multi-touch hardware is required to test scenarios when multiple points are added, moved, or removed simultaneusly. A screenshot is shown in Figure 1.

Multitouch manipulation

Figure 1. Multitouch manipulation with averaged manipulation origin.

One of the complexities of working with multiple manipulation points is deciding how to determine the manipulation origin. One option is to simply take the average position of each point, as shown in Figure 1. Another option is to introduce a speicific "pivot point" as the origin and use this to calculate scale and rotation. This pivot point can either be fixed, or tracking the object being manipulated. The latter two options are shown in Figures 2 and 3.

Multitouch manipulation

Figure 2. Multitouch manipulation with fixed pivot point.

Multitouch manipulation

Figure 3. Multitouch manipulation with pivot point centered on manipulation object.

The solution is demonstrated in the following video. Each approach for determining the manipulation origin is illustrated using translation, rotation, and scaling manipulations, initially in isolation and then in combination.

Video 1. Multitouch game loop manipulation processing.

This post discusses a sample I put together to allow geospatial telemetry data to be visualised using Virtual Earth. The data itself was collected by driving an Aston Martin DB8 Vantage around a track with a GPS receiver. In addition to the location of the car, basic engine telemetry was captured and synchronised with the position data.

The basic idea was to take the data, and "play back" the drive of the car around the track, layering information on a map such as vehicle position, speed, braking position etc. Multiple data sets can be overlaid on the map for comparison. In order to show the vehicle position, a basic 3D car model was chosen. Virtual Earth supports both 2D and 3D map views, the latter of which gave an opportunity to implement a "virtual helicopter" camera which could follow the vehicle around the track.

Video 1. Virtual Earth geospatial telemetry visualisation.

This video shows a couple of laps of telemetry data. The path taken on each lap is drawn on the map (each in a different colour), and each has its own 3D car model (labeled "A" and "B" respectively). The buttons along the bottom of the screen control the "virtual helicopter" camera position and which car the camera is pointing at, and can be seen in more detail in Figure 1 below.

Camera Positions

Figure 1. "Virtual Helicopter" Camera Positions

Front/Rear

These angles follow the car a short distance above and in front of/behind respectively.

Above/Blimp

This angle is directly above the car at a low/high altitude respectively.

Fixed

This setting fixes the camera at its current point in space, but points to the selected car.

In Car

This setting sets the camera position to be "inside" the car, and points the camera in the direction that the car is traveling.

Free

This setting allows the user to freely move the camera.

As an aside, during development of this sample I initially only had access to a couple of models in .x format. Until I managed to find a suitable model for the car, I had to use the following:

Initial Actors

Figure 2. Initial Actors

Initially it was helpful to add some axes to the models so I could ensure they were oriented correctly - you can see these in Figure 2. I also experimented with transparency for "ghosting" the model(s) which didn't have focus:

Ghost Actors

Figure 3. Ghost Actor(s)

The cube shown in Figure 3 was used as a visual marker (also with axes) to show the camera position when I was in a "Free" camera mode. This was really helpful in ensuring the camera was positioned and tracking objects correctly.