Sunday, February 5, 2017

OpenGL 4 with OpenTK in C# Part 8: Drawing multiple objects

In this post we will look at how to reuse the Vertex Array and Buffers to draw the same model multiple times.

This is part 8 of my series on OpenGL4 with OpenTK.
For other posts in this series:
OpenGL 4 with OpenTK in C# Part 1: Initialize the GameWindow
OpenGL 4 with OpenTK in C# Part 2: Compiling shaders and linking them
OpenGL 4 with OpenTK in C# Part 3: Passing data to shaders
OpenGL 4 with OpenTK in C# Part 4: Refactoring and adding error handling
OpenGL 4 with OpenTK in C# Part 5: Buffers and Triangle
OpenGL 4 with OpenTK in C# Part 6: Rotations and Movement of objects
OpenGL 4 with OpenTK in C# Part 7: Vectors and Matrices
OpenGL 4 with OpenTK in C# Part 8: Drawing multiple objects
OpenGL 4 with OpenTK in C# Part 9: Texturing
OpenGL 4 with OpenTK in C# Part 10: Asteroid Invaders
Basic bullet movement patterns in Asteroid Invaders
OpenGL 4 with OpenTK in C# Part 11: Mipmap
OpenGL 4 with OpenTK in C# Part 12: Basic Moveable Camera
OpenGL 4 with OpenTK in C# Part 13: IcoSphere
OpenGL 4 with OpenTK in C# Part 14: Basic Text
OpenGL 4 with OpenTK in C# Part 15: Object picking by mouse

As stated in the previous post, I am in no way an expert in OpenGL. I write these posts as a way to learn and if someone else finds these posts useful then all the better :)
If you think that the progress is slow, then know that I am a slow learner :P
This part will build upon the game window and shaders from part 6..

Projection Matrix

As a starter, in the previous post the cube looked a little odd. It had no real perspective and when the window was rescaled it didn't behave as it should have. I.e. it got out of shape.
To solve this, we shall add a Projection Matrix to our solution.
In our vertex shader, we will add another uniform matrix in addition to the modelView matrix we already have as follows:
#version 450 core

layout (location = 0) in vec4 position;
layout(location = 1) in vec4 color;

out vec4 vs_color;

layout(location = 20) uniform  mat4 projection;
layout (location = 21) uniform  mat4 modelView;

void main(void)
{
 gl_Position = projection * modelView * position;
 vs_color = color;
}

Be sure to get the order of multiplications correct or else things will look very very strange.
In our GameWindow, lets add the following method to create this projection matrix.
private void CreateProjection()
{
            
    var aspectRatio = (float)Width/Height;
    _projectionMatrix = Matrix4.CreatePerspectiveFieldOfView(
        60*((float) Math.PI/180f), // field of view angle, in radians
        aspectRatio,                // current window aspect ratio
        0.1f,                       // near plane
        4000f);                     // far plane
}
Basically we tell OpenTKs Matrix4 to create this matrix for us. And we want to supply the angle of the field of view together with the window aspect ratio and the near and far clipping planes.
Changing the angle is a cheap mans zoom of sorts, the aspect ratio helps keep things in shape even if we drag the window to strange sizes and the near and far clipping determine how close or far away an object can be and still be drawn on screen.
We want to call the CreateProjection from both the OnLoad and OnResize event handlers.
Then in our OnRenderFrame add a call to
GL.UniformMatrix4(20, false, ref _projectionMatrix);
And we should be set.

Drawing multiple objects

So, now that we have gone through the projection matrix that should probably have been covered in an earlier post, but I did not know it at the time of writing we can finally start with the topic of this post: Drawing multiple objects on screen.

Lets initialize a few different RenderObjects in out OnLoad method. As the only model we have at the moment is a cube, lets create some different colored ones so that we know the difference.
In reality these would probably be different models that look differently all together. But for now lets take what we have. But you can imagine that HotPink is a car, BlueViolet is a truck, Red is a Motorcycle and LimeGreen is a lawnmower ;)
protected override void OnLoad(EventArgs e)
{
    VSync = VSyncMode.Off;
    CreateProjection();
    _renderObjects.Add(new RenderObject(ObjectFactory.CreateSolidCube(0.2f, Color4.HotPink)));
    _renderObjects.Add(new RenderObject(ObjectFactory.CreateSolidCube(0.2f, Color4.BlueViolet)));
    _renderObjects.Add(new RenderObject(ObjectFactory.CreateSolidCube(0.2f, Color4.Red)));
    _renderObjects.Add(new RenderObject(ObjectFactory.CreateSolidCube(0.2f, Color4.LimeGreen)));

    CursorVisible = true;

    _program = CreateProgram();
    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
    GL.PatchParameter(PatchParameterInt.PatchVertices, 3);
    GL.Enable(EnableCap.DepthTest);
    Closed += OnClosed;
}

