Java

I’ve been getting back into Java in my spare time recently, as I think about possibly making a few Android games. These are some notes about the differences between Java and C++.

  • In Java (almost) everything is an object. Strings, Floats and Ints are first class types.
  • In C++ we usually don’t have to stress too much about performance. We can usually afford to do extra processing, create and pass around as many temporaries as we like, use extra ram and hold onto large amounts of ram. Java dies if you use too many temporaries. Performance in Java is highly reliant on the algorithms used.
  • Java benefits from lazy initialisation, not doing anything you don’t need to until you need to.
  • Caching previous results (But not holding onto excessive amounts of ram).
  • Reducing number of temporaries by using classes such as StringBuilder.
  • Java is fun to use. Like a strict C++. Strict in a good way. It is how C++ should have been created. Unfortunately the C++ standards committee decided that backwards compatability was a higher priority than creating awesomeness.
  • The built in libraries are pretty good. I can still write algorithms quicker in C++ but there is a lot more extra functionality in the standard Java libraries such as regular expressions, file system, networking, threads, gui and sql. This is changing slightly with C++0x, but it still lacks basic things such as XML parsing, sql and anything related to gui.
  • Each file can only contain 1 public class. This enforces good structure on your API, “what is the public interface going to be?”, where in C++ a lot of APIs just throw all classes in the header and allow the user to do whatever they want.
  • Using classes from other files is less broken. The lack of including is a good thing although packages and import are basically the same as namespaces and include/using.
  • Being forced to catch exceptions is great, the compiler makes sure that you are doing something with the exceptions later. If you throw or rethrow an exception you then have to mark your function as “throws ” so that the exception and catching the exception propogates up the call stack. The best part about this is that the compiler then knows exactly where an exception should be handled and produces an error if you haven’t handled it or rethrown it.
  • I miss const. There is final but it isn’t quite the same.
  • I miss for example operator overriding. Some built in classes such as String, Array, Vector, etc. could definitely benefit from it. buffer[0] is easier for me to write and understand at first glance than buffer.get(0).  Geometric vector and matrix classes could definitely benefit from operator overloading too for example a = b + c can be understood instantly, a.Add(b, c) is a bit awkward and I have to think about it, “a is being modified, right, b and c are left unmodified, right?”.
  • I miss complex macros and ifdef/ifndef. These can be very helpful, for example using one class on one platform and another class on the other or sharing all the code in a class except for a few lines that are different. Apparently the JVM should be good enough that you can branch on the platform and use oop to change functionality and not lose too much performance. I’m not sure what the replacement is though for a part of your application that just doesn’t compile on other platforms because it uses a platform specific API.

Version Control 2.0

GitHub is a pleasure to work with. In 10 years I created 5 or 6 projects on SourceForge, I’ve already created 3 new projects in less than a year on GitHub because they are just so easy to setup. An early design decision for SourceForge was to make deleting projects hard. The idea was that a project should never die, just “retire” until a new maintainer comes along. I don’t think I have users of my libraries or applications let alone prospective maintainers (Actually, I have had a few emails and bug reports for GetFree and it has had quite a few downloads, but that was when it was new and exciting). I wish I could change my projects’ statuses to “unmaintained”. After 1 or 2 years of being unmaintained, if it hasn’t been adopted by another user then after a warning email it should be automatically deleted. There are no orphaned projects on SourceForge, only projects that the owner lets stagnate.

Anyway, this post isn’t about SourceForge’s flaws, it is about GitHub. Half of GitHub’s success is due to using Git. There is a very handy application which works in tandem with git, called git-svn which makes migrating from svn painless. You can setup mappings from svn users to git users, clone an svn project into a git project with full history and for those that have to use legacy svn repositories, it can even commit back to svn. Once you get your application into GitHub though you will probably want to stick with git. This is where the fun begins.

You can fork other projects in seconds, work on your own branch for a bit (Fixing bugs, implementing new functionality, etc.) and then send a pull request to have the owner merge your changes back again (And merging has been fixed in git, unlike svn, it doesn’t make me groan any more). GitHub keeps a record of where a project originated and can generate nice graphs of where projects were forked and merged, as well as statistics about which languages were used, when each developer typically commits, as well as all the basics such as bug tracking, web view of the repository, and activity logs for each project and each user.

