24 2 / 2013

Ruby Brainfuck interpreter

Brainfuck is a esoteric programming language created by Urban Müller on the Amiga back in 1993. you can read more about it in this wikipedia article http://en.wikipedia.org/wiki/Brainfuck.

I Wrote a simple brainfuck interpreter console application in Ruby because it is fun.

It accepts any number of files containing brainfuck and executes them, reading input from stdin and output to stdout (the console)

Further down you will find the “99 bottles of beer” brainfuck program but you can use this Ruby script to execute “any” brainfuck program.

I say “any” as there are several dialects of Brainfuck.

Ruby: Brainfuck interpreter program “brainfuck.rb”


    require 'io/console'

    class Brainfuck
        # array for program execution state
        @@memory = Array.new 3000, 0
        # memory pointer
        @@position = 0
        # stack of program positions for loops
        @@loop = []
        # flag set if skip to end of current loop
        @@jmp = false
        # keeps track of current loop jump nestling depth
        @@jmpi = 0
        # file handle to executing brainfuck program
        @@file = nil
        # IO from where to read program input
        @@input
        # IO from where to write program output
        @@output

        def initialize(input, output)
            @@output = output
            @@input = input
        end

        def run(file)
            @@file = File.open(file)
            @@memory = Array.new 3000, 0
            @@position = 0
            while (m = @@file.getc)
                eval(m)
            end
        end

        def eval(m)

            # handle loop jumps
            if @@jmp == true
                case m
                    when '['
                        @@jmpi+=1
                    when ']'
                        if @@jmpi == 0
                            @@jmp = false
                        else
                            @@jmpi-=1
                        end 
                    else
                end
                return
            end

            # evaluate and execute brainfuck instructions
            case m
                when '>'
                    @@position+=1
                when '<'
                    @@position-=1
                when '+'
                    @@memory[@@position]+=1
                when '-'
                    @@memory[@@position]-=1
                when '.'
                    @@output.print @@memory[@@position].chr
                when ','
                    @@memory[@@position] = @@input.getch.ord
                    @@output.print @@memory[@@position].chr
                when '['
                    if @@memory[@@position] == 0
                        @@jmp = true
                        @@jmpi = 0
                    else
                        @@loop.push @@file.pos-1
                    end
                when ']'
                    if @@memory[@@position] != 0
                        pos = @@loop.pop
                        @@file.seek(pos, IO::SEEK_SET)
                    else
                        @@loop.pop
                    end
                else
            end
        end
    end

    bf = Brainfuck.new(STDIN, STDOUT)

    ARGV.each do | filename |
      bf.run(filename)
    end

Brainfuck: Bottles of beer program “bottles.bf”

Example taken from https://github.com/honzasp/brainfuck/blob/master/machine/examples/ryan_beer.bf


    >>>>>++++++++[<+++++++++>-]<+[>>[>]+[<]<-]>++++++++++[<+++++
    +++++>-]<[>>[+>]<[<]<-]<++++++++[>++++++++[>>->->->>>>>>>>>>
    >->>>->>>>>>->->->->>->>>->>>>->>>>>->->>>>>>->>>>->>>>>->->
    >>>>->>>->>>>>>>->-[<]<-]>>++>++>->>+>++>++>+>>>>++>>->+>>->
    >>>++>>+>+>+>--->>->+>+>->++>>>->++>>+>+>+>--->>-->>+>>->+>+
    >>->>+>++>+>+>->+>>++>++>->>++>->>++>+>++>+>>+>---[<]<<-]>>>
    ++++>++++>+++>--->++>->->->>[-]>->-->[-]>+++>++>+>+++>--->>>
    --->[-]>+>+>+>--->[-]>+++>++>+>+++>->+++>>+++>++>---->->->+>
    --->[-]>->---->-->>+++>++>+>>+++>->++>++>+>->+++>+++>---->--
    >-->+++>++++>->+++>---->--->++>>+>->->---[[<]<]+++++++++[<+<
    +++++++++++>>-]<<[>>>>>[<]>[.>]>--[>.>]<[<<]>++>>>[.>]>[>]>[
    .>]<[[<]<]>>[.>]>--[>.>]<[<<]>++>>>[.>]>[.>]>[>]>[.>]<[[<]<]
    <<[<]>>>+<[>-]>[>]<[+++++++++[<+<->>>>>+<<<-]+<<[>>-]>>>[<]<
    <<++++++++++>>[>>[-]+<<-]>>-<<]>>>-[>]>-<<[<]>[.>]>--[>.>]<[
    <<]>++>>>[.>]>[>]>[.>]<.[[<]<]<<[<]>>-<-]

