Half-Life 2: Point Insertion Part I

Abstract

Recently, Valve released Half-Life 2 and it’s episodes for Linux. For me, this is more or less a dream come true, something I’ve been waiting and wanting and wishing for since I started using Linux in 2006.

I’ve tried Wine, multiple times, and it’s always been a bit too quirky, with too many peculiar bugs and foibles. This is not to say that I don’t find Wine impressive. Wine is probably one of the more audacious projects I’ve ever seen – an attempt to reverse engineer one of the most obtuse black boxes ever, the Windows API.

So now that Half-Life 2 has been natively released for Linux, I decided it was time to do a complete replay of the game. I’ve played the game a lot, but I don’t think I’ve actually sat down and gone end to end for a long time. I always skip bits, replay certain sections and then stop.

This time I’m going to share my experiences, via pretentious blog posts, probably on THE INTERNET (but not necessarily  I’ll accept requests to have pages posted to you, if you first of all send me a written request via the royal mail).

I’m doing this not because I think I’ve got anything interesting to say, or anything new. Everything has been more or less said about the game at this point, and if I ejaculate all over it I don’t think it will make much difference to the world at large.

No, I’m doing this because I want to and because I’m a mouthy git, and because this is the internet I can do what I like.

Technical Specifications

I’m playing this on a Samsung Series 7 Chronos, which is an ultrabook type thing. It’s got:

Xubuntu 13.04 x64

Intel Core i5

8GB RAM

nVidia geforce 630M

Although the nVidia bit is actually Optimus, and I get way better performance out of the Intel bit than I do with the discrete nVidia chip. Still working on that.

And away we go!
Continue reading

And again with the coding…

Here’s a little Arduino code I’ve cooked up for the purposes of providing a nice crank signal to the FPGA-based ECU, for the purposes of bench testing the output. It’s a simulation of a nicely cleaned up, digital signal generated by a 36-1 toothed crank wheel on your typical Ford engine.

Essentially, a little throttle position sensor (read, potentiometer) is hooked up to adc pin 5. This is purely to give me something to twiddle to see if the FPGA is reacting quickly enough to the change in frequency (Not that I have any fear of this, really- damn thing is pretty fast- but alas, I must have something to fiddle with while testing, or it’s no fun!).

The LED flashing part is purely for visual effect; an ‘is it working’ before I had chance to hook it up to an oscilloscope for testing.

The code is simple enough, my written code is starting to look more user-friendly, and- importantly- it works. Onward with the FPGA testing, then?

Maybe after my exams; this was put together in my ‘evening off’. (Oh, ninjaedit- it only ‘works’ when debug = 1)

//-------------------------------------------------------------------------------
 
#include <Wire.h>
 
//-----------------------------------
// Calibration Values for TPS
float minimumReading = 48;
float maximumReading = 919;
//-----------------------------------
 
//Setttings for TPS
int analogPin = 5; // Throttle Position Sensor Wiper Pin
int throttleRead= 0; // variable to store the value read
int throttleCorrected= 0; // variable to store the corrected value
 
//LED flashy bit setup
const int ledPin = 13; // The number of the onboard LED pin
int ledState = LOW; // Used to store the LED state
 
//Variables for Pulse Generator
long pulseLength = 0; // Variable to store the generated pulse length
long gapLength = 0;
int toggle = 1; // Variable to act as a toggle
long lastMicros = 0; // Variable to act as timer function
int count = 1; // Variable to store the current tooth count
int calibrate = 92.59259259259; // Calibration for top speed = appx. 9k rpm
 
int rpm1 = 1; // Variable to store the RPM number
int debug = 1; // Debug setting- changes output from RPM & pulse length to counter & gap indicator
 
void setup()
{
Serial.begin(9600); // Setup serial
pinMode(ledPin, OUTPUT);
}
 
void loop()
{
tpsRead(); // Run TPS Read loop
pulseGenerate();
}
 
