Friday, 3 February 2012

Normal Maps of Coins Part 2

In my last post I produced a normal map of the side of a British pound coin. It was an early attempt at following this normal map tutorial, and the results were passable. But on evaluating the results I also identified some fine tuning I could make to my own technique at the photograph stage to make the edges of the raised areas sharper. This was the result.



On this occasion I did increase the angle of the light, holding it higher above the coin to reduce the shadow length, and as you can see this results in much sharper edges. The benefits of a sharper normal map are instantly visible in the 3D render below.

Unlike the pound coins, which needed a grime effect adding to help define the grooves, the ten pence texture is a shiny metal, with details visible purely from the shape information held in the normal map. Every scratch, dent and line you see here is from the normal map, making it look much more real.

In this image the two pence coin uses the same photos the normal map was generated from, though put through a different process, to create dirty areas and reflective areas on the coin to mimic age and wear.


Full instructions in a future post (when I have more time).

Friday, 27 January 2012

Normal Maps from Photos

Normal mapping is a vital part of 3D modelling and rendering these days. In some cases it take hours off your modelling time, and in others hours off your rendering time (and sometimes both).

A while ago I came across this tutorial about making normal maps from photos. I finally got round to trying it.

Introducing the fruits of my labours - this example of mine is the side of a well worn pound coin.


You don't need Photoshop to do this, and to prove it I used the GIMP image manipulation program to make the normal map, and then applied and rendered in Carrara below.


You can see from this render that it works, but some of the edges need to be sharper.

A brief critique of this attempt shows the angle of the light source was too low when photographing the coin, making long shadows, and positioning the light source slightly higher would shorten the shadows and give sharper less buttery results, but having tested it using the 3D preview mode in the GIMP Normal Map Filter, it isn't half bad, and much quicker than trying to build a high res mesh, or digitally painting a height map for conversion to a normal map using tools like the Nvidia Normal Map Filter.

For some objects you really should give this a try.

Of course, even this early attempt is usable if supported by other channels such as shine and highlight (specular) using a grayscale map based on the same photos as the normal map. I also used the same grayscale map to mix two shades of coin colour to show a diffrence where dirt gets ingrained and where it gets rubbed off and used the same map again to give two levels of reflection because dirt is not as reflective as metal. Combining all these with the normal map brings a whole different level of realism.


I'll explain how I used the same photos as the normal map to make the grayscale specular map that I also used for reflection and grime in a future post.

Tuesday, 18 October 2011

Game Development - High Score Leader Boards in Flash

One way of increasing the repeat appeal of a game, particularly for 1 player games, is to include a leader board of high scores. This gives the player an additional goal of beating their previous best score, allowing them to compete with themselves, and other players, even if the game has only 1 player mode.

As long as your game stores the player's score under the variable "score" this example should provide a good starting point for your own leader board or high score board.

In this example I am using ActionScript 2.0 in Flash.

The Code

The code for this is split into 3 parts. First we create a multidimensional array for keeping the scores and player signatures. Second, we store the score from the game, third we create the leader board that transfers data in and out of the array.

Part 1 - Create a Multidimensional Array

In my game the leader board only shows the top 10 scorers. For each one it displays the score and a 3 character signature from the player.

Before we can store data we need to create the place to store it. In this case I am using a multidimensional array. Multidimensional because I want to store 10 elements (1 for each of the top 10) with 2 data elements (score and signature) per player. Doing it this way allows me to sort them later based on score so I can display them from highest scorer to lowest scorer.

My approach was as follows:

/*NEW ARRAY*/
/*Make a new array object*/
var leaderboard_array:Array = new Array ();
/*'Push' data elements onto the array*/
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});
leaderboard_array.push ({initials:"---", score:"0"});

This code must run only once, run it again and you will add to the end of your array, eventually making it huge.

In effect we create an array of 10 elements, that each contain an array of 2 elements. An array within an array. Using the approach I have, where I have named each 'sub'-element "initials" and "score" means that later I can refer to these directly by name - which makes coding a bit easier to do and debug.

My new array includes pre-coded default values, this means something will display the first time and we don't get a blank leader board.

Part 2 - The Game

Your game is your own. The important thing is that you store the players "score" at the end of the game.

Because the my_array.sort(Array.NUMERIC)in Flash does not work correctly (see here), we cannot use strict datatyping  when we define our variables. So, when you first define the "score" variable, all you need to do is:

var score = 0;

Don't do:

var score:Number = 0;

