Tuesday, 14 May 2013

Painting Space Wolf Grey Hunters

About the only painting I'll ever be able to do

This post is a bit of a change for the previous ones as it actually has nothing to do with computers which is actually quite an achievement for me. I've been buying Games Workshop crap products for what must be at least 20 years now, starting with the original Space Hulk and 40K Rogue Trader, up to 3rd Edition 40K (bit of a break for uni and not having money or space) and on to 5th Edition and beyond. I have a large portion of both mine and my parent's attics filled with the stuff and I still love it. The 40K lore, the miniatures, the hobby, the game - it's awesome. I am, to all intents and purposes, Games Workshop's bitch.

Though I've always liked painting I've never managed to really get the hang of it. But last year GW released a new set of paints and had proper 'For Dummies' style guides that even I could follow and so after buying more plastic crack that I didn't need, I set about trying to actually complete some models to a high standard. Here are the first off to be completed. What we have here is a squad of Grey Hunter Space Wolves:


Essentially, all I did for each was start with spraying everything with The Fang on top of a Chaos Black (or whatever they call it now) undercoat. Then I applied the base colours, followed by a wash, a layer colour or two and a final highlight to the edges of armour or pads. The specific colours used were:

  • Power Armour - Russ Grey (base), Agrax Earthshade (wash), Russ Grey (Layer), Fenrisian Grey (highlight 1), Rhinox Hide (highlight 2 - armour chips)
  • Furs - Steel Legion Drab (base), Seraphim Sepia (wash), Agrax Earthshade (wash), Mournfang Brown (Layer), Tallarn Sand (layer), Ushabti Bone (highlight)
  • Shoulder Pads - Mephiston Red (base), Agrax Earthshade (wash), Mephiston Red (Layer), Wild Rider Red (highlight)
  • Gold Areas - Balthasar Gold (base), Gehenna's Gold (layer), Agrax Earthshade (wash), Gehenna's Gold (highlight)
  • Metal - Leadbelcher (base), Nuln Oil (wash), Ironbreaker (highlight)
  • Bone - Zandri Dust (base), Agrax Earthshade (wash), Ushabti Bone (layer), Screaming Skull (highlight)
  • Black Areas - Abaddon Black (base), Skavenblight Dinge (highlight 1), Dawnstone (highlight 2)Administratum Grey (highlight 3)
  • Power Sword - Stegadon Scale Green (base), Sotek Green (highlight 1), Temple Guard Blue (highlight 2), Guilliman Blue (wash), Fenrisian Grey (highlight 3)
  • Base - Armageddon Dust (base), Agrax Earthshade (wash), Tyrant Skull (highlight)
This is basically taken wholesale from White Dwarf 388 (because I have no imagination). Some of the things I learnt while painting these marines include:

  • Power armour is quite easy to paint - base coat, wash and then highlight at the edges. Job done.
  • Fur is significantly more tricky. When I next have to do this, I'll avoid Mournfang Brown and just highlight up after washing the base coat of Steel Legion Drab. More practise needed here.
  • Little chips in the armour make a big difference and are easy to do.
  • The new texture paints, though awesome, can get *everywhere* if you're not careful with the brush. And they are a pain to remove if you get them where they shouldn't be.
  • A sodding HATE doing transfers on power armour. I'm guessing I'm missing something, but as far as I can tell, you can't easily put a flat transfer on a convex surface as, thanks to geometry and what not, it can't go flat - much like lining paper in a cake tin. I consequently had to put cuts in the transfers which (because they were really quite flimsy) made it a bugger not to rip in half. Add to that me forgetting about them, handling the miniature and consequently getting the meticulously aligned transfer stuck to my hand made this really rather an annoying procedure. I'll need to look up how best to do this in the future....

Hopefully this will help the next time I want to paint some Space Wolves. Next: on to some Necrons!

The full gallery can be found on my 500px page here. Enjoy :)



Sunday, 28 April 2013

Moving Around a 3D cube with Mouse and Keyboard (Part 1)

I never got the hang of XBox controllers

So moving on from a painfully coloured 3D spinning cube created in OpenGL and Qt (see here), I now want to add user input via a mouse and keyboard. The first part of this will be fairy easy and just result in being able to rotate the cube when ever the middle mouse button is pressed - 'mouse look' for those in the know.