So, now we have 4 different RenderObjects created, each containing Vertex Arrays and Buffers. Next step is to draw them on the screen. But we don't want to just draw one of each, lets draw a bunch.
protected override void OnRenderFrame(FrameEventArgs e)
{
    _time += e.Time;
    Title = $"{_title}: (Vsync: {VSync}) FPS: {1f / e.Time:0}";
    GL.ClearColor(_backColor);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

    GL.UseProgram(_program);
    GL.UniformMatrix4(20, false, ref _projectionMatrix);
    float c = 0f;
    foreach (var renderObject in _renderObjects)
    {
        renderObject.Bind();
        for (int i = 0; i < 5; i++)
        {
            var k = i + (float)(_time * (0.05f + (0.1 * c)));
            var t2 = Matrix4.CreateTranslation(
                (float)(Math.Sin(k * 5f) * (c + 0.5f)),
                (float)(Math.Cos(k * 5f) * (c + 0.5f)),
                -2.7f);
            var r1 = Matrix4.CreateRotationX(k * 13.0f + i);
            var r2 = Matrix4.CreateRotationY(k * 13.0f + i);
            var r3 = Matrix4.CreateRotationZ(k * 3.0f + i);
            var modelView = r1 * r2 * r3 * t2;
            GL.UniformMatrix4(21, false, ref modelView);
            renderObject.Render();
        }
        c += 0.3f;
    }
    GL.PointSize(10);
    SwapBuffers();
}
The projection matrix will stay the same during the whole frame, so we need only to set it once before the render loop.
Then for each model that we loaded (different colored cube in our case), lets apply some transforms and rotations, each object gets a unique model view matrix that we set.
Note that the same RenderObject is bound once but rendered multiple times, just with different translations.
In the RenderObject, we need to split the old Render method into a Render and Bind method for this to work.
public void Bind()
{
    GL.BindVertexArray(_vertexArray);
}
public void Render()
{
    GL.DrawArrays(PrimitiveType.Triangles, 0, _verticeCount);
}

The end results should be like this:


For the full source at the end of part 8, go to: https://github.com/eowind/dreamstatecoding

Hope this helps someone out there :)
No cat video today either, it seems to be a every other post thing currently.


Friday, February 3, 2017

OpenGL 4 with OpenTK in C# Part 7: Vectors and Matrices


In this post we will look at vector and matrix math with OpenTK.

This is part 7 of my series on OpenGL4 with OpenTK.
For other posts in this series:
OpenGL 4 with OpenTK in C# Part 1: Initialize the GameWindow
OpenGL 4 with OpenTK in C# Part 2: Compiling shaders and linking them
OpenGL 4 with OpenTK in C# Part 3: Passing data to shaders
OpenGL 4 with OpenTK in C# Part 4: Refactoring and adding error handling
OpenGL 4 with OpenTK in C# Part 5: Buffers and Triangle
OpenGL 4 with OpenTK in C# Part 6: Rotations and Movement of objects
OpenGL 4 with OpenTK in C# Part 7: Vectors and Matrices
OpenGL 4 with OpenTK in C# Part 8: Drawing multiple objects
OpenGL 4 with OpenTK in C# Part 9: Texturing
OpenGL 4 with OpenTK in C# Part 10: Asteroid Invaders
Basic bullet movement patterns in Asteroid Invaders
OpenGL 4 with OpenTK in C# Part 11: Mipmap
OpenGL 4 with OpenTK in C# Part 12: Basic Moveable Camera
OpenGL 4 with OpenTK in C# Part 13: IcoSphere
OpenGL 4 with OpenTK in C# Part 14: Basic Text
OpenGL 4 with OpenTK in C# Part 15: Object picking by mouse