Or the code won't work later, when we have to treat "score" as a string for sorting.

When the game is over, just make sure you store the player's score in the "score" variable, e.g.:

score = endgamescore;

Part 3 - The Leaderboard

At this point we have an array, and a "score". In this part of the program we need to do the following as essential elements.

a. Test whether the player's latest "score" is greater than the lowest score on the current leader board.
b. If it is, allow the player to input a 3 character signature and store it, along with the "score" in the array replacing the previous lowest score.
c. Sort the array by score so each one is listed in order of greatness.
d. Display the contents of the array in text box to show the leader board to the player.

There is more to it than that, especially since sorting numerically in Flash is not actually possible by direct means - I have gone into detail on that on another post - so much of the code is required to solve that problem.

The following code relies on the stage containing:

1. A text input box with the instance name "initials_txt"
2. A button with the instance name "button_btn"
3. A dynamic text box with the instance name "lb_txt"

The code is then as follows:

/* vars */
/* strict datatyping is off for score and sortscore in order to sort it due to restriction in Flash */
var sortscore = 0;
var initials:String = "";
/*set character limit on input text*/
_root.initials_txt.maxChars = 3;
/*PRE-POPULATE LEADERBOARD WITH CURRENT DATA FROM ARRAY*/
for (var i = 0; i < leaderboard_array.length; i++) {
    _root.lb_txt.text += leaderboard_array[i].initials + " " + leaderboard_array[i].score + "\n";
}
/*ADD NEW SCORE ON SUBMIT*/
_root.button_btn.onPress = function () {
    /* get player name value*/
    initials = _root.initials_txt.text;
    /*convert score to decimals ready for correct sorting*/
    sortscore = score / 10000;
    /*convert score values in array to decimals ready for correct sorting*/
    for (var i = 0; i < leaderboard_array.length; i++) {
        leaderboard_array[i].score = leaderboard_array[i].score / 10000;
    }

    /*sort current board by score - low to high*/
    leaderboard_array.sortOn ("score");
    /*if player score is higher than lowest score on board, replace it with player score and name*/
    if (sortscore > leaderboard_array[0].score) {
        _root.leaderboard_array[0].initials = initials;
        _root.leaderboard_array[0].score = sortscore;
    }
    /*sort again to position the new score and initials correctly in order compared to other scores in array*/
    leaderboard_array.sortOn ("score");
    /*convert all the 'decimaled' scores back again to real scores*/
    for (var i = 0; i < leaderboard_array.length; i++) {
        leaderboard_array[i].score = leaderboard_array[i].score * 10000;
    }
    /*reverse the order of the array to show scores from high to low*/
    leaderboard_array.reverse ();
    /*clear existing text from the leader board text box*/
    _root.lb_txt.text = "";
    /*print new array content to the leader board text box*/
    for (var i = 0; i < leaderboard_array.length; i++) {
        _root.lb_txt.text += leaderboard_array[i].initials + " " + leaderboard_array[i].score + "\n";
    }
};

That's the main thrust of it - read the comments in the code to see what each lump of code is doing. Of course there is scope to develop on this yourself, but I hope this helps. Happy leader board-ing.

Friday, 17 June 2011

Generating QR Codes from the Google Chart API

Quick Reference (QR) Codes are a type of Matrix Barcode capable of storing much more information than your normal stripy barcode.

Many organisations have taken to using QR codes as part of an integrated marketing campaign to store web page URLs, allowing users to capture the 'barcode' on their mobile phone cameras in order to visit the site in a quick and easy fashion.

QR Codes from Google Chart API

The Google Chart API has, among other things, the facility to generate QR codes of all types, encoding within them text, binary data or Kanji strings that you define - up to the maximum data limit of a QR code.

The Google Chart API is very simple to understand and returns a PNG file in response to the parameters you set.

Below I have a JavaScript/HTML implementation of the Google Chart API, that returns a QR code based on the text you input.

Generate a QR Code - JavaScript Implementation of Google Chart API











QR Code Generator Source

The source code for my JavaScript implementation above:



Happy QR Code Generating.

Saturday, 14 May 2011

Editing Vado HD Video With Premiere Elements 7

If like me you have had some frustration trying to get Premiere Elements to work with VADO HD video, without hanging on import, you may find this solution helpful.