Join Me

No root file system is defined

On the weekend I was installing the new version of Mythbuntu (More interesting screenshots here) and I had a weird error, “No root file system is defined”. At first I thought it must have been something to do with failing to recognise the existing partitions or possibly they were corrupt. “fdisk -l” worked, returning sda, sda1-sda4, which was correct however “mount” would always fail. It turned out that it was just our old friend dmraid was breaking in new and unexpected ways. Here is how to worked around it:

Boot into live CD mode
Remove dmraid via Package Manager
Run Install Mythbuntu from the desktop shortcut

On multiple distributions and motherboards I consistently have problems with dmraid not finding/incorrectly identifying partitions/drives. I’m not the only one with these problems. I’m sure I am having these problems because I have raid hardware but am not using raid. Surely raid is an advanced enough feature that people with raid should be expected to know to install/add it? Perhaps the install could be attempted without raid support and the installer can say “Do you use raid?” or “Are these devices correct?” and at this point the installation restarts/redetects with dmraid enabled.

How To Automatically Download All of Your YouTube Favourites

FireFox add-ons such as 1-Click YouTube Video Download are good but one must visit every video and manually save it. I have a lot of favourites and I wanted to back them up with as little effort as possible. Here is how.

You will need youtube-dl. It is available via yum/apt-get however the version provided may be quite old (In Fedora 14 it did not support –playlist-start and –playlist-end).

Create a new playlist and add all the videos from your favourites (Note: A playlist can only contain 200 videos if you have more than than this you will have to make multiple playlists and repeat this process for each one).

Click on “Play All”. Copy the URL from the address bar for the first video when it tries to play (You only need this bit: “http://www.youtube.com/view_play_list?p=AE198A14013A3005”).

Now tell youtube-dl to download the videos in the playlist:

python ./youtube-dl.py --title --ignore-errors --playlist-start=1 --playlist-end=200 http://www.youtube.com/view_play_list?p=AE198A14013A3005

If you had more than 200 videos repeat this process for the ones that didn’t fit in the playlist.
This should work for other people’s playlists too.
You might want to make a note of the latest video in your favourites so that the next time you can backup only the new videos.
This process still requires some user interaction, if you find an even easier way where I can just say, “This is my user name, make it happen”, I’d love to know about it.

Git: Review the Changes in a file and Optionally Revert A Particular Change

# Review all the changes in a file, giving us a chance to revert a particular change
git checkout -p path/to/file/to/partially/revert

Note to self: Move this to a useful Git tips post.

malloc double free/non- aligned pointer being freed set a breakpoint in malloc_error_break to debug

malloc: *** error for object 0x3874a0: double free
***set a breakpoint in malloc_error_break to debug

malloc: *** error for object 0x18a138: Non- aligned pointer being freed
*** set a breakpoint in malloc_error_break to debug

So basically something in your code is screwing around with memory.

Either releasing something that has already been released:

int* x = new x[10];
delete [] x;
delete [] x;

Or releasing something that is not pointing to the start of an allocated block of memory:

int* x = new int[10];
x++;
delete [] x;

The error message isn’t very clear if you have no experience with GDB. GDB is a debugger for your binaries. It allows you to set break points at the start of a function and any time that function is called your application will pause and allow you to debug in GDB. We can then get valuable information back by executing commands to get the backtrace, registers state and disassembly. The advantage of using GDB over Xcode/KDevelop is being able to break into any function, not just functions in your source code. Anyway, this is how I got the backtrace to find out where in my sourcecode I was making a mistake:

gdb
file myapplication
break malloc_error_break
run
backtrace

Now whenever a double free or non- aligned pointer is freed it will break into gdb and we can type in “backtrace” and work out what our code did to trigger this.

Cannot open /dev/sda1: Device or resource busy

After an update (Upgrade?) a while ago I couldn’t boot into Fedora, it had the text mode bar graph and after getting to 100% it failed with this error message:

Cannot open /dev/sda1: Device or resource busy

It turned out that this was a dmraid problem. It would appear that something changed when updating and added or enabled dmraid. So I had to find a way to remove or disable it, the simplest solution I found that worked was disabling it via the arguments to the kernel in GRUB.

Edit menu.lst (Or grub.conf, my menu.lst is a symbolic link to grub.conf)

su
gedit /boot/grub/menu.lst

Find the entry that you are currently booting into and add “nodmraid” to the end of the “kernel” line:

	kernel /vmlinuz-2.6.31.6-166.fc12.x86_64 ro root=UUID=7129c2cc-03c5-4b7a-8472-bb9d314446b3  LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us rhgb quiet nodmraid

I also like to add a timeout and remove hiding of the menu (This is in the general entry at the top of the file):

timeout=10
#hiddenmenu

My final menu.lst/grub.conf file looks like this:

default=0
timeout=10
splashimage=(hd0,1)/grub/splash.xpm.gz
#hiddenmenu
title Fedora (2.6.31.6-166.fc12.x86_64)
	root (hd0,1)
	kernel /vmlinuz-2.6.31.6-166.fc12.x86_64 ro root=UUID=7129c2cc-03c5-4b7a-8472-bb9d314446b3  LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us rhgb quiet
	initrd /initramfs-2.6.31.6-166.fc12.x86_64.img

Why Chris, your grub.conf is so puny, only one entry in it. Leave me alone, I only just reinstalled.

How to Find and Remove Folders Recursively in Linux/Unix Because I Always Forget This

# Recursively search for folders called .svn and delete them (Even if not empty)
find . -name .svn -type d -print | xargs rm -rf
 
# Recursively search for files called *~ (gedit creates these for temporarily saving to) and delete them
find . -name \*~ -print | xargs rm -rf
 
# Recursively search for files called *.h or *.cpp and print them
find -name '*.h' -o -name '*.cpp' -print

Blender Export OBJ Python Script

First of all I’d like to state that I’m definitely a Blender n00b and I have never touched Python in my life.

Baby steps, textured sphere loaded from an obj file
Baby steps, textured sphere loaded from an obj file

In my game engine I basically have this sort of layout:

sphere/
sphere.obj
sphere.mat
sphere.png

The .obj points to the .mat file which points to the .png file. So in Blender I would set the material name to “sphere” and ideally in the .obj file it would have a line like this, “usemtl sphere”, I would then get the sphere part and append “.mat” and load the material. I’m not sure if this is standard practice for Blender export scripts, but when exporting to the obj file format, Blender adds the texture name to the material like so, “usemtl sphere_sphere.png”, not cool. Anyway I thought, hey, the export script is written in Python, I wonder if I can fix this?

1) Locate the script. I read somewhere on the Blender site that scripts are in “/usr/share/blender/scripts/”. “export_obj.py” is there, along side “export_obj.pyc” and “export_obj.pyo”.
2) Edit the script.

