Star Names

By
Dave
Project
Published
21 Sep 2010 00:07
Last Modified
3 Jan 2011 13:41

I wanted to add labels to the brighter background stars. Stars are commonly identified using multiple designations, including:

  1. Common names
  2. Bayer names
  3. Flamsteed names
  4. Catalogue identifiers such as Hippacos, Henry Draper etc

In this way, the same star may be referred to as Belelgeuse, α Orionis, 58 Orionis, HIP27989, and HD39801 respectively. Since each designation is used for a varying group of stars, a given star may have a varying number of designations.

I chose to start with Bayer names, since there are a reasonable number of these (approximately 1500), and they would also serve as a good reference to add definitions of constellations and asterisms at a later date. The first step was to build a suitable list, which was greatly helped by the availability in the public domain of cross-references between designations.

I previously discussed a couple of approaches to text rendering for deep sky object labels, and I took a similar approach here. Since I was using wireframe labels, I needed to add a further set of vector definitions for the Greek alphabet. Unfortunately, these characters are not included in the "Modern", "Roman", and "Script" Windows fonts. However, other definitions are available in the public domain, such as the Hershey fonts developed in the 1960s by Dr. A. V. Hershey at the US Naval Weapons Laboratory.

Numeric superscripts are also used in the Bayer system. These may be used to distinguish stars with the same Greek letter, such as (typically optical) binaries, however there are some exceptions such as the chain of stars π1, π2, π3, π4 and π5 Orionis. I therefore needed to further extend the wireframe font rendering to support superscripts. An initial screenshot is shown in Figure 1.

Bayer labels

Figure 1. Bayer star names, in the region of Orion

One of the remaining issues, now highlighted by the larger number of names, is dealing with overlapping labels. Culling labels on the CPU, either by magnitude for wide fields-of-view, or when not visible outside narrow fields-of-view might be a useful approach, and will be investigated at a later date.

Multitouch Game Loop Manipulation Processing

By
Dave
Project
Published
12 Aug 2010 23:05
Last Modified
8 Dec 2012 16:21

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.

Surface 3D Demo Part 2

By
Dave
Project
Published
7 Aug 2010 11:03
Last Modified
13 Jan 2013 18:23

In Part 1 I discussed an simple shader which generated autostereograms from depth maps. The next step was to make the application interactive, so that instead of generating an autostereogram from a static depth-map, an interactive 3D model could be used to generate dynamic autostereograms.

To create a depth-map from a model, I added a pixel shader to return the depth value. A similar example can be found in How To: Create a Depth Texture. In order to obtain a sensible range of depth values, I need to calculate the bounds of the model using bounding spheres. I can then set the near and far planes in my projection matrix to correspond to the closest and furthest points in the model respectively. The depth texture can be extracted by rendering to a render target. It can then be passed as a shader parameter to allow autostereograms to be rendered in real time as the model is manipulated.

One of the main issues with animating an autostereogram is that manipulating the model results in changes across areas of the image which do not correspond to the location of the model itself.1 One way around this distracting side-effect is to use a SIRDS, or Single Image Random Dot Stereogram, and alter the pattern each frame in which the model is manipulated.

Instead of passing a pre-defined pattern texture, I generate a random texture on the CPU as follows:

private Texture2D CreateStaticMap(int resolution)
{
    Random random = new Random();
    Color[] colors = new Color[resolution * resolution];
    for (int x = 0; x < resolution; x++)
        for (int y = 0; y < resolution; y++)
            colors[x + y * resolution] = new Color(new Vector3((float)random.NextDouble()));

    Texture2D texture = new Texture2D(GraphicsDevice, resolution, resolution, 1, TextureUsage.None, SurfaceFormat.Color);
    texture.SetData(colors);
    return texture;
}

The resultant grayscale image is shown below in Figure 1.

SIRDS

Figure 1. SIRDS for animation

1This is exacerbated by my current simplistic stereogram shader, since it doesn't yet implmenent features such as hidden-surface removal (where a part of the model should only be visible by one eye) which in turn leads to additional "echoes" in the image.

Surface 3D Demo Part 1