void tpsRead()
{
throttleRead = analogRead(analogPin); // Read the input pin
throttleCorrected = ((throttleRead-minimumReading)/maximumReading)*100; // Subtract minimum from TPS. Calculate percentage of max
 
if (throttleCorrected<1)
{
throttleCorrected=1;
}
if (debug == 0)
{
rpm1 = 60000000/(pulseLength*36);
Serial.print("Simulated RPM :");
Serial.print(rpm1);
Serial.print("RPM; Pulse Width :");
Serial.print(pulseLength);
Serial.println("uS");
}
}
void pulseGenerate()
{
pulseLength = (throttleCorrected*calibrate); // Calculate length of 'high' pulse (in microseconds)
gapLength = pulseLength*3;
 
if ( (micros() > (lastMicros + pulseLength)) && (toggle==HIGH) && (count <= 35) )
{
lastMicros = micros();
toggle = LOW;
}
if ( (micros() > (lastMicros + pulseLength)) && (toggle==LOW) && (count < 35) )
{
lastMicros = micros();
toggle = HIGH;
count += 1;
if (debug == 1)
{
Serial.print (count);
Serial.print (",");
}
}
if ( (micros() > (lastMicros + gapLength)) && (toggle==LOW) && (count == 35) )
{
lastMicros = micros();
toggle = HIGH;
count = 1;
if (debug == 1)
{
Serial.println ("GAP");
Serial.print(count);
Serial.print (",");
}
}
digitalWrite(ledPin,toggle);
}

On Linux Adoption

Today something very exciting happened. Half-Life 2 and its episodes are now available for Linux.

This year has been great for Linux gaming, and I’m managing to move further and further away from Windows as my primary OS.

My laptop dual boots Windows 8 and Xubuntu 13.04, and my desktop dual boots Windows 7 and Arch Linux.

On my laptop, I never boot Windows at all any more. I bought it as a lightweight gaming machine that I could use when I travel for work, and I’ve found that most of the games I’m playing at the moment have Linux releases (Kerbal Space Program is currently my most played).

My desktop I’m currently playing Far Cry 3 on, so obviously that needs Windows, but now that I’ve got Left 4 Dead 2 and Counter-Strike Source, and with Garry’s Mod on the way too, my reasons for staying in Windows are shrinking.

I announced my pleasure to a “community” of people I hang out with on Skype quite often, and there I faced the usual amount of disdain and apathy.

But I also encountered an arguement against Linux that I’ve not actually come across before, and while it is indeed born of stupidity (and demonstrably wrong in some cases), it nonetheless intrigued me.

It went like this:

There is no killer app for linux

That’s not what they said, but that’s what they meant. They argued that there was no incentive for them to actually use Linux because every tool they might use on Linux already had a windows version.

What?

That’s a seriously weird thing to argue. Generally, you want to reach as wide an audience as possible with your software. Locking yourself to a particular platform, unless you are the platform vendor, is going to be suicide.

Unless you are a particularly niche product, or you are building bespoke software for a client that is running a particular OS, why would you want to lock yourself to a platform? Cross platform development has never been easier, and more and more software companies are starting to bring out versions of their software for more than just Windows.

Leaving linux out of it for a moment, I’d consider that most consumer software these days as being multi platform. Good grief, even Microsoft release Office for Mac.

Apple release iTunes for Windows! Why on earth would they do this? Wouldn’t releasing it for Mac only make more people use Macs?

No. Because while a lot of people can afford an overpriced undersexed mp3 player, they can’t also afford a brand new computer just to use the damn thing. And Apple know this, hence the release of iTunes for Windows.

So that aside, very few people are going to switch to linux because of a particular program they need that has been released for linux and no other platform. At least, most average computer users.

His next argument said “well, I don’t think linux is ready yet. No one distributes it on new computers”.

*Ahem*

And the concept is not new. Dell have been doing this for a few years now.

The next arguement was “Well only computer geeks and nerds will use it”.

I think he seriously underestimated how many geeks & nerds exist on the planet. There are millions of us!
Do we not deserve to choose? If your average consumer can choose between Windows and Mac, can’t we choose something different?

If you go by the numbers in the Steam Hardware and Software survey, at the moment there at around 1.3% of Steam users on Linux.
Steam users peak at around 5.3 million a day.
That’s nearly 70’000 people using steam on linux (at the time of the last hardware survey). The actual numbers may differ.

Valve obviously thinks its worth releasing games for us. If you look at the average price breakdown by OS for the humble bundle, you can see that Linux users might be a minority, but they’re a minority that pays well for games:

Screenshot - 100513 - 18:13:02

The arguement that only nerds will use it….well. My girlfriend prefers Linux over Windows for a lot of things, and only really stays on Windows for some academic software and iTunes.

My sister used Ubuntu, but only until she immersed her laptop in tea. She got on with it.

My parents use it.

