Thursday, August 26, 2010

Virtual Reality User Interface

Quite recently I finished my Master thesis in Interaction Design together with Fredrik Wendt. Our project was performed at Dynagraph and the task was to create a user interface for a Virtual Reality application geared towards beginner users.

The development was performed in Unity3D, an environment mainly used for game development. Apart from the general features separating Unity from other similar software, one of the main benefits with using Unity for this project was that it uses an Immediate Mode Graphical User Interface. This allowed us to quickly create simple, fully functioning prototypes of the different designs we wanted to try. For anyone looking to make small games on his/her free time, I highly recommend having a look at Unity.

The final result of the project is a set of navigation controls and a menu system with a number of functions available to the user. The navigation system has been designed to be usable for people with very little experience with computers in general. While testing, one of the biggest problems for inexperienced computer users turned out to be the inability to use both hands simultaneously to control the camera. The system therefore has to be controllable using only one hand. Our solution to this problem was to implement a navigation system based on a simple idea: the camera goes where the user points. If the user holds the right mouse button, the camera will move towards the surface the mouse is pointing at. The speed of the movement depends on the distance to the target surface.

The interface contains a number of solutions like the one discussed above, all explained in the master thesis report. The report is available in the Chalmers Publication Library in full for anyone who wants to read it.

Until then, you can have a look at the interface by checking these three videos. The 3D environment used in the videos is an example project that comes with the Unity editor and can also be downloaded here. The first video shows the general navigation while the other two videos show the GUI. I'm sorry about the stressed pace in the videos, but I was having some issues with the capturing software which meant I had to decrease the video file sizes.



The main navigation controls, including moving forwards, backwards, panning, rotating and using hover-camera. The main navigation can be done in two ways:

  • The user can move forwards, backwards and strafe by using the WASD-keys while rotating the camera by holding the left mouse button and moving the mouse, or
  • The user can move towards a target by holding the right mouse button and pointing towards the desired destination. The user cannot move backwards without using the keys (which we found very few users tried to do anyway).

In both modes the speed of the movement is automatically set depending on the distance to the target allowing the user to move at street level as easily as fly between mountain tops. In the video the second mode is used to move around.

The user can also pan the view by holding both mouse buttons and moving the mouse. And finally, the user can enter the hover-camera mode by holding the space bar and left mouse button and move the mouse around. A blue marker shows the center of the hover-camera movement when in this mode.





The interface windows and their functionality are hopefully fairly easy to understand in the video. It should be noted that the example project we use in this demo has no dynamic shadows, which is why very little changes when the user sets a new date and time. The light source is moved accordingly in the sky, but it is hard to see in the demo. For more details on the functionality in the interface I refer you to the project report.

Wednesday, August 25, 2010

Sun Position in C#

I recently needed to calculate the Sun's position in the form of celestial coordinates, in this case Altitude and Azimuth angles. While there are a ton of examples explaining celestial coordinates and giving parts of the calculations, as well as a number of online applications for generating these coordinates, there are very few resources that are understandable to non-astronomers.