running ruby brainfuck.rb bottles.bf outputs


    99 bottles of beer on the wall.
    99 bottles of beer...
    Take one down, pass it around,
    98 bottles of beer on the wall.

    98 bottles of beer on the wall.
    98 bottles of beer...
    Take one down, pass it around,
    97 bottles of beer on the wall.

    97 bottles of beer on the wall.
    97 bottles of beer...
    Take one down, pass it around,
    96 bottles of beer on the wall.

    96 bottles of beer on the wall.
    96 bottles of beer...
    Take one down, pass it around,
    95 bottles of beer on the wall.

    95 bottles of beer on the wall.
    95 bottles of beer...
    Take one down, pass it around,
    94 bottles of beer on the wall.

    94 bottles of beer on the wall.
    94 bottles of beer...
    Take one down, pass it around,
    93 bottles of beer on the wall.

    93 bottles of beer on the wall.
    93 bottles of beer...
    Take one down, pass it around,
    92 bottles of beer on the wall.

    92 bottles of beer on the wall.
    92 bottles of beer...
    Take one down, pass it around,
    91 bottles of beer on the wall.

    91 bottles of beer on the wall.
    91 bottles of beer...
    Take one down, pass it around,
    90 bottles of beer on the wall.

    90 bottles of beer on the wall.
    90 bottles of beer...
    Take one down, pass it around,
    89 bottles of beer on the wall.

    89 bottles of beer on the wall.
    89 bottles of beer...
    Take one down, pass it around,
    88 bottles of beer on the wall.

    88 bottles of beer on the wall.
    88 bottles of beer...
    Take one down, pass it around,
    87 bottles of beer on the wall.

    87 bottles of beer on the wall.
    87 bottles of beer...
    Take one down, pass it around,
    86 bottles of beer on the wall.

    86 bottles of beer on the wall.
    86 bottles of beer...
    Take one down, pass it around,
    85 bottles of beer on the wall.

    85 bottles of beer on the wall.
    85 bottles of beer...
    Take one down, pass it around,
    84 bottles of beer on the wall.

    84 bottles of beer on the wall.
    84 bottles of beer...
    Take one down, pass it around,
    83 bottles of beer on the wall.

    83 bottles of beer on the wall.
    83 bottles of beer...
    Take one down, pass it around,
    82 bottles of beer on the wall.

    82 bottles of beer on the wall.
    82 bottles of beer...
    Take one down, pass it around,
    81 bottles of beer on the wall.

    81 bottles of beer on the wall.
    81 bottles of beer...
    Take one down, pass it around,
    80 bottles of beer on the wall.

    80 bottles of beer on the wall.
    80 bottles of beer...
    Take one down, pass it around,
    79 bottles of beer on the wall.

    79 bottles of beer on the wall.
    79 bottles of beer...
    Take one down, pass it around,
    78 bottles of beer on the wall.

    78 bottles of beer on the wall.
    78 bottles of beer...
    Take one down, pass it around,
    77 bottles of beer on the wall.

    77 bottles of beer on the wall.
    77 bottles of beer...
    Take one down, pass it around,
    76 bottles of beer on the wall.

    76 bottles of beer on the wall.
    76 bottles of beer...
    Take one down, pass it around,
    75 bottles of beer on the wall.

    75 bottles of beer on the wall.
    75 bottles of beer...
    Take one down, pass it around,
    74 bottles of beer on the wall.

    74 bottles of beer on the wall.
    74 bottles of beer...
    Take one down, pass it around,
    73 bottles of beer on the wall.

    73 bottles of beer on the wall.
    73 bottles of beer...
    Take one down, pass it around,
    72 bottles of beer on the wall.

    72 bottles of beer on the wall.
    72 bottles of beer...
    Take one down, pass it around,
    71 bottles of beer on the wall.

    71 bottles of beer on the wall.
    71 bottles of beer...
    Take one down, pass it around,
    70 bottles of beer on the wall.

    70 bottles of beer on the wall.
    70 bottles of beer...
    Take one down, pass it around,
    69 bottles of beer on the wall.

    69 bottles of beer on the wall.
    69 bottles of beer...
    Take one down, pass it around,
    68 bottles of beer on the wall.

    68 bottles of beer on the wall.
    68 bottles of beer...
    Take one down, pass it around,
    67 bottles of beer on the wall.

    67 bottles of beer on the wall.
    67 bottles of beer...
    Take one down, pass it around,
    66 bottles of beer on the wall.

    66 bottles of beer on the wall.
    66 bottles of beer...
    Take one down, pass it around,
    65 bottles of beer on the wall.

    65 bottles of beer on the wall.
    65 bottles of beer...
    Take one down, pass it around,
    64 bottles of beer on the wall.

    64 bottles of beer on the wall.
    64 bottles of beer...
    Take one down, pass it around,
    63 bottles of beer on the wall.

    63 bottles of beer on the wall.
    63 bottles of beer...
    Take one down, pass it around,
    62 bottles of beer on the wall.

    62 bottles of beer on the wall.
    62 bottles of beer...
    Take one down, pass it around,
    61 bottles of beer on the wall.

    61 bottles of beer on the wall.
    61 bottles of beer...
    Take one down, pass it around,
    60 bottles of beer on the wall.

    60 bottles of beer on the wall.
    60 bottles of beer...
    Take one down, pass it around,
    59 bottles of beer on the wall.

    59 bottles of beer on the wall.
    59 bottles of beer...
    Take one down, pass it around,
    58 bottles of beer on the wall.

    58 bottles of beer on the wall.
    58 bottles of beer...
    Take one down, pass it around,
    57 bottles of beer on the wall.

    57 bottles of beer on the wall.
    57 bottles of beer...
    Take one down, pass it around,
    56 bottles of beer on the wall.

    56 bottles of beer on the wall.
    56 bottles of beer...
    Take one down, pass it around,
    55 bottles of beer on the wall.

    55 bottles of beer on the wall.
    55 bottles of beer...
    Take one down, pass it around,
    54 bottles of beer on the wall.

    54 bottles of beer on the wall.
    54 bottles of beer...
    Take one down, pass it around,
    53 bottles of beer on the wall.

    53 bottles of beer on the wall.
    53 bottles of beer...
    Take one down, pass it around,
    52 bottles of beer on the wall.

    52 bottles of beer on the wall.
    52 bottles of beer...
    Take one down, pass it around,
    51 bottles of beer on the wall.

    51 bottles of beer on the wall.
    51 bottles of beer...
    Take one down, pass it around,
    50 bottles of beer on the wall.

    50 bottles of beer on the wall.
    50 bottles of beer...
    Take one down, pass it around,
    49 bottles of beer on the wall.

    49 bottles of beer on the wall.
    49 bottles of beer...
    Take one down, pass it around,
    48 bottles of beer on the wall.

    48 bottles of beer on the wall.
    48 bottles of beer...
    Take one down, pass it around,
    47 bottles of beer on the wall.

    47 bottles of beer on the wall.
    47 bottles of beer...
    Take one down, pass it around,
    46 bottles of beer on the wall.

    46 bottles of beer on the wall.
    46 bottles of beer...
    Take one down, pass it around,
    45 bottles of beer on the wall.

    45 bottles of beer on the wall.
    45 bottles of beer...
    Take one down, pass it around,
    44 bottles of beer on the wall.

    44 bottles of beer on the wall.
    44 bottles of beer...
    Take one down, pass it around,
    43 bottles of beer on the wall.

    43 bottles of beer on the wall.
    43 bottles of beer...
    Take one down, pass it around,
    42 bottles of beer on the wall.

    42 bottles of beer on the wall.
    42 bottles of beer...
    Take one down, pass it around,
    41 bottles of beer on the wall.

    41 bottles of beer on the wall.
    41 bottles of beer...
    Take one down, pass it around,
    40 bottles of beer on the wall.

    40 bottles of beer on the wall.
    40 bottles of beer...
    Take one down, pass it around,
    39 bottles of beer on the wall.

    39 bottles of beer on the wall.
    39 bottles of beer...
    Take one down, pass it around,
    38 bottles of beer on the wall.

    38 bottles of beer on the wall.
    38 bottles of beer...
    Take one down, pass it around,
    37 bottles of beer on the wall.

    37 bottles of beer on the wall.
    37 bottles of beer...
    Take one down, pass it around,
    36 bottles of beer on the wall.

    36 bottles of beer on the wall.
    36 bottles of beer...
    Take one down, pass it around,
    35 bottles of beer on the wall.

    35 bottles of beer on the wall.
    35 bottles of beer...
    Take one down, pass it around,
    34 bottles of beer on the wall.

    34 bottles of beer on the wall.
    34 bottles of beer...
    Take one down, pass it around,
    33 bottles of beer on the wall.

    33 bottles of beer on the wall.
    33 bottles of beer...
    Take one down, pass it around,
    32 bottles of beer on the wall.

    32 bottles of beer on the wall.
    32 bottles of beer...
    Take one down, pass it around,
    31 bottles of beer on the wall.

    31 bottles of beer on the wall.
    31 bottles of beer...
    Take one down, pass it around,
    30 bottles of beer on the wall.

    30 bottles of beer on the wall.
    30 bottles of beer...
    Take one down, pass it around,
    29 bottles of beer on the wall.

    29 bottles of beer on the wall.
    29 bottles of beer...
    Take one down, pass it around,
    28 bottles of beer on the wall.

    28 bottles of beer on the wall.
    28 bottles of beer...
    Take one down, pass it around,
    27 bottles of beer on the wall.

    27 bottles of beer on the wall.
    27 bottles of beer...
    Take one down, pass it around,
    26 bottles of beer on the wall.

    26 bottles of beer on the wall.
    26 bottles of beer...
    Take one down, pass it around,
    25 bottles of beer on the wall.

    25 bottles of beer on the wall.
    25 bottles of beer...
    Take one down, pass it around,
    24 bottles of beer on the wall.

    24 bottles of beer on the wall.
    24 bottles of beer...
    Take one down, pass it around,
    23 bottles of beer on the wall.

    23 bottles of beer on the wall.
    23 bottles of beer...
    Take one down, pass it around,
    22 bottles of beer on the wall.

    22 bottles of beer on the wall.
    22 bottles of beer...
    Take one down, pass it around,
    21 bottles of beer on the wall.

    21 bottles of beer on the wall.
    21 bottles of beer...
    Take one down, pass it around,
    20 bottles of beer on the wall.

    20 bottles of beer on the wall.
    20 bottles of beer...
    Take one down, pass it around,
    19 bottles of beer on the wall.

    19 bottles of beer on the wall.
    19 bottles of beer...
    Take one down, pass it around,
    18 bottles of beer on the wall.

    18 bottles of beer on the wall.
    18 bottles of beer...
    Take one down, pass it around,
    17 bottles of beer on the wall.

    17 bottles of beer on the wall.
    17 bottles of beer...
    Take one down, pass it around,
    16 bottles of beer on the wall.

    16 bottles of beer on the wall.
    16 bottles of beer...
    Take one down, pass it around,
    15 bottles of beer on the wall.

    15 bottles of beer on the wall.
    15 bottles of beer...
    Take one down, pass it around,
    14 bottles of beer on the wall.

    14 bottles of beer on the wall.
    14 bottles of beer...
    Take one down, pass it around,
    13 bottles of beer on the wall.

    13 bottles of beer on the wall.
    13 bottles of beer...
    Take one down, pass it around,
    12 bottles of beer on the wall.

    12 bottles of beer on the wall.
    12 bottles of beer...
    Take one down, pass it around,
    11 bottles of beer on the wall.

    11 bottles of beer on the wall.
    11 bottles of beer...
    Take one down, pass it around,
    10 bottles of beer on the wall.

    10 bottles of beer on the wall.
    10 bottles of beer...
    Take one down, pass it around,
    9 bottles of beer on the wall.

    9 bottles of beer on the wall.
    9 bottles of beer...
    Take one down, pass it around,
    8 bottles of beer on the wall.

    8 bottles of beer on the wall.
    8 bottles of beer...
    Take one down, pass it around,
    7 bottles of beer on the wall.

    7 bottles of beer on the wall.
    7 bottles of beer...
    Take one down, pass it around,
    6 bottles of beer on the wall.

    6 bottles of beer on the wall.
    6 bottles of beer...
    Take one down, pass it around,
    5 bottles of beer on the wall.

    5 bottles of beer on the wall.
    5 bottles of beer...
    Take one down, pass it around,
    4 bottles of beer on the wall.

    4 bottles of beer on the wall.
    4 bottles of beer...
    Take one down, pass it around,
    3 bottles of beer on the wall.

    3 bottles of beer on the wall.
    3 bottles of beer...
    Take one down, pass it around,
    2 bottles of beer on the wall.

    2 bottles of beer on the wall.
    2 bottles of beer...
    Take one down, pass it around,
    1 bottle of beer on the wall.

    1 bottle of beer on the wall.
    1 bottle of beer...
    Take one down, pass it around,
    0 bottles of beer on the wall.