gedit /usr/share/blender/scripts/export_obj.py

3) The script is pretty well documented. I knew that I should search for “usemtl” as that is the only constant part of the string (Apart from “_” which is much harder to search for). There are two in the file and we want the second one:

mat_data= MTL_DICT.get(key)
	if not mat_data:
		# First add to global dict so we can export to mtl
		# Then write mtl
 
		# Make a new names from the mat and image name,
		# converting any spaces to underscores with fixName.
 
		# If none image dont bother adding it to the name
		if key[1] == None:
			mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image
		else:
			mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image
 
	if EXPORT_GROUP_BY_MAT:
		file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null)
 
	file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)

mat_data is a dictionary that is filled out and then written the file with “usemtl”. I replaced the offending line:

mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image

with this:

mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image

And then I realised that it was exactly the same as the line from the “if key[1] == None:” so you could probably remove the branch etc. if you want, I didn’t bother.

If you are exporting groups by material you may also need to edit the “if EXPORT_GROUP_BY_MAT:” branch also, again I didn’t bother. Anyway, save and you’re good to go.

4) I was worried that I would have to compile into bytecode or something for Blender to be able to use this, nope, either restart Blender or hit “Update Menu”. Actually as it is an export script, I’m not sure you even need to do that, it probably gets reloaded when you hit “File > Export > Wavefront (.obj)”?

This is the entirety of my Python knowledge, oh, I also know that whitespace is important or something, woo.

PS. I’m loving git, I can’t believe I didn’t switch earlier!

I Love the Idea of a New Smart Phone

The list of awesome phones:
HTC Phones
OpenMoko
Palm Pre