Finally after some wrestling I managed to create a function that produces the same output as these two sites:
http://pvcdrom.pveducation.org/SUNLIGHT/SUNCALC.HTM
http://www.usno.navy.mil/USNO/astronomical-applications/data-services/alt-az-world
(In the former, remember to subtract 1 from the hour field if you're calculating the angles for a date during the summer.. this is to account for daylight saving time. I don't remember if that is needed in the latter.

The calculations in my code are closely based on this site. I've tried to give as descriptive variable names as possible, but using the site for reference is still recommended if you want to understand the calculations. Currently the function simply prints the results, so you have to change that part to fit your needs. Note that the hour angle, right ascension and sun declination are also calculated in the function, if you are looking for any of those.

public static class SunPosition
{
    private const double Deg2Rad = Math.PI / 180.0;
    private const double Rad2Deg = 180.0 / Math.PI;

    /*!
     * \brief Calculates the sun light.
     *
     * CalcSunPosition calculates the suns "position" based on a
     * given date and time in local time, latitude and longitude
     * expressed in decimal degrees. It is based on the method
     * found here:
     * http://www.astro.uio.no/~bgranslo/aares/calculate.html
     * The calculation is only satisfiably correct for dates in
     * the range March 1 1900 to February 28 2100.
     * \param dateTime Time and date in local time.
     * \param latitude Latitude expressed in decimal degrees.
     * \param longitude Longitude expressed in decimal degrees.
     */
    public static void CalculateSunPosition(
        DateTime dateTime, double latitude, double longitude)
    {
        // Convert to UTC
        dateTime = dateTime.ToUniversalTime();

        // Number of days from J2000.0.
        double julianDate = 367 * dateTime.Year -
            (int)((7.0 / 4.0) * (dateTime.Year + 
            (int)((dateTime.Month + 9.0) / 12.0))) +
            (int)((275.0 * dateTime.Month) / 9.0) +
            dateTime.Day - 730531.5;
        
        double julianCenturies = julianDate / 36525.0;

        // Sidereal Time
        double siderealTimeHours = 6.6974 + 2400.0513 * julianCenturies;
        
        double siderealTimeUT = siderealTimeHours +
            (366.2422 / 365.2422) * (double)dateTime.TimeOfDay.TotalHours;
        
        double siderealTime = siderealTimeUT * 15 + longitude;

        // Refine to number of days (fractional) to specific time.
        julianDate += (double)dateTime.TimeOfDay.TotalHours / 24.0;
        julianCenturies = julianDate / 36525.0;

        // Solar Coordinates
        double meanLongitude = CorrectAngle(Deg2Rad *
            (280.466 + 36000.77 * julianCenturies));
        
        double meanAnomaly = CorrectAngle(Deg2Rad *
            (357.529 + 35999.05 * julianCenturies));
        
        double equationOfCenter = Deg2Rad * ((1.915 - 0.005 * julianCenturies) * 
            Math.Sin(meanAnomaly) + 0.02 * Math.Sin(2 * meanAnomaly));
        
        double elipticalLongitude =
            CorrectAngle(meanLongitude + equationOfCenter);
        
        double obliquity = (23.439 - 0.013 * julianCenturies) * Deg2Rad;

        // Right Ascension
        double rightAscension = Math.Atan2(
            Math.Cos(obliquity) * Math.Sin(elipticalLongitude),
            Math.Cos(elipticalLongitude));
        
        double declination = Math.Asin(
            Math.Sin(rightAscension) * Math.Sin(obliquity));

        // Horizontal Coordinates
        double hourAngle = CorrectAngle(siderealTime * Deg2Rad) - rightAscension;
        
        if (hourAngle > Math.PI)
        {
            hourAngle -= 2 * Math.PI;
        }

        double altitude = Math.Asin(Math.Sin(latitude * Deg2Rad) *
            Math.Sin(declination) + Math.Cos(latitude * Deg2Rad) *
            Math.Cos(declination) * Math.Cos(hourAngle));

        // Nominator and denominator for calculating Azimuth
        // angle. Needed to test which quadrant the angle is in.
        double aziNom = -Math.Sin(hourAngle);
        double aziDenom =
            Math.Tan(declination) * Math.Cos(latitude * Deg2Rad) -
            Math.Sin(latitude * Deg2Rad) * Math.Cos(hourAngle);
        
        double azimuth = Math.Atan(aziNom / aziDenom);
        
        if (aziDenom < 0) // In 2nd or 3rd quadrant
        {
            azimuth += Math.PI;
        }
        else if (aziNom < 0) // In 4th quadrant
        {
            azimuth += 2 * Math.PI;
        }

        // Altitude
        Console.WriteLine("Altitude: " + altitude * Rad2Deg);

        // Azimut
        Console.WriteLine("Azimuth: " + azimuth * Rad2Deg);
    }

    /*!
    * \brief Corrects an angle.
    *
    * \param angleInRadians An angle expressed in radians.
    * \return An angle in the range 0 to 2*PI.
    */
    private static double CorrectAngle(double angleInRadians)
    {
        if (angleInRadians < 0)
        {
            return 2 * Math.PI - (Math.Abs(angleInRadians) % (2 * Math.PI));
        }
        else if (angleInRadians > 2 * Math.PI)
        {
            return angleInRadians % (2 * Math.PI);
        }
        else
        {
            return angleInRadians;
        }
    }
}

Iridium

I thought I'd show a little bit about a game project I was involved in during my studies. The game is called "Iridium: Twenty million leagues above the sea", a title inspired by Jules Verne as some of you probably guessed. It was developed in a project course at the Interaction Design Master program at Chalmers University of Technology and the project group consisted of five people; Richard Fredriksson, Robert Krantz, Olof Millberg, Fredrik Wendt and me, Mikael Nilsson. The project has been postponed, probably indefinitely, but I thought I'd talk a bit about it anyway.

The game is set in space in a steampunk environment, which basically means a mix between Victorian era, unbelievable steam contraptions and general science fiction elements. The player takes control of the captain of a space ship and must control his ship and crew in order to make a name for himself by trading and fighting pirates.

The video below shows a bit of the game, especially focused on the GUI which was my main responsibility during the development. The code actually drawing the GUI was written by Olof Millberg and reads the GUI widgets and layouts from tables in Lua-files, much as you use XML layout files when creating GUIs in Android. The GUI was also implemented in Immediate Mode, which basically means that the properties of each widget (size, position, graphics and so on) is defined together with the functionality in the update loop instead of a init phase. I highly recommend anyone interested in GUI coding to check out this video at mollyrocket,com (if you haven't already) and give IMGUI a try.

Since I can't stand listening to my own voice there is no voice-over for the video, but hopefully you will enjoy it anyway. The video shows the layout of the ship the player currently has (as seen in the game) with crew members going around performing their duties and chatting with each-other. The video then focuses on the menus, where the player fiddles a bit with the captain character and then spends some time assigning duties to different crew members during different shifts, to make the ship operate smoothly. You also get a glimpse at the mission interface as well as navigation map. Also take note of the pirate attack in the game (the ship goes all red) and the crews "frantic" actions during it.. of course the captain does what any level-headed commander would do during a crisis: he goes to the salon to drink tea.



Sadly there is no music or sound in the video (so you can't hear the alarm or cannon booms). We used license-free music in the game, but right now I can't find the names of the music creators and so I did not want to post their music without giving them credit.. perhaps I'll find their names later and post a new video.

The video was captured using CamStudio.

Arborvisio

Arborvisio is the name of the result of my Bachelor thesis in Computer Science. I performed the thesis together with Robin Rosengren. Looking at the program you wouldn't guess I'm an interaction designer, but the focus this time around was a bit different.

The program is used to display phylogenetic trees which can be used to study relation between different species, proteins and so on. The application’s main use is intended to be together with ClustalW, for analyzing and displaying multiple sequence alignments of proteins and other biological groups. The output format of ClustalW is the Newick format, which basically looks like this (with some line breaks and indentation to make the tree structure more clear):

(
  Bovine:0.69395,(
    Gibbon:0.36079,(
      Orangutan:0.33636,(
        Gorilla:0.17147,(
          Chimp:0.19268,Human:0.11927
        ):0.08386
      ):0.06124
    ):0.15057
  ):0.54939,Mouse:1.21460
);


This particular tree would look like this when drawn in Arborvisio:



As can bee seen the application can draw three different types of trees, a radial tree, a cladogram and a phylogram. The application also allows the user to edit the presentation of the tree, but not the tree itself. An example of a customized radial tree can be seen below.


The application was developed i Java and licensed under GNU but is free for any and all non-profit fiddling. If you want to know more about the project you're also very welcome to read the project report. All these things can be found on the project site. The site is dated and contains documents originally meant for the project supervisor at school, but the code and report can be downloaded there (under download and documentation respectively) while the rest can be ignored.

Who's Mikael??

I'm a guy from Sweden who just finished my Master thesis in Interaction Design and I thought I'd need somewhere to put videos of projects, random pieces of code or just general stuff I want to inflict on the world. This will be, in every sense of the phrase, a work in progress, so I expect to get the general style of this blog together as soon as I've actually got some content.. you'll have to bare with me.