By
Dave
Project
Published
1 Aug 2010 19:19
Last Modified
13 Jan 2013 18:22

I've always been fascinated by stereoscopic images and their ability to convey depth from just two dimensions, and I was interested to explore their effectiveness in implementing a Surface application for 3D visualisation.

As a multiuser and multidiretional platform, Microsoft Surface is ideal for viewing 2D content. Since stereoscropic images can viewed1 from angles orthogonal to an axis designed to align with the plane of the viewer's eyes, they enable depth perception from two opposing viewing positions on either side of a Surface device.

The first step was to generate a stereoscopic image from a depth-map by implementing a pixel shader to render an autostereogram. My initial algorithm was very basic, and produced images as per the example shown below in Figure 1.

Initial rendering

Figure 1. Initial autostereogram rendering from depth map.

The initial shader takes the following parameters:

  • Depth texture
  • Tile texture
  • Size of tile (number of vertical strips)
  • Depth factor

1In order to perceive a 3D image the viewer must decouple convergence and focusing of their eyes. In order to aid convergence, a disc and ring have been placed at the correct separation. Looking "through" the image results in four shapes (a disc and ring from each eye). The eyes are correctly converged when the two centre shapes "overlap" to give a disc within a ring. At this point the eyes must be refocussed without changing their convergence. Bright light can help, since a contracted iris gives a decreased depth of field.

CAPTCHA Time

By
Dave
Project
Published
22 Jul 2010 23:10
Last Modified
13 Jan 2013 18:20

It's taken a few weeks for the spam-bots to notice my blog engine, but they're now starting to become more active. There are many options in the toolbox for dealing with spam comments, one of which is to add a CAPTCHA. This is a test in which a computer generates a challenge, and then attempts to verify that the response is generated by a human.

There are many CAPTCHA implementations available (reCAPTCHA is a good example), however I though it would be instructive to generate my own. The System.Drawing.Drawing2D namespace got me started, as shown below in Figure 1.

CAPTCHA image

Figure1. Initial CAPTCHA image (enlarged)

The image is generated by a controller action, returning a FileResult object with the appropriate content type. A new image is generated after a configurable interval. There are numerous ways to implement the CAPTCHA check when the comment form is submitted, the simplest of which is to have stored the CAPTCHA data in ASP.NET session state. Given this project is intended as a lightweight, personal blogging engine and that I wouldn't envisage scaling out across multiple servers, this doesn't seem a bad approach for the time-being.

Of course, it's rather sad that I have to use a CAPTCHA, and I apologise for inconveniencing anyone submitting a valid comment.

SEO Results

By
Dave
Project
Published
19 Jul 2010 16:16
Last Modified
3 Jan 2011 01:54

Shortly after implementing the changes to my blog engine as described in the post on Search Engine Optimation, my blog came up as the top result in a Bing search for "Dr Dave", as shown below in Figure 1. Possibly coincidence, but a good outcome nonetheless.

Bing search for Dr Dave

Figure 1. Top search result in Bing!

Still got some way to with Google however, as the same search came 8th overall...

Control Integration

By
Dave
Project
Published
19 Jul 2010 11:13
Last Modified
13 Jan 2013 17:45

There's still some tweaking to do on my radial controls discussed in Part 1 and Part 2 of a previous post, but I wanted to integrate them into the project. I've included a couple of screenshots below. Note that the size of the control has been enlarged for clarity and that the menu structure is purely for test-purposes.

Radial control for boolean settings

Figure 1. Radial control for boolean settings.

Radial control for numeric settings

Figure 2. Radial control for numeric settings.

I decided to render all of the "focus arcs" around the edge of the control, highlighting the relevant arc as appropriate, so that the pointer for numeric values didn't "float" in space when it wasn't adjacent to the currently focussed segment.

The control allows me to define a hierarchical menu structure and update properties using reflection, so it's trivial to add another entry. I can also define min/max ranges, format strings, rates of change when using the keyboard etc. For example, the menu item for "zoom" shown in Figure 2 looks like this:

new MenuItem
{
    FormatString = "Zoom\n{0}",
    PropertyInfo = typeof(Camera).GetProperty("Zoom"),
    Min = 0.0f,
    Max = 45.0f,
    Rate = 1.0f,
    TickFormatString = "0.0",
    ValueFormatString = "0.00",
}