02 2 / 2013

3D Collision detection and resolution using sweeping AABB bounding boxes

In most games there must be some kind of collision detection, in this post I will explain my implementation of sweeping AABB bounding boxes detection and resolution.

This implementation is based on solving collisions for each axis and finding the earliest possible collision in normalized time that satisfies all axises.

This example demonstrates a 2D collision using the X and Y axises only as it is easier to visualize but as you will see, adding the z axis becomes trivial.

We have two boxes, A is positioned at the vector (2, 0) and B at (10, 0).

After the boxes have moved the new position of A is (15, 0) and the position of B is (12, 0)

As you can clearly see A has moved past of B and is now well on the other side. Simply checking if A and B overlaps at their new positions will fail to detect that they have moved through one another. this is where AABB sweeping comes into play.

First we need to determine the velocity of A (VA) and B (VB) by subtracting their previous positions from their new positions.

VA = (15, 0) - (2, 0) = (15-2, 0-0) = (13, 0) VB = (12, 0) - (10, 0) = (12-10, 0-0) = (2, 0)

This means that in 1 time unit A will have moved 11 steps to the right.

We now have the velocity of A relative to the velocity of B, again we see that there will be a collision in some point in the time since A is moving towards B.

The bounding box size (S) of A and B is set to (2, 2) and their positions are always at the center of their bounding boxes. This means that the half size (HS) is (1, 1)

Finding the earliest collision time unit on the x-axis

Since the rightmost edge of A is to the left of the leftmost edge of B the distance between them on the x-axis (DX) is:

DX = (B.x - HS.x) - (A.x + HS.x) = (10-1) - (2+1) = 9 - 3 = 6

Note that DX this is the distance A needs to travel in order to collide with B on the x axis, this is also the earliest possible collision distance between A and B on the x-axis.

Now we have the distance DX between A and B and the relative velocity (V) of A, the time unit (U0.x) is the time needed to cover the distance DX relative to the velocity (V) and can be calculated as DX / V.x

U0.x = DX / V.x = 4 / 11 = 0.54545454545454545454545454545455

This means that the first collision will occur at the normalized time of U0.x and since normalized time spans between 0 -1 this is a valid first collision on the x axis.

Finding the latest collision time unit for the x-axis

Since A is to the left of B the latest collision will take place when the leftmost edge of A intersects the rightmost edge of B.

The distance (DX2) between the leftmost edge of A and rightmost edge of B is:

DX2 = (B.x + HS.x) - (A.x - HS.x) = (10+1) - (2-1) = 11 - 1 = 10

The time unit (U1.x) needed to cover that distance is:

U1.x = DX2 / V.x = 10 / 11 = 0.90909090909090909090909090909091

Since 0.9… is well in the range of normalized time (0-1) it means that there will be a second collision as A moves past B.

Finding the first and last collision times on the y axis

In order to find the earliest/latest collision times for the y-axis you just need to repeat the above steps described for the x-axis, replacing x for y.

The vector U0 will contain all of the earliest possible collision times for x and y and U1 will contain all of the latest possible collision times for x and y.

A word on infinity ∞

Since the position of y in this example never changes it means that the relative velocity in the y-axis (V.y) is 0. The distance between A and B on the y-axis is also zero.

This means that the earliest / latest possible collision time on the y-axis is either negative or positive Infinity

In order to handle this we need to add a check to the earliest collision time unit check that sets U0.y to zero if V.y is zero, we also need to add the check to the latest collision time unit check that sets U1.y to one if V.y is zero.