My brother uses it. He’s the first to admit he’s not technically minded.

A lightweight distro works extremely well for people who only use their laptop as a facebook machine.

Come to think of it, the guy was probably trolling me. He succeeded.

Anyway, this post gave me something to do while waiting for Half-Life 2 to download.

Screenshot - 100513 - 18:17:45

ECU Project- Entry the First

Worthy of note, is that this is -not- the first effort I’ve made in this field.

In short, the reason behind this project is that I have an MGB GT; after the second B-series engine gave up the ghost (they don’t really seem to like 20,000 motorway miles and 12,000 ‘other’ miles a year), I got fed up- and the car sat languishing in the garage for 6 months.

So, my birthday rolled around- and my mother made me a little purchase…

mgb-v8

As it turns out, this gave me some bad ideas. As there are several people in my group of friends and acquaintances- not least of which, my father- who are very much into the Ford Capri, I’d heard of a little engine swap that can be performed relatively simply, into that vehicle- the Cosworth 24v V6.

The block length of which would just about fit. As would the gearbox- assuming I’d switch the auto ‘box that comes bolted to the engine, with an MT75 5-speed manual. Naturally, I prefer the sound of carburetors  and this is as standard a fuel-injected, ECU-controlled engine…

A solution was needed; off-the shelf solutions, as usual, too expensive… this is my first step along the route to achieving it.

The purchase of an FPGA (Field Programmable Gate Array) is my first step along the line- inspired by an interview with a gentleman who suggested that experience using them would aid my future employment prospects.

It’s a nice little device, and very clever- anyone familiar with logic circuitry will understand the basic concepts- AND, NOT and OR gates arranged in specific ways to achieve outputs that are desired.

The software we were using (Quartus II) also incorporates megafunctions- effectively, complex logic-based designs in premade ‘blocks’.

Logic Layout

Pictured above is an (admittedly, relatively complex) LED flasher. Connected to the ‘input’ on the left of the image is one of the internal clock pins on the FPGA- more on this later- and the other is connected to an included LED.

Now, to start with, I had no real idea what to expect- and other than making sure that the board was properly functional, did nothing, until I had a little backup; enter Iain, stage right, for “beer and a curry, honest”.

Further, we were not able to confirm the clock frequency of pin on the FPGA I was using. They appear to be variable, and my board turns out to have a few idiosyncrasies (including relatively poor user manuals). So, having read somewhere that it was either 12, 24, or 48 Mhz, for my trial design we set up a little counter-comparator pair- counting clock pulses, at 6000, turn LED on, at 12,000, reset the counter.

pin assignment

Pin association is given in the above image- pin 66 is one of the onboard clock sources, and pin 35 is the pin for the LED output on my board.

And… it worked! the LED flashed at a steady rate of on for half-second, off for half-second. Telling me that the frequency of the CLK source that we used was 12Mhz.

Some issues we ran into- when assigning the values for the constant values, I mistyped on no less than 3 occasions (easy to do, when you’re typing out a 32-bit binary number), omitting a digit, or duplicating another. This took a surprising length of time to rectify (when you’re not sure your design is going to work, it’s often easy to overlook something obvious). Also, we had a little fun with having to re-design the circuit at various points- the LPM_compare function required a 32 bit number to ‘compare’, up to that point everything had been working on 25 to save space… back to the drawing board!

End of Step One.

Grub EFI Dual boot errors

I recently decided to move install Xubuntu on my desktop, having gotten fed up of Arch Linux. Arch Linux will make it’s return, but I was having too much trouble with the AMD legacy drivers. When I’ve upgraded my graphics card (hint – for one that doesn’t have shit linux support), I’ll move back.

In the meantime, I had some problems with Grub.

To begin with, the install did not recognise my Windows partitions at all, but I could still boot from the EFI menu to Windows. I would rather have grub though, instead of having to hammer away at the F8 key on every cold boot.

According to the Ubuntu page about UEFI, you should use boot-repair.

I used boot repair, and the output from it can be found here.

This updated grub, found the Windows partition, and added Windows as an option (actually 2 options for Windows. Don’t know why, but there are multiple EFI files for Windows on the EFI partition).

I got this error:

error: no such file or device: 16E0-4903
error: no such file or device: 16E0-4903
error: file '/EFI/Microsoft/Boot/bootmgfw.efi' not found
 
Press any key to continue

The grub entry for Windows looked like this:

menuentry "Windows 7" {
search --fs-uuid --no-floppy --set=root 16E0-4903
chainloader (${root})/EFI/Microsoft/Boot/bkpbootmgfw.efi
}

I checked the EFI partition, and sure enough the file is there. I checked the UUID of sda1 (the EFI partition), and it was correct.

I tried to fix it myself, by using the hard drive name instead of the UUID, but that gave errors about partition type.

Turned out I needed to add this:

menuentry "Windows 7" {
insmod part_gpt
search --fs-uuid --no-floppy --set=root 16E0-4903
chainloader (${root})/EFI/Microsoft/Boot/bkpbootmgfw.efi
}

I found the information here.

I don’t know why that line wasn’t added, but there we are.

Origin

So, I added new ram to my build today.

I had to do a cmos reset to get the settings right, more fool me.

What I wasn’t expecting was this, when I booted up:

Yep. Origin relies on your system clock to tell you if the game is released or not. I wonder if this works the other way around: if you’ve pre-loaded something, can you play it if you mess with the system clock?

Ink Part 2

Canny Edge Detection

The first stage for me is going to edge detection. There are many edge detectors, but I’m going to use the Canny Edge Detector, because I’m vaguely familiar with it and it’s quite well regarded.

Here’s the image I’m going to use for the initial development:

This handsome face *cough* is about to be melted down and turned into a bunch of squiggly lines. It was taken with my webcam in a partially darkened hotel room. On a Sunday. I also look a little shocked for some reason.

Step 1: Noise Reduction

To start with I’m going to blur my image. This might seem a bit counter intuitive, but it’s actually very helpful in cutting down the amount of noise in the picture. I mean, look at it. There’s randomly coloured pixels all over the place, due to poor lighting and a poor webcam. This kind of thing is going to cause interference in the various algorithms I’ll be using. I’ll show off why in a bit.

I’m going to use a very basic “box blur” kernel, not a fancy Gaussian one. Mainly because it’s easier and I’m lazy.

I’ll be using a 3×3 convolution kernel, like this:

Box Blur Kernel

Box Blur Kernel

This gets applied to an image by moving the centre of the kernel along each pixel in the image, and multiplying the kernel with the window in the image. The result is then summed.

Obviously, you have to deal with edge cases. I’ve taken the easy way out and _not_ dealt with them. I’m only blurring the pixels that are not at the very edge, which leaves a strip around the image that is unprocessed, one pixel thick. Visually, this doesn’t matter- I can leave it there or reduce the image size by 2 pixels in the x and y direction.

Original image has been desaturated and blurred, to try to cut down on the noise.

 

Step 2: Get Gradient Intensities:

I’m going to use a basic Sobel filter to perform edge detection. Sobel detects rapid intensity changes in a specific direction. In fact, you need a Sobel filter per direction:

Gx

This filter is applied in the same way as the box-blur filter described earlier. Here’s the output:

Gradient intensities in the horizontal direction

The test image with intensities in the Y direction calculated

These two results images are actually from before adding the box-blur filter. I’m doing this whole writeup in the wrong order.

The two gradient intensity images are summed together to get the final gradient result, using this very simple formula

|G| = |Gx| + |Gy|

That is a shortcut from doing the full equation of:

G = SquareRoot(Gx2 + Gy2)

This equation, applied to every pixel in both images, gives this result:

A basic gradient intensity image. By itself, this doesn’t do much, but I like to get tangible output from these algorithms. It’s a good visual lesson for what I just did.

That’s it for now. In the next post I do on this, I’ll be doing:

  • Edge direction calculations
  • Thin edge detection
  • Edge following

 

And the winner is…

Despite a 14-day top end for delivery, the Hobbyking parcel arrived this morning. Only been unboxed so far- here are a few pics:

The postcard is for scale. That’s a 12-inch diameter, 3 bladed prop. The prop fitting kit is very nicely machined and the spinner is a nice finishing touch; not bad for an extra $3 on top of the cost of the motor.

Sadly, batteries don’t have a connector compatible with the charger (despite being the same brand), and I forgot to order the connectors for the speed controller, so more than just a little assembly will have to wait.

Signing off.

Overambitious Project: Ink

I’ve got that itch again. The one that sits at the back of my head going “you haven’t done any cool programming in ages, don’t you think you should?”