As stated in the previous post, I am in no way an expert in OpenGL, or math. I write these posts as a way to learn and if someone else finds these posts useful then all the better :)
If you think that the progress is slow, then know that I am a slow learner :P
This part will not really build on any previous code, we will instead look at the VectorN and MatrixN structs in OpenTK and see how to do basic calculations with help of their methods.

Vectors

Lets start with a definition.
In mathematics, physics, and engineering, a Euclidean vector (sometimes called a geometric or spatial vector, or—as here—simply a vector) is a geometric object that has magnitude (or length) and direction - wikipedia
So the difference between a point (x, y, z) and a vector (x, y, z) is that where the point is just a point in space, the vector has its magnitude (distance from origin (0, 0, 0))
The distance can be calculated with following method:
public static double Magnitude(Vector3 v)
{
    return Math.Sqrt(Math.Pow(v.X, 2.0) + Math.Pow(v.Y, 2.0) + Math.Pow(v.Z, 2.0));
}
As we are using OpenTK, it already provides this for us.
var v = new Vector3(10, 10, 10);
v.Length;
So a point in space (x, y, z) can represent both a point, a vector and a vertex. This is great as we have the need them all in 3D.

Unit vectors

Unit vectors always have the magnitude 1.0.
One great usage for them is to store only direction, without the magnitude. They are also great for calculations that include the magnitude as it will always be 1.
In OpenTK there are 2 ways to normalize and 1 way to estimate a normalization if accuracy is not priority.
[TestMethod]
public void VectorTest_NormalizeVsNormalized()
{
    var normalize = new Vector4(2, 2, 2, 2);
    var fast = new Vector4(2, 2, 2, 2);
    var normalized = normalize.Normalized(); // returns a copy that is normalized
    normalize.Normalize(); // normalizes this vector
    fast.NormalizeFast(); // estimates a normalized vector, inaccurate
    Assert.AreEqual(normalize, normalized);
    // AreEqual fails Expected:<(0,5; 0,5; 0,5; 0,5)>. Actual:<(0,4991541; 0,4991541; 0,4991541; 0,4991541)>
    Assert.AreNotEqual(normalized, fast);  
}

Scalar multiplication
If you have a unit vector with a direction, you can scale it by multiplying it with a scalar value, in the example below we scale scale it with the original vectors length to get a vector that is equal to the original.
[TestMethod]
public void VectorTest_NormalizeMultipliedByLength()
{
    var original = new Vector4(2, 2, 2, 2);
    var normalized = original.Normalized();
    var scaled = normalized * original.Length;
    Assert.AreEqual(original, scaled);
}

Vector operations

Vectors can be added, subtracted multiplied just as any numerical value.
[TestMethod]
public void VectorTest_Addition()
{
    var v1 = new Vector4(2, 2, 2, 1);
    var v2 = new Vector4(2, 2, 2, 1);
    var actual = v1 + v2;
    Assert.AreEqual(4, actual.X);
    Assert.AreEqual(4, actual.Y);
    Assert.AreEqual(4, actual.Z);
    Assert.AreEqual(2, actual.W);
}
[TestMethod]
public void VectorTest_Subtraction()
{
    var v1 = new Vector4(2, 2, 2, 1);
    var v2 = new Vector4(2, 2, 2, 1);
    var actual = v1 - v2;
    Assert.AreEqual(0, actual.X);
    Assert.AreEqual(0, actual.Y);
    Assert.AreEqual(0, actual.Z);
    Assert.AreEqual(0, actual.W);
}
[TestMethod]
public void VectorTest_Multiplication()
{
    var v1 = new Vector4(2, 2, 2, 1);
    var v2 = new Vector4(2, 2, 2, 1);
    var actual = v1 * v2;
    Assert.AreEqual(4, actual.X);
    Assert.AreEqual(4, actual.Y);
    Assert.AreEqual(4, actual.Z);
    Assert.AreEqual(1, actual.W);
}
Vectors can only be divided with scalars, don't ask me why. Tried to understand a thread on it over at Physics Stack Exchange.
[TestMethod]
public void VectorTest_Division()
{
    var v1 = new Vector4(2, 2, 2, 1);
    var actual = v1 / 2;
    Assert.AreEqual(1, actual.X);
    Assert.AreEqual(1, actual.Y);
    Assert.AreEqual(1, actual.Z);
    Assert.AreEqual(0.5f, actual.W);
}