The general rule for this is:

U0.[axis] = 0 if V.[axis] is 0
U1.[axis] = 1 if V.[axis] is 0

Time unit sanity check

A collision has occurred only if A and B intersects on both in the y and x axis. This means that the earliest collision time unit (T0) is the maximum time unit of U0.

T0 = max(U0) = max(0.54, 0) = 0.54

This also means that the latest collision time unit (T1) is the minimum time unit of U1.

T1 = min(U1) = min(0.9, 1) = 0.9

We need to make sure that the earliest collision time (T0) occurs earlier or at the same time as the latest collision time (T1), we also need to make sure that T0 takes place within normalized time.

C1 = T0 <= T1 = 0,54 <= 0,9 = true

C2 = T0 >= 0 and T0 <= 1 = 0,54 >= 0 and 0,54 <= 1 = true

COLLISION = C1 == true and C2 == true

Collision resolution

As you now know T0 represents the normalized point in time where the first collision between A and B takes place.

By using T0 we can interpolate and position A and B using their respective velocities VA and VB.

To move A into its first collision position CPA we add VA multiplied by T0 to its previous position AP (2, 0)

CPA = AP + (VA * T0) = (2, 0) + ((13, 0) * 0.54) = ~ (2+7, 0 + 0) = (9, 0)

We do the same to move B into it’s first collision position CPB

CPB = BP + (VB * T0) = (10, 0) + ((2, 0) * 0.54) = ~ (10+1, 0 + 0) = (11, 0)

Initial positions of A (2, 0) and B (10, 0)

Resolved positions of A (9, 0) and B (11, 0)

Regarding collision resolution collisions

As you can see in the resolution of A and B they are resolved into positions snugged right next to each other.

A discrete collision check on A and B will actually detect a collision as the rightmost side of A is intersecting the leftmost side of B.

In order to counter this we can multiply the relative velocity vector (V) by its normal multiplied by a very small number like 0.00001

This will move A and B apart enough not to be touching after the collision resolution.

22 1 / 2013

Nodejs + Ogre3D + OIS + TCP/UDP Game Server

Been really busy lately with my day job, family and stuff so I’ve got no code for you this time, only a video.


I have been playing around with a game client and game server also in Node and Ogre3d, basically the code is the same as in my last post only that I added a basic TCP/UDP server written in node and after the TCP handshake is done the game client spams its current position to the game server over UDP. The server broadcasts this to all connected clients and the client then updates the position of ‘the player cube’


I have also moved the generation of the maze to the server, it is sent to all client at the end of the TCP handshake.


I initially made the stupid mistake to assume that it all could be done over TCP but as you might suspect it was a terrible so I switched over to UDP instead. It will be interesting to see if I can get this into a complete game as all of the needed components are there. We have the Node/Ogre3D bindings for the graphis, FMOD for sound/music and OIS for user input, exciting!

Tags:

Permalink 1 note

17 1 / 2013

the Minecraft Xboxes : continued

As I wrote in a previous post I won two Xbox360’s on an auction where all of the money gets donated to the My Big Day Foundation . I’m going to donate both of these myself to the play therapy departments of two different children’s hospitals in Stockholm, the Sachs’ Children and Youth Hospital and Astrid Lindgren Children’s Hospital

The play therapy is a place where sick children can get away from everything that has to do with their treatments and give them a chance to play and develop as any normal child would.

The people over at Mojang (makers of Minecraft) where kind enough to provide me with some Xbox Live codes to install Minecraft with before I hand them over to the hospitals :)

Go tweet that they are awesome!

I’m going to call the hospitals tomorrow to arrange the drop off at some point in the start of next week.

13 1 / 2013

Node.js, Ogre3D, Mouse & Keyboard input using OIS, generating a maze

I some time wish I has as much time as I used to, before I was married and had a two year old son but without throwing that away or spending less time with them.

Usually I have some time during the middle of the day when my son is napping and of course in the evenings when he gone to bed for the night. He does not like me tapping away on the keyboard while he is awake and then demands that I search Google for pictures of cats.

Anyway, I thought that I would continue on my progress with Node and Ogre3D and this time I am going to show a demo where I am handling mouse & keyboard input using OIS (Object Oriented Input System).

Again, Minecraft looking graphics as I am far from any kind of genius artist wonder :)

I have created a repository for the demos over at Github so you can download and run them from there. The repository is https://github.com/creamdog/Node.Ogre and this particular demo is https://github.com/creamdog/Node.Ogre/tree/master/NO.3%20-%20OIS

As usual you need only execute the demo.bat file or runt node.exe demo.js from the console.

Here is a recorded video of the demo.

Generating a maze

To demonstrate this I have written a maze generator using recursive backtracking

This generates a nice looking maze, however it could be kind of boring walking around in only narrow corridors so I’ve added a post step to the generation process where solid blocks with three free sides are removed in X iterations.

This creates both nice open areas as well as narrow pathways.

Initializing OIS

the OIS initialization is pretty straight forward after you have created the window. just pass it a window handle, get the mouse and keyboard object and restrict mouse movement by the width/height of the window.


    ois = require('./modules/ois');
    oisInputManager = ois.createInputSystem(window.getHandle());
    keyboard = oisInputManager.getKeyboard();
    mouse = oisInputManager.getMouse();
    mouse.setHeight(window.getHeight());
    mouse.setWidth(window.getWidth());

Moving and looking around

In this demo you can move around using the WASD keys and look around by moving the mouse, like in any FPS.

Basically after this all you need to do is call the .capture() function on both the mouse and keyboard object at the beginning of each frame. After this you can check if a key is pressed by calling for example keyboard.isKeyDown(1) for the ESC key. The number passed to this function is the numerical representation of the OIS::KeyCode enum.

To check if the mouse cursor has moved you call mouse.getXRel() and mouse.getYRel(), both of these return the relative movement of the cursor since the last call to mouse.capture().

The following snippet is the “main loop” of this demo, I also added a “head bopping” simulation when you are moving using the keyboard.