So, first up, we need to put an additional function in for checking mouse movement. Qt makes this very easy (not surprisingly) as all widgets can catch mouse events by overriding the mouseMoveEvent. So after adding the following:

header file: 

protected:
   void mouseMoveEvent(QMouseEvent *event);

cpp file:

void OGLWidget::mouseMoveEvent(QMouseEvent *event)
{

}

We now have a function that will catch any mouse movement. Or mostly, anyway. This will only work with movement when a button is pressed (dragging basically) which won't quite work for this. You therefore should add the following to the constructor of the widget:

setMouseTracking(true);

This will set the widget to track ALL mouse movements.

So now, how do we ensure the cube moves around with the mouse and stops when we release the button? We need to keep two 'temporary' (but member) variables that record the rotation of the cube and mouse coords. The new rotation is then calculated based on the difference between this mouse position and the current one, which is then added to the stored rotation when the mouse button was pressed. As with pictures, code is often worth a thousand words so all of that can probably more easily be understood by viewing the following:

void OGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    // is the middle mouse button down?
    if (event->buttons() == Qt::MidButton)
    {
        // was it already down? If not, store the current coords
        if (!mouseLook_)
        {
            tmpMousePos_ = event->pos();
            tmpRotValue_ = rotValue_;
            mouseLook_ = true;
        }

        // update the rotation values depending on the relative mouse position
        rotValue_.setX( tmpRotValue_.x() + (tmpMousePos_.x() - event->pos().x()) * 0.2 );
        rotValue_.setY( tmpRotValue_.y() + (tmpMousePos_.y() - event->pos().y()) * -0.2 );
    }
    else
    {
        // turn off mouse look
        mouseLook_ = false;
    }
}

Things to note:
  • I've got an additional flag showing whether mouse look is on or not - I could have set one of the other tmp variables to a special value but this is almost never a good idea and variables are (generally) cheap.
  • I've applied a factor of 0.2 to each mouse movement. This is basically the mouse speed and should be configurable an ideal world
  • To incorporate two axis rotation, I've changed rotValue_ to a QPoint type where x stores the y-axis rotation and y stores the x axis rotation.

So you can now rotate the cube when holding down the middle mouse button. Next time, we try to actually move the camera using the WASD keys. This will require a few more changes to the rendering code.

Find the code at:

https://github.com/doc-sparks/Interface/tree/v0.2

Saturday, 27 April 2013

Fixing a Broken DNS in Linux Mint 13

Clearly I just have to start remembering more IP addresses

So last week I needed to go abroad (to CERN as it happens) and when I got there, my Mint 13 running laptop decided to throw a paddy and stop talking to the DNS. I could ping usual Google IPs (8.8.8.8 for example) but DNS just hung despite being reported to correctly (and pingable) in the Network Settings. Having a look at my resolv.conf, I could see that my DNS settings were set to my Uni one. I couldn't remember if these were put in automatically by the ethernet connection in my office or I'd just dumped that there randomly for some reason, but tellingly, these DNSs were NOT pingable (I guess they had fallen over or something).

So, I thought, not a problem - just change the DNSs to Google's and all should be well. Except it wasn't. The laptop was still refusing to talk to anyone by name. Luckily, my phone was not having these troubles and some frantic searching led me to the following Blog. It appears someone in Ubuntu land was trying to be clever and started using dnsmasq instead of resolv.conf. I don't know why this was done and really can't be bothered to find out, but in this occasion it meant I could not find whatever black magic was needed to force the Google DNS to be used.

By *mostly* following the blog, I discovered the following worked like a charm to get control of the DNS back to resolv.conf where (in my humble - and probably naive - opinion) it should still reside. First up, (and be aware, this should all be done under su/root), stop Mint from using dnsmasq by going to:

/etc/NetworkManager/NetworkManager.conf

And commenting out the dns line:

#dns=dnsmasq

Next, get resolvconf to sort out it's links and bring back resolv.conf:

dpkg-reconfigure resolvconf

Just to be sure, do a few more housekeeping bits and pieces and follow up with a restart:

resolvconf --create-runtime-directories
resolvconf --enable-updates
reboot

And now you should be able to edit /etc/resolv.conf as usual and have Mint listen to you. Note that you may want to also change:

/etc/resolvconf/resolv.conf.d/original

for a more permanent setting as I believe on restart resolvconf will recreate the resolv.conf with this. 