Dot Product (inner product)
Geometrically, it is the product of the Euclidean magnitudes of the two vectors and the cosine of the angle between them -wikipedia
If the two vectors are unit vectors, the value will be between -1 and 1, i.e. directly equal to the cosine of the angle between them.
Ok, so what will we use this for? Well, lightning..
So, how to do it
[TestMethod]
public void VectorTest_DotProduct()
{
    var v1 = new Vector2(1, 1).Normalized();
    var v2 = new Vector2(0, 1).Normalized();
    var actual = Vector2.Dot(v1, v2);
    // we know that the angle is 45 degrees, just need the radians
    Assert.AreEqual((float)(Math.Cos(45 * (Math.PI / 180f))), actual);
}
The order of vectors does not matter for the dot product.

Cross Product (vector product)
Lets check wikipedia here as well
Given two linearly independent vectors a and b, the cross product, a × b, is a vector that is perpendicular to both a and b and therefore normal to the plane containing them -wikipedia
The order of vectors matters for the cross product, if you change the order the resulting vector would be inversed.
[TestMethod]
public void VectorTest_CrossProduct()
{
    var v1 = new Vector3(1, 0, 0).Normalized();
    var v2 = new Vector3(0, 1, 0).Normalized();
    var actual = Vector3.Cross(v1, v2);

    Assert.AreEqual(0, actual.X);
    Assert.AreEqual(0, actual.Y);
    Assert.AreEqual(1, actual.Z);
}
[TestMethod]
public void VectorTest_CrossProduct_Inverse()
{
    var v1 = new Vector3(1, 0, 0).Normalized();
    var v2 = new Vector3(0, 1, 0).Normalized();
    var actual = Vector3.Cross(v2, v1);

    Assert.AreEqual(0, actual.X);
    Assert.AreEqual(0, actual.Y);
    Assert.AreEqual(-1, actual.Z);
}

Matrices

In mathematics, a matrix (plural matrices) is a rectangular array of numbers, symbols, or expressions, arranged in rows and columns. -wikipedia
We saw in the previous post that matrices can be really handy when working with 3D when we did the rotations and translations (move) of the object.

The reason we are using a Matrix4 object to store our transformation matrices in is because they can store both the rotation part and the translation part in the same structure.

Identity

Basically a square matrix with its diagonal set to 1 and the rest to 0. It is its own inverse. For more info, wikipedia.
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
In OpenTK
var m = Matrix4.Identity;

Translation

1 0 0 tx
0 1 0 ty
0 0 1 tz
0 0 0 1
Built from a identity matrix, the last column contains the x, y, z values of where you want to move the vertex.
[TestMethod]
public void MatrixTest_Translate()
{
    var translate = Matrix4.CreateTranslation(1, 1, 1);

    var v1 = new Vector4(0, 0, 0, 1);
    var actual = Vector4.Transform(v1, translate);
    Assert.AreEqual(1, actual.X);
    Assert.AreEqual(1, actual.Y);
    Assert.AreEqual(1, actual.Z);
}
Or in a shader, just v * m as we did in previous post.

Rotation

Rotation.X
1 0 0 0
0 cos(a) sin(a) 0
0 -sin(a) cos(a) 0
0 0 0 1
Rotation.Y
cos(a) 0 -sin(a) 0
0 1 0 0
sin(a) 0 cos(a) 0
0 0 0 1
Rotation.Z
cos(a) -sin(a) 0 0
sin(a) cos(a) 0 0
0 0 1 0
0 0 0 1
Where a being the angle.
All these can be multiplied together to form a rotation matrix for all x, y, z.
var rx = Matrix4.CreateRotationX(k * 13.0f);
var ry = Matrix4.CreateRotationY(k * 13.0f);
var rz = Matrix4.CreateRotationZ(k * 3.0f);
var rotation = rx*ry*rz;
Not going to write a test for rotation just now :)

Scaling

sx 0 0 0
0 sy 0 0
0 0 sz 0
0 0 0 1
To scale an object, we generate a scaling matrix that is basically a diagonal with the x, y and z scaling factors set for the 3 first items.
[TestMethod]
public void MatrixTest_Scale()
{
    var translate = Matrix4.CreateScale(2, 4, 8);

    var v1 = new Vector4(2, 2, 2, 1);
    var actual = Vector4.Transform(v1, translate);
    Assert.AreEqual(4, actual.X);
    Assert.AreEqual(8, actual.Y);
    Assert.AreEqual(16, actual.Z);
}