var interval = 0;
function mainLoop() {
    keyboard.capture();
    mouse.capture();
    if(window.isClosed() || keyboard.isKeyDown(1)) {
        clearInterval(interval);
        if(keyboard.isKeyDown(1)) {
            console.log("used pressed ESC, shutting down");
        } else { 
            console.log("window has been closed, shutting down");
        }
        return;
    }
    // move around using the keyboard
    if(keyboard.isKeyDown(17)) {
        cameraNode.translate(0,0,-0.15, 0);
    } else if(keyboard.isKeyDown(31)) {
        cameraNode.translate(0,0, 0.15, 0);
    }
    if(keyboard.isKeyDown(30)) {
        cameraNode.translate(-0.15, 0, 0.0, 0);
    } else if(keyboard.isKeyDown(32)) {
        cameraNode.translate( 0.15, 0, 0.0, 0);
    }
    // look around using the mouse
    var mx = mouse.getXRel() / window.getWidth();
    var my = mouse.getYRel() / window.getHeight();
    cameraNode.yaw(mx*-10, 2);
    cameraNode.pitch(my*-10, 0);
    // simulate "head bopping" when player is moving
    var boppy = 0;
    var r = boppr;
    if(keyboard.isKeyDown(17) || keyboard.isKeyDown(31) || keyboard.isKeyDown(30) || keyboard.isKeyDown(32)) {
        boppr += Math.PI / 10;
        if(boppr>Math.PI)
            boppr = Math.PI - boppr;
    } else {
        boppr = 0;
    }
    boppy = Math.sin(boppr)*0.2;
    // adjust camera y-position to simulate "head bopping"
    cameraNode.setPosition(cameraNode.getPosition().x, boppy, cameraNode.getPosition().z);
    // move light along with the player
    lightNode.setPosition(cameraNode.getPosition().x, cameraNode.getPosition().y, cameraNode.getPosition().z);

    window.update(false);
    window.swapBuffers(true);
    root.renderOneFrame();
    window.messagePump();
}
interval = setInterval(mainLoop, 1);

And there you have it, feel free to poke around in the source that you can find at https://github.com/creamdog/Node.Ogre/tree/master/NO.3%20-%20OIS

Tags:

Permalink 1 note

11 1 / 2013

the Minecraft Xbox

Yesterday I won a 250GB black Xbox 360 on an action on Tradera (ebay owned Swedish auction site)

The Xbox is signed by all the makers of Minecraft including Notch and all of the money made from this auction goes straight to the My Big Day Foundation

“The goal of MinStoraDag, (My Big Day), is to grant wishes to critically ill children (3-18yrs) who are suffering from life-threatening diseases. The foundation’s work is unique as each child is actively involved in planning his or her own wish.”

I am not a big IT millionare and the price I payed for the XBox is a modest 2550 SEK (~300 EUR) but when I get the Xbox by next week I have arranged to donate it to the play therapy department over at the Sachs’ Children and Youth Hospital in Stockholm.

When I spoke to the person over at the play therapy she said that they already had an Xbox but could use another to roll around to children who are unable to attend the play therapy, I think this is an excellent use of this Xbox.

My wife has been working with seriously ill children even before we met and for me that works as a software developer it has made me reflect about life and people in need. I still remember when I visited the play therapy at Huddinge hospital (also in Stockholm) and the small girl with tubes everywhere playing in the toy kitchen with her mom. The hospitals has such a small budget to spend on making these kids happy and they need all of the help they can get.

With this I hope that the My Big Day Foundation can help make some kids dream come true and that the Xbox will bring some happiness to the kids over at the hospital.

This was the first out of four signed Xboxes and if you would like to bid on the next one you can do so over at http://www.tradera.com/xbox-signerad-av-minecraft-ganget-swish-f06-auktion_301611_172702018 (auction will end in 2 days)

I can post some pics of the XBox before I drop it off by next week.

update 2012-01-13

I actually won the bidding on the second Xbox as well and I will donate this to the play therapy department over at Astrid Lindgren Children’s Hospital in Stockholm.

There are two more Minecraft XBoxes to go but I am all out of money, so if you would like to bid on items where all the money goes to My Big Day head over to the items listed at http://www.tradera.com/finding.mvc/itemlisting?ftgnr=948378 and take your pick!

07 1 / 2013

Building Ogre in Windows 7/8 using Visual Studio 2012

Since there are no prebuilt Ogre SDK’s targeting Visual Studio 2012 I decided to build it myself from source.

This is a guide on how to build Ogre in Windows using CMake and Visual Studio.

Prerequisites

This guide assumes you are running Windows 7/8 and have Visual Studio 2012 installed.

Needed software

CMake

You will need this to configure Ogre and it’s dependencies. Download and install it from http://www.cmake.org/cmake/resources/software.html

Mercurial

You will need this as Ogre uses this as their source code versioning system. Install it using the big blue button over at http://mercurial.selenic.com

DirectX SDK / Windows SDK

If you want to build Ogre with support for DirectX you will need to install the DirectX SDK for Windows 7 or just the Windows SDK if you are running Windows 8.

You can download the DirectX Software Development Kit from http://www.microsoft.com/en-us/download/details.aspx?id=6812

If the DirectX SDK or WindowsSDK installer fails with something like error S1023 you should follow this guide on how to uninstall and re-install the “Visual C++ 2010 Redistributable Package “

You can skip this and only build the Ogre OpenGL rendering system.

Download and build the Ogre dependencies

Here we will clone and build the Ogre dependencies project from https://bitbucket.org/cabalistic/ogredeps using Mercrial and CMake.

clone the Ogre dependencies repository

Create the directory c:/projects/ and open it in the windows explorer, right click and choose “TortoiseHg > Clone…”

Set “https://bitbucket.org/cabalistic/ogredeps” as the source and “c:\projects\ogredeps” as the destination, click clone and let it finish.

Configure the dependencies project using CMake

Start CMake and set “Where is the source code” to c:/projects/ogredeps. Click on the “Configure” button at the lower left.

In the dialog choose “Visual Studio 11” in the dropdown and click “Finish”

Set “CMAKE_INSTALL_PREFIX” to c:/projects/ogredeps/install

Set “Where to build the binaries” to “c:/projects/ogredeps/build” and click on “Generate”, it will create solution files for you in c:/projects/ogredeps/build

Build the Ogre Dependencies using Visual Studio

open the solution file c:/projects/ogredeps/build/OGREDEPS.sln and build the “ALL_BUILD” project using both debug and release mode, then build the “INSTALL” project using both release and debug, this will build and install the dependencies to c:/projects/ogredeps/install

Download and build Ogre

We now have all of the tools and dependencies needed to build Ogre.

clone the Ogre repository

Open the c:/projects folder in the windows explorer, using TortoiseHg clone “https://bitbucket.org/sinbad/ogre/ -u v1-8” into c:/projects/ogre/

This will create a clone of the latest unstable branch, right click on the folder c:/projects/ogre/, choose TortoiseHg > Update and change the branch version to “v1-8” and click the update button.

v1-8 is the latest stable version of Ogre as I am writing this, check http://www.ogre3d.org/developers/mercurial if this has changed when you are reading this.

Configure Ogre using CMake

Start CMake and set “Where is the source code” to c:/projects/ogre. Click on the “Configure” button at the lower left.

In the dialog choose “Visual Studio 11” in the drop-down and click “Finish”

CMake will fail, this is ok, we will fix it.

set “Where to build the binaries” to c:/projects/ogre/build

set “OGRE_DEPENDENCIES_DIR” to c:/projects/ogredeps/install

set “CMAKE_INSTALL_PREFIX” to c:/OgreSDK

make sure to check both “OGRE_BUILD_SAMPLES” and “OGRE_INSTALL_SAMPLES” if you wanna test Ogre after the build/install.

now click on “Configure” and then on “Generate” and it will generate the solution files for us in c:/projects/ogre/build

Build Ogre using Visual Studio