However, a new hotness has just been born.

The Nokia n900.

32 GB internal storage
Expandable to up to 48 GB with external microSD card
3.5G mobile network
Quadband GSM with GPRS and EDGE
Data transfers over a cellular network 10/2Mbps
Data transfers over Wi-Fi 54Mbps

Flash 9.4 support (In your face iPhone users, Nokia loves me)

5-megapixel (2584 × 1938 resolution) digital camera (iPhone is up to 3.2-megapixel)
800 × 480 resolution video recording
Dual LED flash

800 × 480 resolution screen
Tactile and onscreen QWERTY keyboards (Yes, none of this onscreen keyboard rubbish)
Removable battery (That probably won’t explode)

Assisted-GPS receiver
Ovi Maps pre-installed

TV out (PAL/NTSC) with Nokia Video Connectivity Cable (CA-75U, included in box) or WLAN/UPnP

Wide aspect ratio 16:9 (WVGA)
Video recording file format: .mp4; codec: MPEG-4
Video recording at up to 848 × 480 pixels (WVGA) and up to 25fps
Video playback file formats: .mp4, .avi, .wmv, .3gp; codecs: H.264, MPEG-4, Xvid, WMV, H.263

Music playback file formats: .wav, .mp3, .AAC, .eAAC, .wma, .m4a

The important part:
Development in C and Python are supported, using GTK.
Unfortunately it looks like C++ is not supported so anyone wanting to do any OOP will have to do it in Python.
That is great that Nokia are supporting open standards, releasing a mobile phone running Linux. It would be nice if they supported C++ too, but that is just my personal preference, and it may come in the future, I know all the C++ jazz is quite complex and definitely non-trivial.

I’d still rather use Python than C. I certainly hope that Windows Mobile dies and the highly overrated iPhone becomes less popular, not completely die, just put in its place. I would love to see the world embrace open standards, open source software and a rise in DRM free, happy, feel good devices, gain popularity and eventually dominate the market and warm people’s hearts.

Moving from SVN to GIT

So I have a few projects on SourceForge, but they’re all hosted via SVN. With all this distributed version control going on I thought I would like to get in on the action. I thought about moving to github, but what happens in 5 or 10 years when I want to move on to another revision control software? The name has a limited life expectancy. Anyway so I wanted to switch so I researched alot, this is the best information I found and this blog entry is basically a rehash specific to SourceForge (Because I didn’t find any good SourceForge specific information).

Note: For this tutorial you will want to change all occurrences of USERNAME to your user name for example “pilkch”, PROJECTNAME to your project name for example “breathe” and YOURFULLNAME to your full name for example “Chris Pilkington”.

First of all we need to download git and git-svn:

su
yum install git git-svn

Now we are going to create our repo directory for holding our repositories:

cd ~
mkdir repo

Create a users.txt file to map our subversion users to git users:

users.txt

USERNAME = YOURFULLNAME <USERNAME@PROJECTNAME.git.sourceforge.net>

As the other article says, we basically check out a svn directory as a git repository:

cd repo
mkdir PROJECTNAME_from_svn
cd PROJECTNAME_from_svn
git svn init http://PROJECTNAME.svn.sourceforge.net/svnroot/PROJECTNAME/PROJECTNAME --no-metadata
git config svn.authorsfile ../users.txt
git svn fetch

Check that worked (Just read the last few changes to make sure svn history is present, you can hit spacebar to scroll back a page of history or two just to make sure):

git log

From now on we can use git commands, first of all want to create a copy of the git-svn repository:

cd ..
git clone PROJECTNAME_from_svn PROJECTNAME

PROJECTNAME/ now contains our “clean” repository and PROJECTNAME_from_svn can be deleted if you like. We now just need to add and push our local repository to the remote location:

cd PROJECTNAME
git config user.name "YOURFULLNAME"
git config user.email "USERNAME@users.sourceforge.net"
git remote rm origin # This may not be necessary for you
git remote add origin ssh://USERNAME@PROJECTNAME.git.sourceforge.net/gitroot/PROJECTNAME/PROJECTNAME
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
git push origin master

Now to check that this is working you can browse to the git page of your SourceForge project and there should be data in your repository. And we can clone our repository back again to check that everything is working.