So this has been a long post, at least I am starting to get a hang of things. Hopefully this has helped someone out there.
To get you in a better mood after all the theory, here is a GIF of 2 of our cats fighting.. Again.

Thursday, February 2, 2017

OpenGL 4 with OpenTK in C# Part 6: Rotations and Movement of objects


In this post we will look at how to manipulate an object by rotating and moving it around.

This is part 6 of my series on OpenGL4 with OpenTK.
For other posts in this series:
OpenGL 4 with OpenTK in C# Part 1: Initialize the GameWindow
OpenGL 4 with OpenTK in C# Part 2: Compiling shaders and linking them
OpenGL 4 with OpenTK in C# Part 3: Passing data to shaders
OpenGL 4 with OpenTK in C# Part 4: Refactoring and adding error handling
OpenGL 4 with OpenTK in C# Part 5: Buffers and Triangle
OpenGL 4 with OpenTK in C# Part 6: Rotations and Movement of objects
OpenGL 4 with OpenTK in C# Part 7: Vectors and Matrices
OpenGL 4 with OpenTK in C# Part 8: Drawing multiple objects
OpenGL 4 with OpenTK in C# Part 9: Texturing
OpenGL 4 with OpenTK in C# Part 10: Asteroid Invaders
Basic bullet movement patterns in Asteroid Invaders
OpenGL 4 with OpenTK in C# Part 11: Mipmap
OpenGL 4 with OpenTK in C# Part 12: Basic Moveable Camera
OpenGL 4 with OpenTK in C# Part 13: IcoSphere
OpenGL 4 with OpenTK in C# Part 14: Basic Text
OpenGL 4 with OpenTK in C# Part 15: Object picking by mouse

As stated in the previous post, I am in no way an expert in OpenGL. I write these posts as a way to learn and if someone else finds these posts useful then all the better :)
If you think that the progress is slow, then know that I am a slow learner :P
This part will build upon the game window and shaders from the previous post.

3D Cube

Ah, the old cube that is used in all tutorials is back.
Lets create a helper class, ObjectFactory, that emits the vertices for a cube (single color)
public class ObjectFactory
{
 public static Vertex[] CreateSolidCube(float side, Color4 color)
 {
  side = side/2f; // half side - and other half
  Vertex[] vertices =
  {
   new Vertex(new Vector4(-side, -side, -side, 1.0f),   color),
   new Vertex(new Vector4(-side, -side, side, 1.0f),    color),
   new Vertex(new Vector4(-side, side, -side, 1.0f),    color),
   new Vertex(new Vector4(-side, side, -side, 1.0f),    color),
   new Vertex(new Vector4(-side, -side, side, 1.0f),    color),
   new Vertex(new Vector4(-side, side, side, 1.0f),     color),

   new Vertex(new Vector4(side, -side, -side, 1.0f),    color),
   new Vertex(new Vector4(side, side, -side, 1.0f),     color),
   new Vertex(new Vector4(side, -side, side, 1.0f),     color),
   new Vertex(new Vector4(side, -side, side, 1.0f),     color),
   new Vertex(new Vector4(side, side, -side, 1.0f),     color),
   new Vertex(new Vector4(side, side, side, 1.0f),      color),

   new Vertex(new Vector4(-side, -side, -side, 1.0f),   color),
   new Vertex(new Vector4(side, -side, -side, 1.0f),    color),
   new Vertex(new Vector4(-side, -side, side, 1.0f),    color),
   new Vertex(new Vector4(-side, -side, side, 1.0f),    color),
   new Vertex(new Vector4(side, -side, -side, 1.0f),    color),
   new Vertex(new Vector4(side, -side, side, 1.0f),     color),

   new Vertex(new Vector4(-side, side, -side, 1.0f),    color),
   new Vertex(new Vector4(-side, side, side, 1.0f),     color),
   new Vertex(new Vector4(side, side, -side, 1.0f),     color),
   new Vertex(new Vector4(side, side, -side, 1.0f),     color),
   new Vertex(new Vector4(-side, side, side, 1.0f),     color),
   new Vertex(new Vector4(side, side, side, 1.0f),      color),

   new Vertex(new Vector4(-side, -side, -side, 1.0f),   color),
   new Vertex(new Vector4(-side, side, -side, 1.0f),    color),
   new Vertex(new Vector4(side, -side, -side, 1.0f),    color),
   new Vertex(new Vector4(side, -side, -side, 1.0f),    color),
   new Vertex(new Vector4(-side, side, -side, 1.0f),    color),
   new Vertex(new Vector4(side, side, -side, 1.0f),     color),

   new Vertex(new Vector4(-side, -side, side, 1.0f),    color),
   new Vertex(new Vector4(side, -side, side, 1.0f),     color),
   new Vertex(new Vector4(-side, side, side, 1.0f),     color),
   new Vertex(new Vector4(-side, side, side, 1.0f),     color),
   new Vertex(new Vector4(side, -side, side, 1.0f),     color),
   new Vertex(new Vector4(side, side, side, 1.0f),      color),
  };
  return vertices;
 }
}
And replace the triangle initialization with a call to it in the OnLoad method in the GameWindow
protected override void OnLoad(EventArgs e)
{
    Vertex[] vertices = ObjectFactory.CreateSolidCube(0.2f, Color4.HotPink);
    _renderObjects.Add(new RenderObject(vertices));

    CursorVisible = true;

    _program = CreateProgram();
    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
    GL.PatchParameter(PatchParameterInt.PatchVertices, 3);
    GL.Enable(EnableCap.DepthTest);
    Closed += OnClosed;
}