Open the solution file c:/projects/ogre/build/OGRE.sln and build the “ALL_BUILD” project using both debug and release mode, then build the “INSTALL” project using both release and debug, this will build and install the Ogre SDK and Samples into c:/OgreSDK

All done! you have now successfully built and installed Ogre into c:/OgreSDK

Execute C:\OgreSDK\bin\release\SampleBrowser.exe to view the prebuilt demos.

04 1 / 2013

Node.js, Ogre3D, Materials and Lighting

Thought that would post a quick post on my progress but limit it to basic texturing and lighting (and some music).

For this demo I am going to intialize ogre3d, create a window, load some textures/materials, generate a landscape (minecraft like), position some light and spin it around.

Please excuse my poor artistic skills :)

As before you can download from here, run it by either double-clicking the demo.bat file or run ./node.exe demo.js from a console.

If you can’t run the demo or don’t want to here is a video of it running (sorry for the choppy framerate, it is the video, not the demo)

This is the structure of this demo

resources/
-- birds_in_the_woods.mod
-- sky.material
-- textures.jpg
-- textures.material
demo.js
graphics.js
music.js
terrain.js

As you can see there is a resource folder for the music, texture and materials. the materials are standard ogre material script files.

I did start out wrapping functionality to diagrammatically generate textures in Nodejs but later decided it be best just leave it to Ogre to parse material scripts. This way you get all of the material functionality in Ogre without the need to port/wrap anything.

In the material files you can specify several passes (layers) optionally along with shaders to spice things up if you really want to.

The demo.js file

this is basically the entry point of the demo, initializing the music, graphics and contains the program “main loop”.


//lets have some music
music = require('./music.js');
music.initialize();

//initilize Ogre, generate some terrain and set up the scene
graphics = require('./graphics.js');
graphics.initialize();

//play the music
music.play();

//main loop here
loopInterval = null;
function mainLoop() {
    if(graphics.isClosed()) {
        console.log("window closed, shutting down");
        clearInterval(loopInterval);    
        return;
    }
    graphics.update();
}
loopInterval = setInterval(mainLoop, 1);

The graphics.js file

This one is a bit larger, it contains variable declarations in the beginning for what plugins to load, the window size and title, and also holder for some ogre objects such as the scene manager, a camera, a viewport and the root scene node.

The following are new additions to the graphics initialize function since the last demo.

intitializeResources

this is used to point out the ./resources catalog as an additional resource in Ogre as well as initializing all resource groups.

Resource groups in Ogre are used for everything, like textures, materials, shaders, fonts, etc

The following will load up the two material files textures.material and sky.material into the default Ogre resource group.


function intitializeResources() {
    root.addResourceLocation('./resources','FileSystem');
    resourceManager = root.getResourceGroupManager();
    resourceManager.initializeAllResourceGroups();
}

createLights

used to first set the ambient lighting of the current scene and then creates and positions two lights that will be used to light up the terrain.

Diffuse is the general color of the light, attenuation controls how far the light will “reach”.


function createLights() {

    sceneManager.setAmbientLight(0.15, 0.1, 0.125);

    light = sceneManager.createLight();
    light.setAttenuation(100, 1.0, 0.045, 0.0075);
    light.setDiffuseColour(1.0, 0.5, 0.0);
    light.setSpecularColour(1.0, 1.0, 0.0);
    lightNode = rootSceneNode.createChildSceneNode("lightNode");
    lightNode.attachLight(light);
    lightNode.translate(5,5,-10.0);

    light2 = sceneManager.createLight();
    light2.setAttenuation(100, 1.0, 0.045, 0.0075);
    light2.setDiffuseColour(0.0, 0.0, 1.0);
    lightNode2 = rootSceneNode.createChildSceneNode("lightNode2");
    lightNode2.attachLight(light2);
    lightNode2.translate(-10,5,-10.0);
}

after the lights has been created the last thing that happens in the graphics initialize function is to generate the terrain using the terrain.js file, load and position the terrain and create a “night time sky” using the ./resources/sky.material file.


    //set the mood
    createLights();

    //generate some terrain
    terrain = require('./terrain.js');
    terrain.createTerrainMesh('TerrainObject', 'TerrainMesh');

    //create a terrain instance and position it
    var entity = sceneManager.createEntity("TerrainMesh");
    entity.setCastsShadows(false);
    var node = rootSceneNode.createChildSceneNode("TerrainNode");
    node.attachEntity(entity);
    node.translate(0,-10,-10.0);
    node.pitch(0.35);
    cubeNode = node;
    cubeEntity = entity;

    //create a sky using the 'sky' material
    sceneManager.setSkyDome('sky');

    root.clearEventTimes();
};

The terrain.js file

This is what generates the minecraft like terrain in the demo, it is a very crude way to generate terrain using a boolean 128x128x128 array.

Basically what it does is to first create a Ogre ManualObject which is used to generate a mesh.

Using the boolean 128x128x128 array it first creates all of the vertices, normals, texture coordinates and colours. It skips array positions that are false

After that is done it creates the cube sides by mapping triangles to the vertices, again using the boolean 128x128x128 array. It It skips array positions that are false and also do not create cube sides that touch another cube.

The material used is the textured material from the file ./resources/textures.material and the image from ./resources/textures.jpg

This texture is actually a sprite texture that contains both the dirt/grass and combination. the top of the cubes get mapped with the coordinates of the grass part and the sides of the cube get mapped with the combination of grass and dirt.

Again, you can download the demo from here, run it by either double-clicking the demo.bat file or run ./node.exe demo.js from a console.

31 12 / 2012

Node.js+Ogre3D+Fmod-Demo 1

this is the first part in a series of posts where I will be posting about 3D application development in Node using Ogre (and FMOD)

Follow this link for the second part of the series “Node.js, Ogre3D, Materials and Lighting”

Nine years ago I wrote a demo using FMOD and OpenGL direct mode in C++ using Visual Studio 6.0, sadly both the source and binaries has been lost in the myriad of disk crashes and broken CD’s since then.

For the last couple of years I have been doing mainly .NET development but I have felt the urge to get back to writing some C/C++ and thought that, “hey! why not pick up some Node.js as well” ?

Instead of going straight OpenGL I decided to try something new and use a 3D-engine, I decided to use Ogre3D as it is open source.

I also had a lot of help from the Ogre3D Mad Marx Tutorials

Since I am running Windows 8 and using Visual Studio 2012 I needed to build and install Ogre3D from source. I will not go into the details here on how to go about setting that up.

the FMOD binaries and headers is a straight download from http://www.fmod.org

I then installed Node.js (32-bit version because Ogre3D compiled as 32-bit)

Then with the help of Node.js API docs I wrapped both Ogre3D and FMOD in two separate addons called “OgreToNode.node” and “fmod.node”

I will not go into the details on how to build the addons here, they are a mess right now but they work as a proof of concept.

Now, using these addons I was ready to write a simple demo in node! :)

The demo is available for download from the link below, run it by executing the “demo.bat” file or from a console window running “node.exe demo.js”

Download: http://creamdog.se/NodeOgreFMODPart1.zip