git clone ssh://USERNAME@PROJECTNAME.git.sourceforge.net/gitroot/PROJECTNAME/PROJECTNAME

You may also want to ignore certain types of files, place a file called .gitignore in the root directory of your project and fill it with the patterns you want ignored:

.gitignore

.DS_Store
.svn
._*
~$*
.*.swp
Thumbs.db

Now when we want to update we can do:

git commit -a -m "This is my commit message." # All changes to the local repository need to be committed before we try merging new changes
git pull # Grab any changes from the main repository

Committing is slightly different:

git add .gitignore # For example we might want to add our new .gitignore file
git commit -a -m "This is my commit message." # Note: Your commit has now only been staged, it is not in the main repository yet
git push # Now it is pushed into the main repository

The last step is to remove your svn repository which for SourceForge is as simple as unchecking a checkbox on the Admin->Features page.

Symbols/Characters Returned by ls -l

$ ls -l
total 24
drwxrwxr-x   ...   thisisadirectory
-rw-rw-r--   ...   thisisafile
lrwxrwxrwx.  ...   thisisalink -> /media/data

We know what the rwx fields are but what about d, – and l? Ok, those are pretty obvious too, here is a list of the more obscure ones because I always forget.

d Directory.
l Symbolic link.
Regular file.

b Block buffered device special file.
c Character unbuffered device special file.
s Socket link.
p FIFO pipe.
. indicates a file with an SELinux security context, but no other alternate access method.

s setuid – This is only found in the execute field.
If there is a “-” in a particular location, there is no permission. This may be found in any field whether read, write, or execute field.

The file permissions bits include an execute permission bit for file owner, group and other. When the execute bit for the owner is set to “s” the set user ID bit is set.
This causes any persons or processes that run the file to have access to system resources as though they are the owner of the file. When the execute bit for the group is set to “s”,
the set group ID bit is set and the user running the program is given access based on access permission for the group the file belongs to.

libxdgmm

I think the Portland Project from freedesktop.org, is a great idea and
everyone should be supporting it in their applications.

I’ve just created a very small C++ wrapper (libxdgmm) for accessing XDG more easily. To use it, you need libxdgmm.h and libxdgmm.cpp. Just add these to your project and then use them like so:

#include <libxdgmm/libxdg.h>
 
int main(int argc, char** argv)
{
  if (!xdg::IsInstalled()) std::cout<<"XDG is not installed"<<std::endl;
  else {
    std::string data;
    xdg::GetDataHome(data);
    std::cout<<"data=\""<<data<<"\""<<std::endl;
 
    std::string config;
    xdg::GetConfigHome(config);
    std::cout<<"config=\""<<config<<"\""<<std::endl;
 
    // Obviously these have to exist to work.  You can translate the error code returned by calling xdg::GetOpenErrorString(int result);
    xdg::OpenFile("/home/chris/dev/cMd3Loader.cpp");
    xdg::OpenFolder("/home/chris/");
    xdg::OpenURL("http://chris.iluo.net");
  }
 
  return EXIT_SUCCESS;
}

I still have to wrap some of the other functionality, such as XDG_DESKTOP_DIR, XDG_DOCUMENTS_DIR, XDG_MUSIC_DIR, desktop-file-utils, xdg-desktop-menu and xdg-desktop-icon etc. I will wrap these as I need them (Or at special request). I don’t think I will be supporting xdg-screensaver or xdg-mime as I don’t have a use for them right now.

C++0x compiling with gcc

Gcc has some early support for C++0x. You can enable it with -std=c++0x (Note: You can already use Boost without enabling this flag). Enabling this flag broke boost::filesystem for me, but this has already been reported and fixed:

boost/filesystem/operations.hpp

661	661	    inline bool is_empty( const path & ph ) 
662	 	-      { return is_empty<path>( ph ); } 
 	662	+      { return boost::filesystem::is_empty<path>( ph ); } 
663	663	    inline bool is_empty( const wpath & ph ) 
664	 	-      { return is_empty<wpath>( ph ); } 
 	664	+      { return boost::filesystem::is_empty<wpath>( ph ); }

The full patch is much longer, but this seemed to be all I needed to get it to work (Note: You will need to su and then gedit /usr/include/boost/filesystem/operations.hpp).