This should result in something like the following;
So nothing fancy at all. As you can see the lines are drawn thanks to the following line in the OnLoad, it was PolygonMode.Fill before and now it says PolygonMode.Line.
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
and each side of the cube is drawn as 2 triangles.
So lets get this cube moving

Rotating

I am really bad at math. Thankfully a lot of this is provided by OpenTK.

Matrices

We will use matrices to rotate and move (translate) objects in 3D.
Our first goal is to create a model=>view matrix. The purpose of this matrix is to transform the coordinates of each vertex from model space (i.e. what we create above for the cube) to coordinates in the view space.

Vertex Shader
First lets update our vertex shader so that it can take a matrix input and then transform the vertex position with it.
#version 450 core

layout (location = 0) in vec4 position;
layout(location = 1) in vec4 color;

out vec4 vs_color;

layout (location = 20) uniform  mat4 modelView;

void main(void)
{
 gl_Position = modelView * position;
 vs_color = color;
}
Note the uniform keyword here, what it says is that this is no ordinary attribute that could differ between vertices but constant for this batch.

Having done so, lets add some rotations to the cube so that we can see all sides of it.
In our OnUpdateFrame, lets add a little more then just the keyboard handler
private Matrix4 _modelView;
protected override void OnUpdateFrame(FrameEventArgs e)
{
 _time += e.Time;
 var k = (float)_time*0.05f;
 var r1 = Matrix4.CreateRotationX(k * 13.0f);
 var r2 = Matrix4.CreateRotationY(k * 13.0f);
 var r3 = Matrix4.CreateRotationZ(k * 3.0f);
 _modelView = r1 * r2 * r3;

 HandleKeyboard();
}
And update our OnRenderFrame to provide the new matrix to our shader with the GL.UniformMatrix4 command.
protected override void OnRenderFrame(FrameEventArgs e)
{
    Title = $"{_title}: (Vsync: {VSync}) FPS: {1f / e.Time:0}";
    GL.ClearColor(_backColor);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

    GL.UseProgram(_program);
    GL.UniformMatrix4(20,              // match the layout location in the shader
                      false,           // transpose
                      ref _modelView); // our matrix
    foreach (var renderObject in _renderObjects)
    {
        renderObject.Render();
    }
    SwapBuffers();
}

Output should be something like this:

Translating (moving)

Moving the object around is the next step, this we will be doing with the help of Translations.
Add the following to the OnUpdateFrame method to make the object circle around the center of the screen at a leisurely pace.
var t1 = Matrix4.CreateTranslation(
    (float) (Math.Sin(k * 5f) * 0.5f),
    (float) (Math.Cos(k * 5f) * 0.5f),
    0f);
_modelView = r1*r2*r3*t1;

Should give the following result

Be aware that the order of the multiplications is really important,
_modelView = t1*r1*r2*r3;
Yields in a totally different experience



For the full source at the end of part 6, go to: https://github.com/eowind/dreamstatecoding

Hope this helps someone out there :)
I must sadly inform that there is no cat video for this part, hopefully they will do something fun in front of the camera until next post.

Until next time: Work to Live, Don’t Live to Work