If you can’t run the demo or don’t want to here is a video of it running (sorry for the choppy framerate, it is the video, not the demo)

All of the following code is from the file “demo.js”

1. Intitialize FMOD and load the music

The following code is pretty straight forward, create a fmod system instance, initialize it, create a sound channel and load a .mod file (I could have loaded a mp3 or something but this is the .mod I used in my original demo nine years ago)

Note that this code does not begin playback of the .mod



music = {
    fmod: require('./modules/fmod'),
    fmodSystem: null,
    channel: null,
    sound: null,
    mediafile: './media/music.mod',
    initialize: function() {
        music.fmodSystem = music.fmod.createFmodSystem();
        music.fmodSystem.init();
        var version = music.fmodSystem.getVersion();
        console.log("fmod intialized, version = "+version);
        music.channel = music.fmod.createChannel();
        console.log("loading sound from "+music.mediafile);
        music.sound = music.fmodSystem.createSound(music.mediafile);
    },
    play: function() {
        console.log('playing '+music.mediafile+' ('+music.sound.getLength()+'ms)');
        music.fmodSystem.playSound({sound:music.sound, channel:music.channel});
    }
}
music.initialize();

.

2. Initialize Ogre3D

This is a bit more complicated, you need to create a Ogre Root instance, load needed plugins such as OpenGL (the rendering system), creating a window, creating a scene, positioning the camera, generating, loading an positioning the spinning cube.


graphics = {
    ogre : require('./modules/OgreToNode'),
    logfile: 'demo.log',
    root: null,
    window: null,
    windowTitle: 'Node.js Ogre/Fmod Demo',
    windowWidth: 800,
    windowHeight: 600,
    sceneManager: null,
    rootSceneNode: null,
    camera: null,
    cameraNode: null,
    viewPort:null,
    cubeEntity: null,
    cubeNode: null,
    plugins: [  
        './modules/RenderSystem_GL_d',
        './modules/Plugin_ParticleFX_d',
        './modules/Plugin_CgProgramManager_d',
        './modules/Plugin_OctreeSceneManager_d'
    ],
    initialize: function() {
        console.log("intializing ogre...");
        graphics.root = graphics.ogre.createRoot("", "", graphics.logfile);
        graphics.loadPlugins();
        graphics.root.setRenderSystemByName(graphics.root.getRenderSystemNames()[0]);
        graphics.createWindow();
        graphics.sceneManager = graphics.root.createSceneManager({name: "TheSceneManager"});
        graphics.rootSceneNode = graphics.sceneManager.getRootSceneNode();
        graphics.createCamera();
        graphics.createViewport();      
        //configure the camera
        var ratio = graphics.viewPort.getActualWidth() / graphics.viewPort.getActualHeight();
        graphics.camera.setAspectRatio(ratio);
        graphics.camera.setNearClipDistance(0.5);
        graphics.camera.setFarClipDistance(3000);
        //configure window
        graphics.window.setActive(true);
        graphics.window.setAutoUpdated(false);
        graphics.root.clearEventTimes();
        //generate and load the spinning cube
        graphics.generateCubeMesh();
        graphics.loadCubeMesh();
    },
    createCamera: function() {
        console.log("creating ogre camera...");
        graphics.camera = graphics.sceneManager.createCamera({name: "TheCamera"});
        graphics.cameraNode = graphics.rootSceneNode.createChildSceneNode({name: "TheCameraNode"});
        graphics.cameraNode.attachCamera(graphics.camera);
    },
    createViewport: function() {
        console.log("creating ogre viewport...");
        var viewPortWidth = 0.98;
        var viewPortHeight = 0.98;
        var viewPortLeft = (1.0 - viewPortWidth) * 0.5;
        var viewPortTop = (1.0 - viewPortHeight) * 0.5;
        graphics.viewPort = graphics.window.addViewPort(
        {
            camera: graphics.camera, 
            zorder: 100, 
            top: viewPortTop, 
            left: viewPortLeft, 
            width: viewPortWidth, 
            height: viewPortHeight
        });
        graphics.viewPort.setAutoUpdated(true);
        graphics.viewPort.setBackgroundColour(0.0,0,0.0,1.0);
    },
    createWindow: function() {
        console.log("creating ogre window...");
        graphics.window = graphics.root.createRenderWindow(
        {
            title: graphics.windowTitle, 
            width: graphics.windowWidth, 
            height: graphics.windowHeight, 
            fullscreen: false, 
            params: {"FSAA":"0", "vsync":"true"}
        });
    },
    loadPlugins: function() {
        console.log("loading ogre plugins...");
        for(var i=0;i<graphics.plugins.length;i++) {
            graphics.root.loadPlugin(graphics.plugins[i]);  
        }
    },
    loadCubeMesh: function() {
        var entity = graphics.sceneManager.createEntity("CubeMesh");
        var node = graphics.rootSceneNode.createChildSceneNode("CubeNode");
        node.attachEntity(entity);
        node.translate(0,0,-5.0);
        graphics.cubeNode = node;
        graphics.cubeEntity = entity;
    },
    generateCubeMesh: function() {
        // Example taken from "MadMarx Tutorial 4 - ManualObject to Mesh"
        // http://www.ogre3d.org/tikiwiki/tiki-index.php?page=MadMarx+Tutorial+4&structure=Tutorials
        console.log("generating cube mesh...");
        var size = 0.7;
        var object = graphics.sceneManager.createManualObject("CubeMeshObject");
        object.setDynamic(false);
        object.begin({material:"BaseWhiteNoLighting",renderOperation:4});
        {
            var cp = 1.0 * size ;
            var cm = -1.0 * size;

            object.position(cm, cp, cm);// a vertex
            object.colour(0.0,1.0,0.0,1.0);
            object.position(cp, cp, cm);// a vertex
            object.colour(1.0,1.0,0.0,1.0);
            object.position(cp, cm, cm);// a vertex
            object.colour(1.0,0.0,0.0,1.0);
            object.position(cm, cm, cm);// a vertex
            object.colour(0.0,0.0,0.0,1.0);

            object.position(cm, cp, cp);// a vertex
            object.colour(0.0,1.0,1.0,1.0);
            object.position(cp, cp, cp);// a vertex
            object.colour(1.0,1.0,1.0,1.0);
            object.position(cp, cm, cp);// a vertex
            object.colour(1.0,0.0,1.0,1.0);
            object.position(cm, cm, cp);// a vertex
            object.colour(0.0,0.0,1.0,1.0);

            // face behind / front
            object.triangle(0,1,2);
            object.triangle(2,3,0);
            object.triangle(4,6,5);
            object.triangle(6,4,7);

            // face top / down
            object.triangle(0,4,5);
            object.triangle(5,1,0);
            object.triangle(2,6,7);
            object.triangle(7,3,2);

            // face left / right
            object.triangle(0,7,4);
            object.triangle(7,0,3);
            object.triangle(1,5,6);
            object.triangle(6,2,1);         
        }
        object.end();
        object.convertToMesh("CubeMesh");
    }
}
graphics.initialize();

.

