Sunday, 1 September 2013

Traffic Shaping and Throttling in Linux

Because my University seems to have worse internet connectivity than my house

During my day job as sys-admin for the a Particle Physics Group, I recently was wrapped on the knuckles by central IT for one of our users saturating the whole university's bandwidth. My first reaction was of surprise that they didn't have traffic throttling in place already but this turned to incredulity when I learnt that they only had a 1Gb/s connection for the WHOLE CAMPUS and one of our guys just downloading some LHC data from a couple of fast sites in the UK had brought the entire system to it's knees. Consequently, I was asked to stop people doing this (!) until the network had been upgraded to 10Gb/s. I decided that setting up some traffic shaping on our machines was probably a better idea. 

A quick search led to this page that described how to use the tc command provided by the iptables package to do exactly what I needed and even provided a nice bash script to do the job - problem solved! At some point in the future I may update this post with the actual ins and outs of how the script works (when I've figured it out myself!) but until then, just grab the script, change the download/upload limits as you wish and off you go :)

Sunday, 25 August 2013

Adding New Screen Resolutions in Linux MInt

Because 800x600 is too low-res even for the console

In this day and age, I thought that plugging my laptop into a KVM switch with a known monitor on the other end it would just work but apparently I had over estimated our current level of technology and I was left with a very nice 1920x1080 monitor running at a ludicrous 800x600. Whatever the switch was doing, it meant that Mint couldn't detect the monitor and allow me to select a sensible resolution.

So how do you tell Mint to stop being stupid and run a monitor at a given resolution? This post on the Linux Mint Community site had the answer. In summary, do the following:


  • First, create a 'modeline' using cvt - this is the configuration line that will be added to the monitor settings and contains info on refresh rate, vsync, etc. Note that this use the VESA standard and so should be compatible with pretty much everything.

~ $ cvt 1920 1080
# 1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.16 kHz; pclk: 173.00 MHz
Modeline "1920x1080_60.00"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync

  • This mode info now needs to be added to the monitor settings using xrandr and the info from the above Modeline:

xrandr --newmode "1920x1080_60.00"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
xrandr --addmode VGA1 "1920x1080_60.00"

This setting should now be added to the list of default options given for the monitor. Note that this isn't permanent and won't survive a reboot - however, I very rarely reboot my laptop anyway (yay linux!) and the original blog post has info about how to do this if you want to give it a try.

Sunday, 2 June 2013

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

3D rotations broke my brain

So in the first part of this post, I got the cube to respond to mouse movements in so you can rotate around it. Inspiring stuff. Next, I want to add keyboard control using good old WASD movement. The movement I want to recreate is your typical RTS style mouse movement of having the camera rotate around a point (done) and then move that point over a plane using the keyboard (definitely not done).

First things first: How do we check for keyboard input? This is actually not as quite as simple as just triggering on a key press event as if you hold down a key as these don't fire often enough. It is also very difficult (maybe impossible) to poll the actual keyboard hardware in an OS-independent way. However, we can use the Qt-provided functions keyPressEvent and keyReleaseEvent to track the state of the keyboard and act accordingly. To do this, just override these functions in the MainWindow object (this is what gets the keyboard events by default) and update a QMap to the status of each key. The actual code I've added is quite simple and is shown below:

header:

public:    
    // check key status
    bool isKeyDown(int key);

private:
    // keyboard map for deciding key presses
    QMap keyboardMap_;

protected:
    void keyPressEvent(QKeyEvent *event);
    void keyReleaseEvent(QKeyEvent *event);


cpp file:

void MainWindow::keyPressEvent(QKeyEvent *e)
{
    // if we're quitting, then fine
    if (e->key() == Qt::Key_Escape)
    {
        close();
        return;
    }

    // otherwise update the keyboard map
    keyboardMap_[ e->key() ] = true;
}

void MainWindow::keyReleaseEvent(QKeyEvent *e)
{
    // update the keyboard map
    keyboardMap_[ e->key() ] = false;
}

bool MainWindow::isKeyDown(int key)
{
    // check in the map to see if the key is down
    if (keyboardMap_.contains(key))
        return keyboardMap_[ key ];
    else
        return false;
}


So we grab any key press or release events and then simply update the QMap with state for this key code. After that, all we need is an access function to allow the widget to query the key state and move the view accordingly.

Now, to actually move the view accordingly takes a little bit of thought. We have to be a little careful as to where we put the translation given by the keyboard movement in order to give the RTS style rotate-around-a-point camera we're looking for. At present, we have:

    // move into the screen
    glTranslatef(0.0f, 0.0f, -6.0f);

    // rotate the cube by the rotation value
    glRotatef(rotValue_.y(), 1.0f, 0.0f, 0.0f);
    glRotatef(rotValue_.x(), 0.0f, 1.0f, 0.0f);

To apply the lateral movement, we need to think about which order to perform these translations and movements in to get the affect we want, remembering that we are transforming the world relative to the camera. This turns out to be:
  1. Translate back by the zoom factor 
  2. Rotate the coordinate system around the origin (equivalent to rotating the camera)
  3. Translate the view to the current focus point position
Applying these gives the following code:

    // reset the view to the identity
    glLoadIdentity();

    // move everything back by the zoom factor
    glTranslatef(0.0f, 0.0f, -zoomValue_);

    // rotate everything
    glRotatef(rotValue_.y(), 1.0f, 0.0f, 0.0f);
    glRotatef(rotValue_.x(), 0.0f, 1.0f, 0.0f);

    // finally offset by the current viewing point
    glTranslatef(posValue_.x(), posValue_.y(), 0.0f);

This almost gives us the keyboard control we were looking for. However, as it stands, if you just polled the key status and increased or decreased the x and y values, you would always be moving on those axes. What we really want is to move relative to the direction we're facing. Unfortunately, this is where we can't avoid some trigonometry as we need to take the movement speed and angle of rotation around the vertical axis to give the change in x and y values needed. Long story short, this code in a new 'mainLoop' function does the job:

    // check for keyboard movement
    if (parentWin_->isKeyDown(65))  // A
    {
        posValue_.setY( posValue_.y() + (0.05 * sin( PI * rotValue_.x() / 180.0) ) );
        posValue_.setX( posValue_.x() + (0.05 * cos( PI * rotValue_.x() / 180.0) ) );
    }

    if (parentWin_->isKeyDown(68))  // D
    {
        posValue_.setY( posValue_.y() - (0.05 * sin( PI * rotValue_.x() / 180.0) ) );
        posValue_.setX( posValue_.x() - (0.05 * cos( PI * rotValue_.x() / 180.0) ) );
    }

    if (parentWin_->isKeyDown(87)) // W
    {
        posValue_.setY( posValue_.y() + (0.05 * cos( PI * rotValue_.x() / 180.0) ) );
        posValue_.setX( posValue_.x() - (0.05 * sin( PI * rotValue_.x() / 180.0) ) );
    }

    if (parentWin_->isKeyDown(83))  // S
    {
        posValue_.setY( posValue_.y() - (0.05 * cos( PI * rotValue_.x() / 180.0) ) );
        posValue_.setX( posValue_.x() + (0.05 * sin( PI * rotValue_.x() / 180.0) ) );
    }

Note the conversion from degrees (as accepted by glRotatef) and radians (as accepted by sin/cos).

Things to note:
  • I've added mouse wheel zoom by overloading mouseWheelEvent and clamping the zoom value.
  • In order to poll the keyboard state and a fast enough rate, I've added a mainLoop slot function that is attached to the timer and then calls the updateGL function.
  • In order to call into the parent window's keyboard map, you need to make the widget aware of it and I personally prefer to store this pointer in a member variable through the constructor rather than having a global variable or static singleton type framework.
  • The rotation/translation order can be difficult to get your head around - try to remember that the camera is static and the transformations apply to the coordinate system!
And we're done! We now have a mouse and keyboard controlled scene to zoom around.

Find the code at:

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

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 :)