Sunday 7 November 2010

Week Two - Map design and Development (Continuation)

Map Development

Weekly Targets 

  • Obtain all the data from the RSS feeds required for use with other parts of the site.
  • Finalise the design of the Map
  • Create a fully working prototype of the Map
    I have now developed the code to collect all the data i need to create the first prototype for the map using the exact same methods as before. I also created statements to convert the degrees of the wind direction from numbers to an actual direction such as North and South etc.

    The expanded function for loading and filtering the XML data is as follows

    function rssLoaded(e:Event) {

        trace("loaded "+ userMapArray[u][0]);

        var xml:XML=new XML(e.target.data);

        rssXML=xml.channel;

        rssXML.ignoreWhitespace = true;

        //weatherStringTest = rssXML;

        weatherString = rssXML;

        var weatherArray:Array = weatherString.split(">");

        weatherArray.splice(0,15);

        windString = weatherArray[0];
        visibString = weatherArray[1];
        conditionsString = weatherArray[33];
      
        sunString = weatherArray[2];
        sunsrArray = sunString.split(" ");
      
        sunRiseString = sunsrArray[3];
        sunSetString = sunsrArray[5];
      
        sunRiseString = sunRiseString.replace("sunrise=","");
        sunSetString = sunSetString.replace("sunset=","");
        sunRiseString = sunRiseString.replace(removeText2,"");
        sunSetString = sunSetString.replace(removeText2,"");
      
        trace(sunRiseString);
        trace(sunSetString);
      
        visibString = visibString.replace(removeText,"");
        windString = windString.replace(removeText,"");
        windString = windString.replace("/","");

        visibArray = visibString.split(" ");
        windArray = windString.split(" ");
        conditionsArray = conditionsString.split(",");

        tempString = conditionsArray[1];
        tempString = tempString.replace("F<BR /","");
        tempString = tempString.replace(" ","");
      
      
        trace(tempString);
      
        visibArray.splice(0,4);
        visibArray.splice(1,2);

        windDirString = windArray[4];
      
        if (windArray[4] == 0) {
          
            windDirString = "North";
          
        } else if (windArray[4] >1 && windArray[4] <=45) {

            windDirString = "North East";
          
        } else if (windArray[4] >45 && windArray[4] <= 90) {

            windDirString = "North East";
          
        } else if (windArray[4] > 90 && windArray[4] <= 135) {

            windDirString = "South East";
          
        } else if (windArray[4] > 135 && windArray[4] <= 180) {

            windDirString = "South";
          
        } else if (windArray[4] > 180 && windArray[4] <= 225) {

            windDirString = "South West";
          
        } else if (windArray[4] > 225 && windArray[4] <= 270) {

            windDirString = "West";
          
        } else if (windArray[4] > 270 && windArray[4] <= 315) {

            windDirString = "North West";
          
        } else if (windArray[4] > 315 && windArray[4] <= 360) {

            windDirString = "North";
        }
      
        windArray.splice(0,4);

        conditionsArray.splice(1,1);

        visibString = visibArray[0];
        windString = windArray[0];
        conditionsString = conditionsArray[0];

        userMapArray[u][6] = visibString;
        userMapArray[u][7] = windString;
        userMapArray[u][8] = conditionsString;
        userMapArray[u][9] = windDirString;
        userMapArray[u][10] = sunRiseString;
        userMapArray[u][11] = sunSetString;
        userMapArray[u][12] = tempString;

        windString = windArray[1];

        userMapArray[u][7] = windString;

        u++;

        if (u == userMapArray.length && los == false) {

            addPlaces();
            los = true;
        }
      
        if (u<userMapArray.length) {

            loadMap();
          
        }
      
    }

    The first real problem i came across with the map is populating it using the data retrieved from an XML feed. The main problem is that there is no real way i can retrieve the data "on Mass" and instead have to go through the code individually for each location. For instance if i have twenty locations on the map then flash will read the same code twenty times. This can be a time consuming process so instead of having the data from the map load every time the user wants to swop or change locations, all the data will be retrieved and stored during the loading screen at the very beginning of the users journey. This way even when the data is refreshed and updated the user wont have to undergo any waiting period each time they want to use the map.

    I have decided on parts of the final design for the map such as the functionality available to it, the panel design, creating the map object using away3d instead of blender for memory reasons and the graphic design for the map texture which is placed on the sphere. The colour scheme may change as at this stage as I'm not entirely sure on it.

    The texture for the map is a png file created in photoshop.This is just a first draft of the final design which will have each indivdual countires borders mapped onto it. The design uses some basic filter gallery editing to create the shadowing and glow effect which looks like the following:

    World Map created in photoshop


    The most conventional method of creating the map was by using a sphere, a 3d object in flash which uses a very low amount of memory compared to an object created in blender. The sphere in its basic form is simply a wire frame and needed some kind of graphical input to make it look like an actual map. Adding any type of material uses up memory so the key here was to find a solution which both looks good and doesn't put a huge burden on the frame rate by using up memory.


    A basic wireframe sphere

    With the graphics created it was time to start considering which method i was going to use for attaching my map png to the sphere. I started to experiment with the three major classes used for adding material to 3d objects using away3d. The first was the very simplistic colorMaterial class.Although i already knew i wouldn't be able to use my png file as material using this class i thought it would be worth experimenting with for the following reason. The ColorMaterial class lets you  adds a colour of your choice to the surface of the shape. The positives for using this is that it works perfectly with the shading classes which i intend to use on the map to represent the day and night aspect of the garden  and it uses up very little memory. The shading classes work very effectively with the color material and hopefully it works the same with the bitmapMaterial class that ive decided to use.

    Sphere with colorMaterial attached to it
    Although, after a bit more research, i decided that the bitmap class was going to be the way to go i also experimented with the movieMaterial class. This class allows you to use a regular movieclip as a texture. The major point of this is that the movieclip that's in use keeps its original 2d values but is wrapped around a 3d object. So i could actually have a 2d animation running on the movie clip on the surface of a 3d object  for example simulating the atmosphere and cloud coverage. This would also allow me to create the buttons for each location using the normal  method of adding event listeners to them to represent mouse over and mouse out effects.  So the idea was to create a bitmap and simply use a  movieclip as a holder which worked exactly as planned but its uses a massive amount of memory. The memory used using a colourMaterial added about an extra megabyte to the overall usage rate, the movieclipMaterial added about 200 megabytes to the overall usage rate and caused the frame rate to practically reach a constant 0.


    As stated this was the material class i was going to use.  The bitMapMaterial class  allows you to use an image file (jpeg,gif,png) as the material. Basically what it does is wrap the image around the 3d object, this technique doesnt have the added flexibility of the movieclipMaterial class but it would offer the same result, a 3d sphere with the map design on its surface. The image has to be an exact fit to the sphere other wise it will scale it to increase size or decrease its size. The class also allows you to smooth the material so that the image has no rough edges or any blur added to it. This was by and far the best way to go , there was little added memory so it didn't affect the frame rate, the only down side is the because the image file could be fairly large there is some loading time involved like with any image loaded into flash which will need to be taken into consideration at later date. So this is this class Ive decided to use not only for the map, but for the buttons on the map representing locations which will be mapped to a simple plane and then added to the container which holds the sphere so they all rotate in the same way.


    The sphere with the bitmap applied to it


    The third and final major problem Ive had with the map this week was placing the locations onto the sphere. In conventional 2D there is only an X position and Y position to take into consideration (Horizontal and Vertical). In 3d there is still the X and Y position but there is also the Z position (Depth). So accurately pin pointing a specific position in 3D isn't as straight forward as i expected. Luckily though it is quite straight forward using away3d as they have classes called sceneX, sceneY and SceneZ which work like world coordinates in other 3d packages.  By using a simple event listener to trace back the position of the mouse click, i can retrieve the exact co ordinates of Y X and Z of the mouse position on the sphere which is inside a 3d container. 

    Grabbing the X ,Y and Z coordinates and displaying them in the output panel


    With the 3d map set up  the next step is to add the locations to the sphere which the user could interact with. I decided on a simple roll over roll out effect which will show and remove a panel containing the following data 

    • Country Name
    • City Name
    • Current Conditions
    • Temperature (Fahrenheit)
    • Wind Speed
    • Wind Direction
    • Visibility
    • Sun Rise
    • Sun Set
    • Small graphic of the current weather conditions

    The panel is fairly basic in design and will have no 3d properties or values. All the data within it though is dynamic.Firstly though a simple version of this was created for testing purposes making sure that the data from the array is correct and accurate and that it functions in the correct way.

    An advanced design the of rollover location panel with data

    The final step before testing the proto type was to create a button in the 3d space, an object that the user would be able to roll lover to launch the specific panel.The buttons also had to be 3d so they would rotate when the sphere or map is rotated to keep them in position. Using the same method i used to create the texture for the sphere i simply used a bitmap of a circle as the mesh for a plane which is a two sided square object, then added extra indexes to the array to account for the X ,Y and Z positions of where the button needed to be placed on the sphere. The updated pre indexed array now looks like the following:

    userMapArray[0]=["Aberdeen","Scotland","45.97100469589326","165.26268671548647",
    "-255.60575271249087","10243"];
        
    userMapArray[1] = ["Glasgow","Scotland","56.1913383443454","156.1457014357577","-258.1154902360284",
    "21125"];
       
    userMapArray[2] =["Edinburgh","Scotland","50.13906413553286","157.39541336396513",
    "-258.96572380652304","19344"];



    The ProtoType can be found here
     

    First prototype

     

    No comments:

    Post a Comment