3. wrapping it all up

Lastly I start playing the music and enter the main program loop. Inside the loop I fetch the spectrum from the left speaker as it it there the drums are in the playing .mod.

Using that I pulse the cube along the z-axis.


music.play();
cubeBackTranslation = 0;
loopInterval = null;
function mainLoop() {

    if(graphics.window.isClosed()) {
        console.log("shutting down");
        clearInterval(loopInterval);    
        root.shutdown();
        return;
    }

    //get left side spectrum, where the drums are
    var spectrum = music.channel.getSpectrum(0);

    //calculate median value and amplify
    var median = 0;
    for(var i=0;i<spectrum.length-1;i++) {
        median += spectrum[i];
    }
    median = median / spectrum.length;
    median *= 300;

    //spinn the cube
    graphics.cubeNode.yaw(Math.random()*0.02);
    graphics.cubeNode.pitch(Math.random()*0.03);

    //pulsate the cube along the z-axis
    graphics.cubeNode.translate(0,0,median+cubeBackTranslation);
    cubeBackTranslation = -median;

    graphics.window.update(false);
    graphics.window.swapBuffers(true);
    graphics.root.renderOneFrame();
    graphics.window.messagePump();
}
loopInterval = setInterval(mainLoop, 1);

.

Download the demo from here: http://creamdog.se/NodeOgreFMODPart1.zip

Follow this link for the second part of the series “Node.js, Ogre3D, Materials and Lighting”

17 12 / 2012

Installing CyanogenMod Android 4.1.2 on the Samsung Galaxy Tab 10.1 P7500

Background

I bought a Samsung Galaxy Tab 10.1 (model P7500) in November 2011, it came with Android 3 (HoneyComb) installed which was the tablet version of Android. Of course I was expecting Samsung to push out 4.x at some time under 2012 but it does not seem very likely that they will come through (the Android 4.0 version is still listed as preliminary for Q4 2012)

Of course I could just go out and purchase the Samsung Galaxy 10.1 version 2 tables, I am sure that would make Samsung very happy and my wife very angry with me so I decided to do it myself and install CyanogenMod 10 with Android 4.1.2

Everything is working fine running this version of CyanogenMod, 3G, Wifi and the Camera, all good!

Note that I am using Windows 8 but it should work using 7 or Vista, I guess.

important: you are doing all of this on your own risk, I can not be held responsible if you brick your device.

Download all the necessary files

You will need the USB driver, ClockworkMod, TabRootEasy, nightly build of CyanogenMod and the Google Apps Package.

important: first unplug your Galaxy Tab 10.1 from your computer if it is connected.

  1. Download and install the Samsung Tab Windows Driver for Windows from http://androiddrivers.net/samsung-android-drivers/download-samsung-galaxy-tab-10-1-windows-drivers/

  2. Download and unzip http://downloadandroidrom.com/file/GalaxyTab10.1/recovery/Tab10.1WifiRecovery.zip to C:/tmp/samsung/Tab10.1WifiRecovery/ this contains the windows application ODIN used to install ClockworkMod to your Samsung Galaxy Tab.

  3. Download http://droidbasement.com/galaxy/recovery/cwm5/p4/2/recovery.tar.md5 to C:/tmp/samsung/Tab10.1WifiRecovery/recovery.tar.md5 (this is the ClockworkMod 5.5.0.4 application)

  4. Download and unzip TabRootEasy from http://downloadandroidrom.com/file/GalaxyTab10.1/rooting/tabrooteasy.zip to C:/tmp/samsun/tabrooteasy/

  5. Download the latest nightly CyanogenMod build from http://get.cm/?device=p4&type= to c:/tmp/samsung/cm-10-20121216-NIGHTLY-p4.zip or whatever the latest build is named when you do this. Do not unzip this file.

  6. Download Google Apps (this will add Google Play to your CyanogenMod installation) from http://goo.im/gapps, make sure you pick the version for “CyanogenMod 10.0.x” and download it to c:/tmp/samsung/gapps-jb-20121011-signed.zip

  7. Plug your Samsung Galaxy Tab 10.1 into your computer using the USB cable and copy the following files to the root of the device.

  • c:/tmp/samsun/tabrooteasy/Samsung_Galaxy_Tab_10.1_root.zip
  • c:/tmp/samsung/cm-10-20121216-NIGHTLY-p4.zip
  • c:/tmp/samsung/gapps-jb-20121011-signed.zip

Installing ClockworkMod 5.5.0.4 and rooting your Samsung Galaxy Tab 10.1

this is what we will use to backup/wipe your device and install CyanogenMod (Android 4.1.2) and Google Apps. It will also be needed to restore your device in case you brick it.

Launch c:/tmp/samsung/Tab10.1WifiRecovery/Odin3 v1.85.exe, click on the “PDA” button in the bottom right section of the application and choose to open the file c:/tmp/samsung/recovery.tar.md5 (this is the ClockworkMod 5.5.0.4 application), lastly click the “START” button and it will install the ClockworkMod application to your Galaxy Tab 10.1.

Rooting your Galaxy Tab 10.1

important: Rooting your Samsung Galaxy Tab will void your guarantee.

Start your Samsung Galaxy Tab by holding down both the Power button and Volume down button until you see a selection menu. Press the volume down button once to select the left item and then press volume up to launch ClockworkMod.

  1. Use the volume up/down keys to mark “install zip from sdcard” and press the power button.

  2. Select “choose zip from sdcard” and press the power button.

  3. Now select the Samsung_Galaxy_Tab_10.1_root.zip file you copied over earlier and press the power button, confirm the installation by choosing “yes..” and press the power button.

Reboot your Galaxy Tab 10.1 when the install has completed, it is now rooted.

Installing CyanogenMod 10 (Android 4.1.2) and Google Apps.

important: you should be aware that this will wipe all of your user-data and apps from your Samsung Galaxy Tab.

Start your Samsung Galaxy Tab by holding down both the Power button and Volume down button until you see a selection menu. Press the volume down button once to select the left item and then press volume up to launch ClockworkMod.

important: you can now backup your current install of Android on your Samsung Galaxy Tab 10.1. you do this by navigating to “backup and restore” with the volume buttons and the pressing the power button. navigate to “backup” and press the power button again. it will now create a backup of the current install on your Samsung Galaxy Tab 10.1

now to continue on to installing CyanogenMod

  1. Use the volume up/down keys to mark “wipe data/factory reset” and press the power button. confirm the wipe by choosing “yes..” and press the power button again.

  2. Use the volume up/down keys to mark “install zip from sdcard” and press the power button.

  3. Select “choose zip from sdcard” and press the power button.

  4. Select the cm-10-20121216-NIGHTLY-p4.zip file you copied over earlier and press the power button, confirm the installation by choosing “yes..” and press the power button.

  5. Repeat steps 2 - 4 but choose to install gapps-jb-20121011-signed.zip instead.

Reboot your Samsung Galaxy Tab 10.1 when the last install is complete and it will now be running Cyanogenmod 10 (Android 4.1.2) with access to Google Play, yay!