Search Engine Optimisation

By
Dave
Project
Published
16 Jul 2010 17:16
Last Modified
13 Jan 2013 18:17

Search Engine Optimisation (SEO) is an important consideration for any website. In addition to the sitemap already discussed for my blog engine, I'd been meaning to do some further work on SEO and I thought I'd start by downloading the SEO Toolkit and throwing it at my site.

Fortunately, it picked up all sorts of "violations". In order to correct these, and other issues relevant to SEO, I made the following changes:

  1. Corrected HTML formatting issues such as non-closed or improperly-nested tags
  2. Added <meta name="keywords"> and <meta name="description"> tags to the post detail view and post model (and updated my posts with relevant tags and descriptions)
  3. Removed multiple canonical formats when using paging-links. For example, instead of rendering a link to http://drdave.co.uk/blog/?page=1, I just use http://drdave.co.uk/blog/
  4. Issued HTTP 301 (Moved Permanently) status codes for links to my previous blog engine, as discussed in the comments on legacy & not-found links.

These are just some of the potential updates that may help optimise my blog engine for search engines, but they are a good starting point.

A Matter of Controls Part 2

By
Dave
Project
Published
14 Jul 2010 23:53
Last Modified
13 Jan 2013 17:44

In Part 1 I showed some screenshots of a radial dial for controlling settings. I've made the following visual changes:

  • Removed the central buttons and to allow a Surface tag to control the dial position and orientation
  • Adjusted the size and fonts to use a tag 39mm in diameter (a poker chip)
  • Added a label indicating current category above the dial which can also be used to drag the dial with the mouse
  • Added a back button to the last (clockwise) segment to navigate back to the previous category
  • Added a ring to the centre of the dial to indicate dial focus when more than one dial is present. The arc segments around the outside indicate item segment focus for a given dial
  • Added highlighting to show selected or pressed item states
Bool dial

Figure 1. Radial control for boolean settings

Blog Engine Download

By
Dave
Project
Published
11 Jul 2010 16:10
Last Modified
3 Jan 2011 01:54

I thought I'd make available the Blog Engine I've just written using ASP.NET MVC2. This is a lightweight, personal blogging engine, and is being used to run this site. It is intended for use with IIS7 (running in Integrated Mode). Currently it uses XML files for storage, and no databases are required.

The following downloads are available:

  1. Dr Dave's Blog Engine (binaries and ASP.NET pages) (zip'd), 188Kb. Files required to run Dr Dave's Blog Engine.
  2. Dr Dave's Blog Engine (source code) (zip'd), 47Kb. Visual Studio 2010 project for Dr Dave's Blog Engine

To get started with the binaries, follow these steps:

  1. Un-zip the blog engine binaries and ASP.NET pages.
  2. If your website is not on the root web, i.e. http://{domain}, but instead sits under a sub-directory, e.g. http://{domain}/{directory}, update the "VirtualPath" setting in the Web.Config file with the directory, e.g.

    <add key="virtualpath" value="/{directory}">

    Don't forget the forward-slash before (but not after) the directory name.

  3. Change the Title and Subtitle properties, also in Web.Config.
  4. If you would like to change the Author name, update the value in the /App_Data/users.xml file.
  5. Update the feed title and link properties in the site.master file, e.g.

    <link rel="alternate" type="application/rss+xml"
        title="My Title" href="http://{domain}/{directory}/feed" />
  6. Copy the files to your website.
  7. Navigate to http://{domain}/{directory}, and you should see the following:

    front page

    Figure 1. Front page after installation

  8. Click "Sign In". The default username is "admin" with a password of "password".
  9. Click on "Change Password" and change the password. A combination of upper-case letters, lower-case letters and numbers is recommended, with a length of at least six characters.

If you decide to use this engine to run your blog, please keep the "Powered by" link, and I'd be grateful if you could inlcude an acknowledgement.

This project remains under active development as and when bugs are identified, or further features are required and I have the time. Note that I do not have time to support the installation or operation of this blog engine, however I will endeavour to answer questions in comments.

Page