When for a recent birthday I was the glad recipient of a new VADO HD pocket video camera, and a new sealed Premiere Elements 7, I was excited to get editing some footage. However I quickly ran into trouble - when importing the VADO footage into Elements it would either hang, or if it did import would apparently have no picture. Worse, because of the way the Elements video library previews video assets from all your projects by default, Elements would fail to start up and hang - purely because some VADO HD footage was in the library.

If Premiere Elements won't start because of a dodgy video file in the library

First, if Elements won't start, or hangs, because you have some incompatible footage in the library the simplest cure is to rename the suspect file, or rename the folder it is in, before you start elements. This will break the link Elements has to the file. Then Elements will start properly and give you a 'file not found' icon where the video thumbnail once was in the library. At this point you can simply click on it in the library and delete it.

Making Premiere Elements read VADO HD video files

In trying to solve this I have tried 2 conversion methods (one using Super, and another using Prism), but either of those means a laborious process of mass conversion, and you end up with duplicate files in different formats, and the converted files are either much larger than the originals, or a lower quality I found.

The best solution was simply to install the K-Lite Codec Pack. The installer checked for conflicting codecs as it went along, giving me the option to remove them automatically (which I did). I used the advanced installer option so I could choose what to install, and selected the "lots of stuff" option so I got pretty much everything - including the all important h.264.

Once installed I ran Premiere Elements, imported a native unconverted VADO HD video file and added it to the timeline with barely a pause in the action.

Forget laborious file conversion - try installing the K-Lite Codec Pack before you do anything else.

Still stuck?

If you still have problems you may find the following helpful:

Batch converting VADO HD
Handbrake Video Transcoder
Converting Video for Premiere

Friday, 29 April 2011

Convert Flash to HTML5 with Adobe Wallaby

.NET magazine reports this month that Adobe has released a "Flash-to-web-standards converter" called Wallaby, that basically takes your FLA file and spits out standards compliant HTML5 with accompanying JavaScript.

I must say I was waiting for Adobe to make a move like this ever since Apple got the mardies and decided to not support the Flash Player on its mobile devices. But I thought it might be a feature of CS6, I didn't expect it to be a free Adobe AIR app that I could download today.

.NET quotes senior product manager at Flash Professional as saying "Wallaby's initial focus is on converting banner ads and simple animations to HTML5, to cater for iOS, but that future development will be driven by consumer requirements..." buy .NET for more info.

So, while not expecting great shakes for some of my more advanced Flash work, I can't wait to see what it can do... I'm going to have a play.

Saturday, 9 April 2011

Experimenting with Sound in Flash - DJ Music Mixer


As soon as I realised the possibilities available with Sound Objects in Flash I realised that you could write a simple sound mixing app using ActionScript.

I started this experiment ages ago, but ran into a problem with the sound I couldn't solve straight away. 18 months later I remember it exists and blow the dust off to find the problem still waiting for me.

Just in case any one else has struggled with the same problem... I now have the solution, or at least know why that particular approach wouldn't work and have an alternative.

Once you set up a Sound Object you can either use attachSound to connect an embedded sound from your document Library, or you can use loadSound to load in an external MP3 file. But... and this is where I went wrong... you can't do both. In other words, if the first time you initialise the sound object you use attachSound you can't later change the sound using loadSound and expect it to behave normally. At least that was my experience.

My experimental app was a 2 channel audio mixer that used 2 Sound Objects, one for each channel. The mixing was done very simply by reducing the volume of one Sound Object while simultaneously increasing the volume of the other. So far so good.

However, for the Sound Objects to properly initialise, (and therefore the volume control code work properly) they needed to have a sound loaded into them straight away. The most obvious solution to me was to use attachSound to connect a sound embedded in the movie. So I made a couple of MP3s of 0 second duration and used those embedded within the app. Fine, the Objects initialised OK.

However, to be useful you need to be able to load external MP3s in, or it's only a 2 song show. And that's where the problem arose, because I would need switch from using attachSound to loadSound after the object initialised, and all of a sudden the volume control stops working as expected.

And that's what stumped me. It was only coming back with fresh eyes that allowed me to spot this discrepancy.

So, how to overcome it?

Simples - use loadSound from the first, but get Flash to load a non-existent sound by getting it to load nothing (e.g. ""). Sure, Flash will error, and complain it can't find the file, but the Sound Object will still initialise correctly - and the error is only visible when you test the movie from within the authoring software, not once exported.

Hey presto, when I load an external sound it all works, because I used loadSound all along and didn't change method later on. My music mixing app finally works.

It's possible there are other factors or other solutions - happy to hear about them, but that's how I got round it.

If it helps, happy to help.