Last thing to note: While messing around, I tried to select 'Automatic (DHCP) addresses only' under IPv4 Settings for the wireless I was using. THIS WAS A BAD IDEA! It stopped the above working for other reasons I didn't understand. I plan to revisit all this at some point to try to better understand how DNS is handled in Mint/Ubuntu as I'm sure there was probably a better way around this...

Friday, 29 March 2013

Using Python within C++

I tried to think of a Jake the Snake reference... but failed.

I now have a working (and easily available) package for programming my Lego Mindstorms NXT (look here for more info). The downside is that it's written in python and I'm more of a C++ kind of guy. I could root around to try to find something that's C compatible but as this was easily available in the Mint repos, I thought it might be a better idea to just call the python code within C++.

This is not as easy as you'd think, or at least, it isn't if you want to do it right. If you only care about running some commands through the Python interpreter and not paying any attention to the results, the you can easily use something like the following:

Py_Initialize();
PyRun_SimpleString("import os");
PyRun_SimpleString("print 'hello world'");
Py_Finalize();

This is essentially a python version of a system() call (kindof..).

Anyway, we're getting ahead of ourselves. First, you need to gain access to the python headers and libraries. Through Linux, this is fairly trivial as I would guess all distros would have the python2.7-dev (or whatever version you choose) available - note that it may not be installed by default though. For Qt, you can then add the following to your .pro file:

 LIBS += -Lpython2.7 -lpython2.7

and then you can include the python header:

 #include <python2.7/Python.h>

Putting the simple hello world code into a main function should build and run as expected. So that's the basics of accessing python within C++. How do you go about integrating this properly into your code though? For that, you need to go a bit more in depth into how python is written and how it handles memory and objects.

One of the main selling points of python is it's garbage collection and object reference handling - it deals with all references to any objects and deletes objects that don't have any. Within the framework of the python language, this is fine. However, when you're poking around under the hood, you have to be careful to do what python usually does for you. In other words, you have to be very careful about tracking object references that get passed back to you from function calls (and nearly all function calls pass back object references!).

To integrate with the PythonNXT python module, I've found the following functions the most useful. There are many others (obviously) that can be found here but this should give you the basic idea of what's going on and what you need to be careful about. The main things to remember is that everything returns/deals with a PyObject base type (or actually, a pointer to one) and you have to keep track of anything that gets returned to you from the API functions.

Py_Initialize

Initialises the python interpreter. Call this before doing anything else!

Py_Finalize

Shuts everything down to do with the interpreter. Don't call anything after this!

PyObject* PyImport_ImportModule(const char *name)

This will import the given module and return a new reference to the module object.

PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name)

This will return the named object associated with the given  object. For example, if you've just loaded a module and want to call a function, use this with the function name to return a new reference to that function. Or, you have a python object that you want to call a function on, use this to get a reference to that function and then use PyObject_CallObject to actually call the function.

PyObject* PyObject_CallObject(PyObject *callable_object, PyObject *args)

When passed a reference to a function (say from the above, PyObject_GetAttrString), this will call the given function with arguments given (specified as Python objects). This returns a new reference which will be the pythonified version of the actual function return value.

PyObject* Py_BuildValue(const char *format, ...)

This constructs a python object (tuple, list, single value, etc.) based on the given format and supplied arguments (e.g. Py_BuildValue("(i)", 1) will give a tuple of one integer value). Used for PyObject_CallObject above - note that it seems you should always create tuples for this, not just single values (e.g. "(i)" rather than "i")!

void Py_XDECREF(PyObject *o)

This will decrease the reference count of the given object and therefore delete it if the count goes to 0. Note that this version checks for NULL pointers being passed. This is the main thing to remember - you must call this on any returned objects when you're done with them unless the function returns a 'borrowed' (rather than 'new') reference. If you don't, you'll be leaking memory like sieve.


This covers the basics of using Python code through the C-API. In addition to these, the following (and related) are worth looking up to manipulate Lists and Tuples. They're fairly self-explanatory:

PyList_GetItem
PyTuple_GetItem


Finally, the basic types (int, double, etc.) have dedicated python objects associated so you can easily cast to these objects (e.g. PyIntObject) to access the actual data values from these objects.

In a future post, I'll go into a bit of detail how I've used this to create a basic interface to the PythonNXT module through C++/Qt.