Anyway, you will want to test it out:

enum A
{
  A_1,
  A_2
};
 
enum B
{
  B_1,
  B_2
};
 
void Test()
{
  B b = 0;
 
  b = true;
  b = 1;
  b = A_1;
  b = A::A_1;
  b = B_1;
  b = B::B_1;
}

The only lines of Test that compile are “b = B_1;” and “b = B::B_1;”. Under C++98/C++03 this would 100% compile, which could easily create bugs where the code compiles but may not be what is intended. We can also get slightly tighter restrictions again, by defining “enum B” as “enum class B”. This restricts the correct lines of Test to “b = B::B_1”, meaning the enum must be fully qualified which should lead to less ambiguous code. In a real situation you will also want to actually initialise b to a decent value initially as well: “B b = B::B_1” for example.

Anyway, this is a pretty trivial example, just a tidy up of the language really, you will want to delve deeper. Variadic templates, Initializer lists, Lambda expressions and closures, New character types, Unicode string literals, Raw string literals and Universal character name literals look good. Extern templates, Inheriting constructors, nullptr, __func__, C99 preprocessor, long long, Extended integral types can’t get here soon enough.

Upgraded Linux Kernel not recognising ext3 partitions and the solution

Unable to access resume device (/dev/dm-1)
mount: error mounting /dev/root on /sysroot as ext3: No such file or directory

Being a Linux noob, I found this solution

Create mkinitrd.new

chmod +x mkinitrd.new
su
cd /boot
sudo ./mkinitrd.new -f initrd-2.6.27.24-170.2.68.fc10.x86_64.img 2.6.27.24-170.2.68.fc10.x86_64

“Error: glXCreateContext failed” After Updating Video Drivers

After updating video drivers I couldn’t run 3d applications, for example glxinfo:

Error: glXCreateContext failed

The following needs to be present in the xorg.conf file:

Section "Files"
ModulePath "/usr/lib64/xorg/modules/extensions/nvidia"
ModulePath "/usr/lib64/xorg/modules"
EndSection

Yearly Update :)

Sudoku Work in Progress
Skysytem background, testing wireframe grid, TombRaider MD3 model, testing material boxes, particle systems, frames per second messages, pegs, shocks, all the necessary elements of a Sudoku game.

It’s been a while, I have like 20 draft entries in WordPress ranging from 1 paragraph comments up to 10 paragraph full on entries that still need that final once over and edit before going live. Actually it might be cool if there was (There probably is) a plugin so that people could optionally go to a page on my blog where they can see everything that hasn’t been published yet, like tagged with “draft” or something and comment on which ones I should flesh out and which ones I should ditch before they are even finished.

Anyway, so I have been working (Getting side tracked while working on) my Sudoku game.

Basically in Sudoku mode you get to select a number from the “palette” at the top and then click on all the places you want it on the board. The solver I have coded up can solve about 80% of Sudoku boards with “human solvable” methods and the remaining 20% can be solved with a combination of human solvable and then resorting to brute force for anything it can’t find. A valid board should not need brute forcing which means that I need to implement more rules for my human solving methods first. I should be doing something like this:

if (solve_human_methods()) ... solved
else ... this board is invalid as it could not possibly be solved by a human without resorting to brute force

However I haven’t implemented all human methods of solving yet, only about 4 or 5 simple ones, actually probably less, there are about 2 or 3 real rules and then 4 or 5 extrapolated rules that are just combinations of the first ones.

Anyway, in First Person mode there is flying around (No clip mode) as well as moving Lara Croft around (Optionally other MD3 models) with sort of appropriate animations based on velocity (But not facing direction yet). One thing I have noticed is that half of the MD3 models I download have different file naming conventions, so at some stage I want to break out some Quake 3 action and see what file names it uses and use that as my standard.

Why all this other stuff in a Sudoku game? Whichever game I am working at the time becomes my test bed application for whatever I feel like implementing when bored. I really need to make a dedicated test bed that does nothing else but demonstrate stuff. I’ve also split my game engine into Spitfire and Breathe portions, which splits the library into two halves, the generic tools for any application (string, math, xml, md5 hashes etc.) and game specific features (OpenGL rendering, audio, physics, MD3 animation, etc.) respectively.