It’s an urge to go and work on a personal coding project, where I can experiment with stuff I find interesting, and can set my own pace and goals. This has become especially important recently, since I don’t even do any coding for my job anymore. I’m moving over to a managerial/everyman/”guy who knows stuff” role, so It’s not just a creative urge, it’s an urge to keep my “skills” sharp.

*Disclaimer: I’m not an amazing programmer, but I enjoy problem solving and I like to think I’ve built some cool stuff*

This project is going to be partly a rehash of my Computer Vision project at University – at least, it will use some of the same algorithms and technologies, and a large part of it will be about extracting a “useful” feature set from a set of images. What I do with that feature set is going to be very different though, and things I considered to be “useful” in my old project will probably be very different.

Here’s the abstract from my dissertation:

Reconstruction of 3D Models From 2D Images.
This project is about trying to recognise “interesting” features or points in two dimensional images, and then attempting to find corresponding features in a different image of the same scene. The coordinates of these points in different images can be used to generate 3D coordinates using Ullman’s theorem. This paper explorers a variety of options for detecting features, and several different methods for matching these features over different images. The variables used to generate and extract features are thoroughly tested, in order to find the best settings for the system. The results are then compared to the initial project specification to see if the system can operate as needed.

Now, this is not what I intend to do here at all. I just posted it anyway.

Right-

Ink, Project goal:

Write a program that will take video, and turn it into what looks like a series of hand-drawn ink sketches.

A still might look like this:

An ink drawing I found on the internet somewhere.

The animation should have enough flaws in it to make it seem hand-drawn, and it will probably have a much lower frame rate than the original video.

Part of my inspiration for this is Raymond Brigg’s “The Snowman”

 

I love the way the crosshatching works on this. The animation is low frame rate, the background is mostly static, but the movements are complex and the shading is wonderful.

 

So I want to achieve that programatticaly. You heard me. Any artist who reads this will probably tell me I’m removing all the soul from the animation, and they’d probably be right, but this is a project that I want to do.

Another inspiration is “A Scanner Darkly”, a film that I love for many, many reasons, not least because it’s adapted from a Phillip K Dick novel, and all adaptions of his work to film have been fantastic in their own ways. Even Total Recall is brilliant, but not for the same reasons Blade Runner is.

Well, maybe not.

But aside from the brilliant plot, (which, to be honest, was mostly about following stoners around. And paranoia. And government surveillance  And pharmacological conspiracies. And insanity. And psychotic breaks), it was produced in a unique way.

It was filmed normally, then every frame was redrawn partly by hand and then animated the rest of the way. Visually, it’s stunning, but the animation is so realistic that it creates a bizarre disconnect in your head while you watch it, and in places you can forget it’s animation at all. It very much suits the subject matter of the film.

 

And then there’s this clip, which I’m including for no reason other than the fact that it’s funny. Sort of:

 

Your sins will be read to you ceaselessly, in shifts, throughout eternity. The list will never end. 

So I want to try and build something similar to the system they used here. (They called it “rotoshop”, and they never released the program). It won’t be so fully-featured (damn, there’s an enterprise-y word. And another one! Auugh, what’s happened to my vocabulary?), because I will probably run into problems and get bored or frustrated. Besides, I’m not trying to accomplish the same thing, but I suspect some of the methodology will be similar.

So, here it goes.

… And then 3 come along at once!

Gentlemen, start your engines!

It’s a race between Germany and Hong Kong!
The flight electronics for the Bormatec have now been ordered from HK-based stockists, Hobbyking.

http://www.hobbyking.com/hobbyking/store/index.rc

2x 4000 mAh, 14.8 volt, 4S1P (4 series, 1 parallel) Lithium-Polymer cells, for main power.
An NTM Prop Drive Series 42-38 brushless motor, rated at 750kv*
Along with a 70 Amp ESC and the servos required to operate the aircraft.
Oh, and a LiPo charger. ‘Cos I was lacking one.

The combination of these, using one battery at a time (for better at-the-field testing times), should allow flight times of approximately half an hour. For propeller choice, I have gone for a scale-ish 3-bladed unit from Master Airscrew; 12 x 6 inch.

Running cost at this point, is now c. £350, including the original Arduino electronics and sensor modules. Significantly less, it’s worth noting, than any comparable equipment you could buy… Let’s say a comfortable factor of 10. At the minimum.

And now the waiting begins…

* KV in the sense of brushless RC motors, means RPM per Volt. (so max RPM 11,100)